fix: exemplar draw keeps other classes' full-set preview (REQ-182 amended)
- AutoAnnotateModal: render merges last full-set detections for non-exemplared classes with conditioned results for exemplared ones (selected-not-exemplared filter); drawing an example no longer clears the other classes' detections - Run Preview now always refreshes full-set first (exemplars: []) then re-runs exemplared classes - docs: REQ-182 amended (merge semantics), design/ui-spec/tasks synced
This commit is contained in:
1 parent
8fb65d2de9
commit
8f41c6c85a
5 files changed
+59
-38
No files matched your search
@@ -20,7 +20,6 @@ export default function AutoAnnotateModal({
|
||||
const [minBoxFrac, setMinBoxFrac] = useState(0.0)
|
||||
const [classParams, setClassParams] = useState({})
|
||||
|
||||
|
||||
// Class selection state
|
||||
const [selectedClasses, setSelectedClasses] = useState(() => {
|
||||
if (engine === 'base_model') {
|
||||
@@ -85,20 +84,25 @@ export default function AutoAnnotateModal({
|
||||
})
|
||||
|
||||
const activePool = activeClassName ? pools[activeClassName] || [] : []
|
||||
// While any selected class has examples, only those classes contribute.
|
||||
const exemplaredClasses = selectedClasses.filter(name => pools[name]?.length)
|
||||
// merged: exemplared classes show conditioned results (replacing their full-set
|
||||
// boxes); everyone else keeps the last full-set run (amended REQ-182)
|
||||
const nameById = Object.fromEntries(project.classes.map(c => [c.class_id, c.name]))
|
||||
const exemplaredSet = new Set(exemplaredClasses)
|
||||
const selectedSet = new Set(selectedClasses)
|
||||
const renderShapes = exemplaredClasses.length > 0
|
||||
? exemplaredClasses.flatMap(name => shapesByClass[name] || [])
|
||||
? [
|
||||
...previewShapes.filter(s => {
|
||||
const n = nameById[s.class_id]
|
||||
return selectedSet.has(n) && !exemplaredSet.has(n)
|
||||
}),
|
||||
...exemplaredClasses.flatMap(name => shapesByClass[name] || []),
|
||||
]
|
||||
: previewShapes
|
||||
|
||||
const handlePreview = () => {
|
||||
if (exemplaredClasses.length > 0) {
|
||||
run(exemplaredClasses)
|
||||
return
|
||||
}
|
||||
const frame = currentFrame
|
||||
if (!frame) return
|
||||
|
||||
let isMounted = true
|
||||
setIsLoadingPreview(true)
|
||||
setPreviewError('')
|
||||
@@ -111,8 +115,8 @@ export default function AutoAnnotateModal({
|
||||
target_class_names: selectedClasses,
|
||||
class_params: buildClassParams(classParams),
|
||||
custom_model_path: customModelStagedPath,
|
||||
exemplars: engine === 'sam3' ? activePool : [],
|
||||
exemplar_class_name: engine === 'sam3' ? activeClassName : null
|
||||
exemplars: [],
|
||||
exemplar_class_name: null
|
||||
}).then(res => {
|
||||
if (isMounted && res.shapes) {
|
||||
setPreviewShapes(res.shapes)
|
||||
@@ -123,7 +127,9 @@ export default function AutoAnnotateModal({
|
||||
setPreviewError(err.message || 'Preview failed')
|
||||
setPreviewShapes([])
|
||||
}).finally(() => {
|
||||
setIsLoadingPreview(false)
|
||||
if (!isMounted) return
|
||||
if (exemplaredClasses.length > 0) run(exemplaredClasses) // manages busy itself
|
||||
else setIsLoadingPreview(false)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -212,11 +218,9 @@ export default function AutoAnnotateModal({
|
||||
border: '1px solid rgba(168, 85, 247, 0.4)', background: '#18181b',
|
||||
overflowY: 'auto', borderRadius: 8
|
||||
}}>
|
||||
|
||||
{/* Left Side: Preview */}
|
||||
<div style={{ flex: '1 1 450px', display: 'flex', flexDirection: 'column', minWidth: 280 }}>
|
||||
<h3 style={{ margin: '0 0 8px 0', color: '#e4e4e7', fontSize: '1rem' }}>Preview</h3>
|
||||
|
||||
<div style={{ position: 'relative', width: '100%', background: '#000', borderRadius: 6, overflow: 'hidden', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
||||
{currentFrame ? (
|
||||
/* This wrapper must hug the image and nothing else: both overlays
|
||||
@@ -294,7 +298,6 @@ export default function AutoAnnotateModal({
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div style={{ marginTop: 10 }}>
|
||||
<div className="row" style={{ justifyContent: 'space-between', marginBottom: 4 }}>
|
||||
<span className="hint" style={{ fontSize: '0.8rem' }}>Preview Frame ({frameIndex + 1} / {frames.length}):</span>
|
||||
@@ -380,7 +383,6 @@ export default function AutoAnnotateModal({
|
||||
promptError={promptError}
|
||||
savedPrompt={activeClass ? classPrompts[activeClass.class_id] : ''}
|
||||
/>
|
||||
|
||||
<div className="row" style={{ justifyContent: 'flex-end', gap: 10, marginTop: 16, paddingTop: 10, borderTop: '1px solid rgba(255,255,255,0.08)' }}>
|
||||
<button className="btn btn-ghost" onClick={onClose} disabled={isSubmitting}>Cancel</button>
|
||||
<button
|
||||
@@ -392,9 +394,7 @@ export default function AutoAnnotateModal({
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user