fix: improve TUI with View buttons and smooth out blur interpolation
This commit is contained in:
parent
aa4bb03098
commit
599fa858f6
2 changed files with 63 additions and 13 deletions
|
|
@ -337,6 +337,16 @@ class FaceSelectionScreen(Screen):
|
|||
.face-row {
|
||||
height: 3;
|
||||
margin-bottom: 0;
|
||||
align: left middle;
|
||||
}
|
||||
|
||||
.face-checkbox {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.view-btn {
|
||||
min-width: 8;
|
||||
margin-left: 2;
|
||||
}
|
||||
|
||||
#blur-method-label {
|
||||
|
|
@ -391,13 +401,21 @@ class FaceSelectionScreen(Screen):
|
|||
sample_info = (
|
||||
f" [dim]{self.face_samples[cluster.id]}[/dim]"
|
||||
)
|
||||
with Horizontal(classes="face-row"):
|
||||
yield Checkbox(
|
||||
f"Person {cluster.id + 1} "
|
||||
f"({len(cluster.faces)} detections)"
|
||||
f"{sample_info}",
|
||||
value=True,
|
||||
id=f"cluster-{cluster.id}",
|
||||
classes="face-row",
|
||||
classes="face-checkbox",
|
||||
)
|
||||
if cluster.id in self.face_samples:
|
||||
yield Button(
|
||||
"View",
|
||||
id=f"view-{cluster.id}",
|
||||
variant="default",
|
||||
classes="view-btn",
|
||||
)
|
||||
yield Label("Blur method:", id="blur-method-label")
|
||||
yield Select(
|
||||
|
|
@ -424,6 +442,25 @@ class FaceSelectionScreen(Screen):
|
|||
self.app.pop_screen()
|
||||
elif event.button.id == "blur-btn":
|
||||
self._start_encoding()
|
||||
elif event.button.id and event.button.id.startswith("view-"):
|
||||
cluster_id = int(event.button.id.split("-")[1])
|
||||
if cluster_id in self.face_samples:
|
||||
self._open_image(self.face_samples[cluster_id])
|
||||
|
||||
def _open_image(self, path: Path) -> None:
|
||||
"""Open image in default viewer."""
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
try:
|
||||
if sys.platform == "darwin":
|
||||
subprocess.run(["open", str(path)])
|
||||
elif sys.platform == "win32":
|
||||
os.startfile(str(path))
|
||||
else:
|
||||
subprocess.run(["xdg-open", str(path)])
|
||||
except Exception:
|
||||
pass # Ignore if viewer fails to launch
|
||||
|
||||
def _start_encoding(self) -> None:
|
||||
# Collect selected cluster IDs
|
||||
|
|
@ -438,7 +475,9 @@ class FaceSelectionScreen(Screen):
|
|||
if cluster.id == -1:
|
||||
selected_ids.add(-1)
|
||||
|
||||
blur_method = self.query_one("#blur-method", Select).value
|
||||
blur_method = str(self.query_one("#blur-method", Select).value)
|
||||
if blur_method == "Select.NoSelection":
|
||||
blur_method = "gaussian"
|
||||
|
||||
# Generate output path
|
||||
stem = self.video_path.stem
|
||||
|
|
|
|||
|
|
@ -145,13 +145,24 @@ def get_bboxes_for_frame(
|
|||
all_clusters = set(prev_by_cluster.keys()) | set(next_by_cluster.keys())
|
||||
for cid in all_clusters:
|
||||
if cid in prev_by_cluster and cid in next_by_cluster:
|
||||
# Face present in both: standard linear interpolation
|
||||
bbox = interpolate_bboxes(prev_by_cluster[cid], next_by_cluster[cid], t)
|
||||
result.append((cid, bbox))
|
||||
elif cid in prev_by_cluster:
|
||||
# Face leaving frame — use prev bbox (fade out handled by caller if desired)
|
||||
result.append((cid, prev_by_cluster[cid]))
|
||||
# Face leaving: shrink to center of previous bbox
|
||||
x1, y1, x2, y2 = prev_by_cluster[cid]
|
||||
cx, cy = (x1 + x2) // 2, (y1 + y2) // 2
|
||||
center_bbox = (cx, cy, cx, cy)
|
||||
# Interpolate from full bbox (t=0) to center point (t=1)
|
||||
bbox = interpolate_bboxes(prev_by_cluster[cid], center_bbox, t)
|
||||
result.append((cid, bbox))
|
||||
else:
|
||||
# Face entering frame — use next bbox
|
||||
result.append((cid, next_by_cluster[cid]))
|
||||
# Face entering: grow from center of next bbox
|
||||
x1, y1, x2, y2 = next_by_cluster[cid]
|
||||
cx, cy = (x1 + x2) // 2, (y1 + y2) // 2
|
||||
center_bbox = (cx, cy, cx, cy)
|
||||
# Interpolate from center point (t=0) to full bbox (t=1)
|
||||
bbox = interpolate_bboxes(center_bbox, next_by_cluster[cid], t)
|
||||
result.append((cid, bbox))
|
||||
|
||||
return result
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue