feat: update Python processors and add utility scripts
- Update ASR, face, OCR, pose processors - Add release pre-flight check script - Add synonym generation, chunk processing scripts - Add face recognition, stamp search utilities
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
#!/usr/bin/python3.11
|
||||
"""
|
||||
ASR x Face Combination Statistics
|
||||
For each ASR segment, count unique faces (person_ids) appearing during that segment.
|
||||
Then aggregate: how many segments have 1 face, 2 faces, 3 faces, etc.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from collections import defaultdict
|
||||
|
||||
UUID = "384b0ff44aaaa1f1"
|
||||
BASE_DIR = f"output/{UUID}"
|
||||
|
||||
|
||||
def load_json(filepath):
|
||||
with open(filepath, "r") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def build_asr_face_stats():
|
||||
print(f"📊 Building ASR x Face combination statistics for {UUID}...")
|
||||
|
||||
# Load data
|
||||
asr_data = load_json(os.path.join(BASE_DIR, f"{UUID}.asr.json"))
|
||||
face_data = load_json(os.path.join(BASE_DIR, f"{UUID}.face_clustered.json"))
|
||||
|
||||
segments = asr_data.get("segments", [])
|
||||
face_frames = face_data.get("frames", [])
|
||||
|
||||
# Build face lookup: timestamp -> set of person_ids
|
||||
face_by_time = {}
|
||||
for frame in face_frames:
|
||||
ts = frame.get("timestamp", 0)
|
||||
faces = frame.get("faces", [])
|
||||
pids = set()
|
||||
for f in faces:
|
||||
pid = f.get("person_id")
|
||||
if pid:
|
||||
pids.add(pid)
|
||||
face_by_time[ts] = pids
|
||||
|
||||
# Get sorted timestamps for efficient lookup
|
||||
sorted_times = sorted(face_by_time.keys())
|
||||
|
||||
def get_faces_in_range(start, end):
|
||||
"""Get all unique person_ids appearing in a time range."""
|
||||
all_pids = set()
|
||||
for ts in sorted_times:
|
||||
if start <= ts <= end:
|
||||
all_pids.update(face_by_time[ts])
|
||||
return all_pids
|
||||
|
||||
# Analyze each ASR segment
|
||||
face_count_dist = defaultdict(int)
|
||||
segment_details = []
|
||||
|
||||
for seg in segments:
|
||||
start = seg.get("start", 0)
|
||||
end = seg.get("end", 0)
|
||||
text = seg.get("text", "")
|
||||
|
||||
pids = get_faces_in_range(start, end)
|
||||
face_count = len(pids)
|
||||
|
||||
face_count_dist[face_count] += 1
|
||||
segment_details.append(
|
||||
{
|
||||
"start": start,
|
||||
"end": end,
|
||||
"text": text[:80],
|
||||
"face_count": face_count,
|
||||
"person_ids": list(pids)[:5], # Top 5
|
||||
}
|
||||
)
|
||||
|
||||
return dict(face_count_dist), segment_details, len(segments)
|
||||
|
||||
|
||||
def print_stats(dist, total_segments):
|
||||
print("\n" + "=" * 60)
|
||||
print("📈 ASR x Face Combination Statistics")
|
||||
print("=" * 60)
|
||||
|
||||
print(f"\nTotal ASR segments: {total_segments}")
|
||||
print(f"\n{'Face Count':<12} {'Segments':>10} {'Percentage':>12}")
|
||||
print("-" * 40)
|
||||
|
||||
sorted_dist = sorted(dist.items(), key=lambda x: x[0])
|
||||
for fc, count in sorted_dist:
|
||||
pct = count / total_segments * 100
|
||||
print(f" {fc:>2} faces {count:>8} {pct:>6.1f}%")
|
||||
|
||||
# Summary
|
||||
total_faces_sum = sum(fc * count for fc, count in dist.items())
|
||||
avg_faces = total_faces_sum / total_segments if total_segments > 0 else 0
|
||||
max_faces = max(dist.keys()) if dist else 0
|
||||
|
||||
print(f"\n📊 Summary:")
|
||||
print(f" Average faces per segment: {avg_faces:.1f}")
|
||||
print(f" Max faces in a segment: {max_faces}")
|
||||
print(
|
||||
f" Segments with 0 faces: {dist.get(0, 0)} ({dist.get(0, 0) / total_segments * 100:.1f}%)"
|
||||
)
|
||||
print(
|
||||
f" Segments with 1 face: {dist.get(1, 0)} ({dist.get(1, 0) / total_segments * 100:.1f}%)"
|
||||
)
|
||||
print(
|
||||
f" Segments with 2+ faces: {total_segments - dist.get(0, 0) - dist.get(1, 0)}"
|
||||
)
|
||||
|
||||
# Show some example segments
|
||||
print(f"\n🔍 Example Segments:")
|
||||
print(f" 0 faces:")
|
||||
examples = [s for s in segment_details if s["face_count"] == 0][:3]
|
||||
for ex in examples:
|
||||
print(f" [{ex['start']:.0f}s-{ex['end']:.0f}s] {ex['text']}...")
|
||||
|
||||
print(f" 1 face:")
|
||||
examples = [s for s in segment_details if s["face_count"] == 1][:3]
|
||||
for ex in examples:
|
||||
print(
|
||||
f" [{ex['start']:.0f}s-{ex['end']:.0f}s] {ex['person_ids'][0]}: {ex['text']}..."
|
||||
)
|
||||
|
||||
print(f" 3 faces:")
|
||||
examples = [s for s in segment_details if s["face_count"] == 3][:3]
|
||||
for ex in examples:
|
||||
pids = ", ".join(ex["person_ids"])
|
||||
print(f" [{ex['start']:.0f}s-{ex['end']:.0f}s] [{pids}] {ex['text']}...")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
dist, segment_details, total = build_asr_face_stats()
|
||||
print_stats(dist, total)
|
||||
|
||||
# Save
|
||||
output_path = os.path.join(BASE_DIR, "asr_face_stats.json")
|
||||
with open(output_path, "w") as f:
|
||||
json.dump({"distribution": dist, "segments": segment_details}, f, indent=2)
|
||||
print(f"\n💾 Saved: {output_path}")
|
||||
Reference in New Issue
Block a user