bugfixes
This commit is contained in:
parent
95bf0fdd79
commit
c595bd29f8
BIN
backend/dist/nsfwapp-linux-amd64
vendored
BIN
backend/dist/nsfwapp-linux-amd64
vendored
Binary file not shown.
BIN
backend/dist/nsfwapp.exe
vendored
BIN
backend/dist/nsfwapp.exe
vendored
Binary file not shown.
BIN
backend/dist/nsfwapp_amd64.deb
vendored
BIN
backend/dist/nsfwapp_amd64.deb
vendored
Binary file not shown.
@ -218,6 +218,9 @@ type PoseInteraction = {
|
|||||||
type: 'keypoint'
|
type: 'keypoint'
|
||||||
personIndex: number
|
personIndex: number
|
||||||
keypointIndex: number
|
keypointIndex: number
|
||||||
|
startClientX: number
|
||||||
|
startClientY: number
|
||||||
|
moved: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type PoseKeypointPlacement = {
|
type PoseKeypointPlacement = {
|
||||||
@ -225,6 +228,11 @@ type PoseKeypointPlacement = {
|
|||||||
keypointName: string
|
keypointName: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PoseKeypointAction = {
|
||||||
|
personIndex: number
|
||||||
|
keypointIndex: number
|
||||||
|
}
|
||||||
|
|
||||||
type MagnifierState = {
|
type MagnifierState = {
|
||||||
visible: boolean
|
visible: boolean
|
||||||
clientX: number
|
clientX: number
|
||||||
@ -366,6 +374,7 @@ const POSE_RELIABLE_KEYPOINT_MIN_CONFIDENCE = 0.20
|
|||||||
const POSE_RELIABLE_MIN_SCORE = 0.30
|
const POSE_RELIABLE_MIN_SCORE = 0.30
|
||||||
const POSE_RELIABLE_MIN_KEYPOINTS = 6
|
const POSE_RELIABLE_MIN_KEYPOINTS = 6
|
||||||
const POSE_RELIABLE_MIN_QUALITY = 0.45
|
const POSE_RELIABLE_MIN_QUALITY = 0.45
|
||||||
|
const POSE_KEYPOINT_TAP_MOVE_THRESHOLD_PX = 6
|
||||||
const POSE_UNRELIABLE_COLOR = '#94a3b8'
|
const POSE_UNRELIABLE_COLOR = '#94a3b8'
|
||||||
const POSE_PERSON_COLORS = ['#38bdf8', '#a78bfa', '#34d399', '#f59e0b', '#fb7185']
|
const POSE_PERSON_COLORS = ['#38bdf8', '#a78bfa', '#34d399', '#f59e0b', '#fb7185']
|
||||||
const POSE_SKELETON_EDGES: Array<readonly [string, string]> = [
|
const POSE_SKELETON_EDGES: Array<readonly [string, string]> = [
|
||||||
@ -4241,6 +4250,7 @@ export default function TrainingTab(props: {
|
|||||||
setActivePosePersonIndex(null)
|
setActivePosePersonIndex(null)
|
||||||
setPendingPoseKeypoint(null)
|
setPendingPoseKeypoint(null)
|
||||||
setHoveredPoseKeypoint(null)
|
setHoveredPoseKeypoint(null)
|
||||||
|
setSelectedPoseKeypointAction(null)
|
||||||
if (poseKeypointMapAnimationFrameRef.current !== null) {
|
if (poseKeypointMapAnimationFrameRef.current !== null) {
|
||||||
cancelAnimationFrame(poseKeypointMapAnimationFrameRef.current)
|
cancelAnimationFrame(poseKeypointMapAnimationFrameRef.current)
|
||||||
poseKeypointMapAnimationFrameRef.current = null
|
poseKeypointMapAnimationFrameRef.current = null
|
||||||
@ -4401,6 +4411,8 @@ export default function TrainingTab(props: {
|
|||||||
const [poseInteraction, setPoseInteraction] = useState<PoseInteraction | null>(null)
|
const [poseInteraction, setPoseInteraction] = useState<PoseInteraction | null>(null)
|
||||||
const [pendingPoseKeypoint, setPendingPoseKeypoint] = useState<PoseKeypointPlacement | null>(null)
|
const [pendingPoseKeypoint, setPendingPoseKeypoint] = useState<PoseKeypointPlacement | null>(null)
|
||||||
const [hoveredPoseKeypoint, setHoveredPoseKeypoint] = useState<PoseKeypointPlacement | null>(null)
|
const [hoveredPoseKeypoint, setHoveredPoseKeypoint] = useState<PoseKeypointPlacement | null>(null)
|
||||||
|
const [selectedPoseKeypointAction, setSelectedPoseKeypointAction] =
|
||||||
|
useState<PoseKeypointAction | null>(null)
|
||||||
const [poseKeypointMapView, setPoseKeypointMapView] = useState<PoseKeypointMapView>('body')
|
const [poseKeypointMapView, setPoseKeypointMapView] = useState<PoseKeypointMapView>('body')
|
||||||
const [poseKeypointMapViewBoxValue, setPoseKeypointMapViewBoxValue] =
|
const [poseKeypointMapViewBoxValue, setPoseKeypointMapViewBoxValue] =
|
||||||
useState(POSE_BODY_MAP_VIEW_BOX)
|
useState(POSE_BODY_MAP_VIEW_BOX)
|
||||||
@ -4560,6 +4572,7 @@ export default function TrainingTab(props: {
|
|||||||
setActivePosePersonIndex(null)
|
setActivePosePersonIndex(null)
|
||||||
setPendingPoseKeypoint(null)
|
setPendingPoseKeypoint(null)
|
||||||
setHoveredPoseKeypoint(null)
|
setHoveredPoseKeypoint(null)
|
||||||
|
setSelectedPoseKeypointAction(null)
|
||||||
|
|
||||||
poseFaceImagePanGestureRef.current = null
|
poseFaceImagePanGestureRef.current = null
|
||||||
poseFaceImagePanCenterRef.current = null
|
poseFaceImagePanCenterRef.current = null
|
||||||
@ -7369,14 +7382,38 @@ export default function TrainingTab(props: {
|
|||||||
: clampedPos
|
: clampedPos
|
||||||
|
|
||||||
if (poseInteraction) {
|
if (poseInteraction) {
|
||||||
|
const pointerDistance = Math.hypot(
|
||||||
|
snapshot.clientX - poseInteraction.startClientX,
|
||||||
|
snapshot.clientY - poseInteraction.startClientY
|
||||||
|
)
|
||||||
|
const hasMoved =
|
||||||
|
poseInteraction.moved ||
|
||||||
|
pointerDistance > POSE_KEYPOINT_TAP_MOVE_THRESHOLD_PX
|
||||||
|
|
||||||
|
if (!hasMoved) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!poseInteraction.moved) {
|
||||||
|
const nextInteraction = {
|
||||||
|
...poseInteraction,
|
||||||
|
moved: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
poseInteractionRef.current = nextInteraction
|
||||||
|
setPoseInteraction(nextInteraction)
|
||||||
|
setSelectedPoseKeypointAction(null)
|
||||||
|
}
|
||||||
|
|
||||||
markManualCorrection()
|
markManualCorrection()
|
||||||
|
|
||||||
let nextPoseMagnifier: MagnifierState | null = null
|
let nextPoseMagnifier: MagnifierState | null = null
|
||||||
|
const activePoseInteraction = poseInteractionRef.current ?? poseInteraction
|
||||||
|
|
||||||
setCorrection((prev) => {
|
setCorrection((prev) => {
|
||||||
const persons = clonePosePersons(prev.posePersons)
|
const persons = clonePosePersons(prev.posePersons)
|
||||||
const person = persons[poseInteraction.personIndex]
|
const person = persons[activePoseInteraction.personIndex]
|
||||||
const point = person?.keypoints?.[poseInteraction.keypointIndex]
|
const point = person?.keypoints?.[activePoseInteraction.keypointIndex]
|
||||||
|
|
||||||
if (!person || !point) {
|
if (!person || !point) {
|
||||||
return prev
|
return prev
|
||||||
@ -7402,15 +7439,15 @@ export default function TrainingTab(props: {
|
|||||||
box: poseBoxFromKeypoints({
|
box: poseBoxFromKeypoints({
|
||||||
...person,
|
...person,
|
||||||
keypoints: person.keypoints.map((candidate, index) =>
|
keypoints: person.keypoints.map((candidate, index) =>
|
||||||
index === poseInteraction.keypointIndex ? nextPoint : candidate
|
index === activePoseInteraction.keypointIndex ? nextPoint : candidate
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
keypoints: person.keypoints.map((candidate, index) =>
|
keypoints: person.keypoints.map((candidate, index) =>
|
||||||
index === poseInteraction.keypointIndex ? nextPoint : candidate
|
index === activePoseInteraction.keypointIndex ? nextPoint : candidate
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
persons[poseInteraction.personIndex] = nextPerson
|
persons[activePoseInteraction.personIndex] = nextPerson
|
||||||
|
|
||||||
const next: CorrectionState = {
|
const next: CorrectionState = {
|
||||||
...prev,
|
...prev,
|
||||||
@ -7692,6 +7729,7 @@ export default function TrainingTab(props: {
|
|||||||
y: clamp01(rawPos.y),
|
y: clamp01(rawPos.y),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
setSelectedPoseKeypointAction(null)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7822,6 +7860,17 @@ export default function TrainingTab(props: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (activePoseInteraction) {
|
if (activePoseInteraction) {
|
||||||
|
if (activePoseInteraction.moved) {
|
||||||
|
setSelectedPoseKeypointAction(null)
|
||||||
|
} else {
|
||||||
|
setSelectedPoseKeypointAction({
|
||||||
|
personIndex: activePoseInteraction.personIndex,
|
||||||
|
keypointIndex: activePoseInteraction.keypointIndex,
|
||||||
|
})
|
||||||
|
setPendingPoseKeypoint(null)
|
||||||
|
setActivePosePersonIndex(activePoseInteraction.personIndex)
|
||||||
|
}
|
||||||
|
|
||||||
setPoseInteraction(null)
|
setPoseInteraction(null)
|
||||||
clearBoxGestureRefs()
|
clearBoxGestureRefs()
|
||||||
return
|
return
|
||||||
@ -8007,6 +8056,18 @@ export default function TrainingTab(props: {
|
|||||||
}
|
}
|
||||||
return current
|
return current
|
||||||
})
|
})
|
||||||
|
|
||||||
|
setSelectedPoseKeypointAction((current) => {
|
||||||
|
if (!current) return null
|
||||||
|
if (current.personIndex === personIndex) return null
|
||||||
|
if (current.personIndex > personIndex) {
|
||||||
|
return {
|
||||||
|
...current,
|
||||||
|
personIndex: current.personIndex - 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return current
|
||||||
|
})
|
||||||
}, [markManualCorrection])
|
}, [markManualCorrection])
|
||||||
|
|
||||||
const addPosePerson = useCallback(() => {
|
const addPosePerson = useCallback(() => {
|
||||||
@ -8031,7 +8092,16 @@ export default function TrainingTab(props: {
|
|||||||
setActiveBoxIndex(null)
|
setActiveBoxIndex(null)
|
||||||
setActivePosePersonIndex(nextPersonIndex)
|
setActivePosePersonIndex(nextPersonIndex)
|
||||||
setPendingPoseKeypoint(null)
|
setPendingPoseKeypoint(null)
|
||||||
|
setSelectedPoseKeypointAction(null)
|
||||||
switchPoseKeypointMapView('body')
|
switchPoseKeypointMapView('body')
|
||||||
|
setMobilePanel('labels')
|
||||||
|
|
||||||
|
window.requestAnimationFrame(() => {
|
||||||
|
mobileLabelsScrollRef.current?.scrollIntoView({
|
||||||
|
block: 'start',
|
||||||
|
behavior: 'smooth',
|
||||||
|
})
|
||||||
|
})
|
||||||
}, [markManualCorrection, switchPoseKeypointMapView, uiLocked])
|
}, [markManualCorrection, switchPoseKeypointMapView, uiLocked])
|
||||||
|
|
||||||
const removePoseKeypoint = useCallback((personIndex: number, keypointIndex: number) => {
|
const removePoseKeypoint = useCallback((personIndex: number, keypointIndex: number) => {
|
||||||
@ -8074,6 +8144,12 @@ export default function TrainingTab(props: {
|
|||||||
correctionRef.current = next
|
correctionRef.current = next
|
||||||
return next
|
return next
|
||||||
})
|
})
|
||||||
|
|
||||||
|
setSelectedPoseKeypointAction((current) =>
|
||||||
|
current?.personIndex === personIndex && current.keypointIndex === keypointIndex
|
||||||
|
? null
|
||||||
|
: current
|
||||||
|
)
|
||||||
}, [markManualCorrection])
|
}, [markManualCorrection])
|
||||||
|
|
||||||
const resetPosePersons = useCallback(() => {
|
const resetPosePersons = useCallback(() => {
|
||||||
@ -8091,6 +8167,7 @@ export default function TrainingTab(props: {
|
|||||||
})
|
})
|
||||||
|
|
||||||
setActivePosePersonIndex(null)
|
setActivePosePersonIndex(null)
|
||||||
|
setSelectedPoseKeypointAction(null)
|
||||||
if (poseKeypointMapAnimationFrameRef.current !== null) {
|
if (poseKeypointMapAnimationFrameRef.current !== null) {
|
||||||
cancelAnimationFrame(poseKeypointMapAnimationFrameRef.current)
|
cancelAnimationFrame(poseKeypointMapAnimationFrameRef.current)
|
||||||
poseKeypointMapAnimationFrameRef.current = null
|
poseKeypointMapAnimationFrameRef.current = null
|
||||||
@ -8162,11 +8239,15 @@ export default function TrainingTab(props: {
|
|||||||
type: 'keypoint',
|
type: 'keypoint',
|
||||||
personIndex,
|
personIndex,
|
||||||
keypointIndex,
|
keypointIndex,
|
||||||
|
startClientX: e.clientX,
|
||||||
|
startClientY: e.clientY,
|
||||||
|
moved: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
poseInteractionRef.current = nextInteraction
|
poseInteractionRef.current = nextInteraction
|
||||||
setPoseInteraction(nextInteraction)
|
setPoseInteraction(nextInteraction)
|
||||||
setActivePosePersonIndex(personIndex)
|
setActivePosePersonIndex(personIndex)
|
||||||
|
setSelectedPoseKeypointAction(null)
|
||||||
setTouchMagnifier({
|
setTouchMagnifier({
|
||||||
visible: true,
|
visible: true,
|
||||||
clientX: e.clientX,
|
clientX: e.clientX,
|
||||||
@ -9803,6 +9884,7 @@ export default function TrainingTab(props: {
|
|||||||
if (uiLocked) return
|
if (uiLocked) return
|
||||||
setShowPoseSkeleton(true)
|
setShowPoseSkeleton(true)
|
||||||
setActivePosePersonIndex(personIndex)
|
setActivePosePersonIndex(personIndex)
|
||||||
|
setSelectedPoseKeypointAction(null)
|
||||||
setPendingPoseKeypoint({
|
setPendingPoseKeypoint({
|
||||||
personIndex,
|
personIndex,
|
||||||
keypointName: poseKeypointId(point.name),
|
keypointName: poseKeypointId(point.name),
|
||||||
@ -10117,11 +10199,13 @@ export default function TrainingTab(props: {
|
|||||||
|
|
||||||
if (pending) {
|
if (pending) {
|
||||||
setPendingPoseKeypoint(null)
|
setPendingPoseKeypoint(null)
|
||||||
|
setSelectedPoseKeypointAction(null)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
setShowPoseSkeleton(true)
|
setShowPoseSkeleton(true)
|
||||||
setActivePosePersonIndex(targetIndex)
|
setActivePosePersonIndex(targetIndex)
|
||||||
|
setSelectedPoseKeypointAction(null)
|
||||||
setPendingPoseKeypoint({
|
setPendingPoseKeypoint({
|
||||||
personIndex: targetIndex,
|
personIndex: targetIndex,
|
||||||
keypointName,
|
keypointName,
|
||||||
@ -10877,14 +10961,18 @@ export default function TrainingTab(props: {
|
|||||||
const selected =
|
const selected =
|
||||||
pendingPoseKeypoint?.personIndex === personIndex &&
|
pendingPoseKeypoint?.personIndex === personIndex &&
|
||||||
pendingPoseKeypoint.keypointName === keypointId
|
pendingPoseKeypoint.keypointName === keypointId
|
||||||
|
const actionSelected =
|
||||||
|
selectedPoseKeypointAction?.personIndex === personIndex &&
|
||||||
|
selectedPoseKeypointAction.keypointIndex === pointIndex
|
||||||
const hovered =
|
const hovered =
|
||||||
hoveredPoseKeypoint?.personIndex === personIndex &&
|
hoveredPoseKeypoint?.personIndex === personIndex &&
|
||||||
hoveredPoseKeypoint.keypointName === keypointId
|
hoveredPoseKeypoint.keypointName === keypointId
|
||||||
const dragging =
|
const dragging =
|
||||||
poseInteraction?.personIndex === personIndex &&
|
poseInteraction?.personIndex === personIndex &&
|
||||||
poseInteraction.keypointIndex === pointIndex
|
poseInteraction.keypointIndex === pointIndex
|
||||||
const highlighted = selected || hovered || dragging
|
const highlighted = selected || actionSelected || hovered || dragging
|
||||||
const showLabel = selected || dragging
|
const showLabel = selected || actionSelected || dragging
|
||||||
|
const showDeleteAction = actionSelected && !dragging && !uiLocked
|
||||||
const facePlacement = poseFaceImageZoomActive
|
const facePlacement = poseFaceImageZoomActive
|
||||||
? poseFaceKeypointLabelPlacement(keypointId)
|
? poseFaceKeypointLabelPlacement(keypointId)
|
||||||
: null
|
: null
|
||||||
@ -10939,7 +11027,11 @@ export default function TrainingTab(props: {
|
|||||||
|
|
||||||
{showLabel ? (
|
{showLabel ? (
|
||||||
<div
|
<div
|
||||||
className="pointer-events-none absolute z-[370] flex max-w-[9rem] items-center gap-1 rounded-full bg-white/95 px-2 py-1 text-[10px] font-black leading-none text-gray-950 shadow-lg ring-1 ring-black/10 dark:bg-white/95 dark:text-gray-950"
|
data-pose-control="true"
|
||||||
|
className={[
|
||||||
|
'absolute z-[370] flex max-w-[10.5rem] items-center gap-1 overflow-hidden rounded-full bg-white/95 text-[10px] font-black leading-none text-gray-950 shadow-lg ring-1 ring-black/10 dark:bg-white/95 dark:text-gray-950',
|
||||||
|
showDeleteAction ? 'pointer-events-auto p-0.5 pr-1' : 'pointer-events-none px-2 py-1',
|
||||||
|
].join(' ')}
|
||||||
style={{
|
style={{
|
||||||
left,
|
left,
|
||||||
top,
|
top,
|
||||||
@ -10957,6 +11049,26 @@ export default function TrainingTab(props: {
|
|||||||
style={{ backgroundColor: color }}
|
style={{ backgroundColor: color }}
|
||||||
/>
|
/>
|
||||||
<span className="min-w-0 truncate">{label}</span>
|
<span className="min-w-0 truncate">{label}</span>
|
||||||
|
|
||||||
|
{showDeleteAction ? (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="ml-0.5 inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-red-600 text-white shadow-sm transition hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500/40"
|
||||||
|
title={`${label} löschen`}
|
||||||
|
aria-label={`${label} löschen`}
|
||||||
|
onPointerDown={(event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
}}
|
||||||
|
onClick={(event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
removePoseKeypoint(personIndex, pointIndex)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TrashIcon className="h-3 w-3" aria-hidden="true" />
|
||||||
|
</button>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user