feat: per-class exemplar preview, class hide toggle, container NMS flag (REQ-182, REQ-183, REQ-184)
This commit is contained in:
1 parent
1a99f2ffe4
commit
96a00267d9
18 files changed
+537
-124
No files matched your search
@@ -23,6 +23,7 @@ export default function ReviewPage({ batchId: rawBatchId, projectId, onProject }
|
||||
const [busy, setBusy] = useState(false)
|
||||
const [error, setError] = useState('')
|
||||
const [activeJob, setActiveJob] = useState(null)
|
||||
const [hiddenClasses, setHiddenClasses] = useState(() => new Set())
|
||||
|
||||
const batchId = batch?.id || rawBatchId
|
||||
const stripRef = useRef(null)
|
||||
@@ -184,7 +185,33 @@ export default function ReviewPage({ batchId: rawBatchId, projectId, onProject }
|
||||
})
|
||||
}, [])
|
||||
|
||||
const markAll = useCallback(() => setMarkedIds(annotations.map((row) => row.id)), [annotations])
|
||||
const toggleHide = useCallback((classId) => {
|
||||
setHiddenClasses((current) => {
|
||||
const next = new Set(current)
|
||||
if (next.has(classId)) next.delete(classId)
|
||||
else next.add(classId)
|
||||
return next
|
||||
})
|
||||
}, [])
|
||||
|
||||
// REQ-183: while a class is hidden, no shape of it may be selected or
|
||||
// marked — however it got there (draw, reclass, copy) — so Delete can
|
||||
// never hit an invisible shape.
|
||||
useEffect(() => {
|
||||
if (!hiddenClasses.size) return
|
||||
setSelectedId((currentId) => {
|
||||
const row = annotations.find((a) => a.id === currentId)
|
||||
return row && hiddenClasses.has(row.class_id) ? null : currentId
|
||||
})
|
||||
setMarkedIds((rows) => rows.filter((id) => {
|
||||
const row = annotations.find((a) => a.id === id)
|
||||
return !row || !hiddenClasses.has(row.class_id)
|
||||
}))
|
||||
}, [hiddenClasses, annotations])
|
||||
|
||||
const visibleAnnotations = annotations.filter((row) => !hiddenClasses.has(row.class_id))
|
||||
|
||||
const markAll = useCallback(() => setMarkedIds(visibleAnnotations.map((row) => row.id)), [visibleAnnotations])
|
||||
|
||||
const removeMarked = useCallback(async () => {
|
||||
if (!markedIds.length || !frame) return
|
||||
@@ -460,7 +487,7 @@ export default function ReviewPage({ batchId: rawBatchId, projectId, onProject }
|
||||
<AnnotationCanvas
|
||||
frame={frame}
|
||||
imageUrl={api.frameUrl(frame.id)}
|
||||
annotations={annotations}
|
||||
annotations={visibleAnnotations}
|
||||
selectedId={selectedId}
|
||||
activeClass={activeClass}
|
||||
assistMode={assistMode}
|
||||
@@ -503,9 +530,9 @@ export default function ReviewPage({ batchId: rawBatchId, projectId, onProject }
|
||||
className="btn"
|
||||
style={{ padding: '2px 8px', fontSize: '0.78rem' }}
|
||||
onClick={markAll}
|
||||
disabled={!annotations.length}
|
||||
disabled={!visibleAnnotations.length}
|
||||
>
|
||||
Select all ({annotations.length})
|
||||
Select all ({visibleAnnotations.length})
|
||||
</button>
|
||||
<span className="muted" style={{ fontSize: '0.78rem' }}>
|
||||
{markedIds.length
|
||||
@@ -623,6 +650,8 @@ export default function ReviewPage({ batchId: rawBatchId, projectId, onProject }
|
||||
reclass={reclass}
|
||||
clearClassInBatch={clearClassInBatch}
|
||||
clearClassInFrame={clearClassInFrame}
|
||||
hiddenClasses={hiddenClasses}
|
||||
onToggleHide={toggleHide}
|
||||
annotations={annotations}
|
||||
selectedId={selectedId}
|
||||
setSelectedId={setSelectedId}
|
||||
|
||||
Reference in new issue
Block a user