fix(人物管理): 头像优先选独照帧,避免双人图当头像

人物卡片头像挑选策略调整:
1. 优先『独照』帧——该帧只有当前人物一个标签且 face_count=1(双人图不再作为某人头像)
2. 无独照时退而求其次用 face_count 最大的帧
3. 最后按时间序第一张兜底
修复: 一张图出现两人时(如 event_21/frame_3 '人物1, 人物2'),两人卡片都拿双人图做头像、无法区分的问题
This commit is contained in:
ericwyuan
2026-08-21 05:54:38 +08:00
parent 73f6c77544
commit ae1c13589f

View File

@@ -795,11 +795,12 @@ elif page == "👤 人物管理":
real_to_label = {v: k for k, v in alias_map.items()} real_to_label = {v: k for k, v in alias_map.items()}
# 聚合每个真实人物出现的帧(时间升序) # 聚合每个真实人物出现的帧(时间升序)
# 聚合每个真实人物出现的帧(时间升序),保留原始 person 串供独照判定
person_frames = {} person_frames = {}
for r in detail_rows: for r in detail_rows:
for p in resolve_persons(r['person'], alias_map): for p in resolve_persons(r['person'], alias_map):
person_frames.setdefault(p, []).append( person_frames.setdefault(p, []).append(
(r['event_id'], r['frame_index'], r['frame_timestamp'])) (r['event_id'], r['frame_index'], r['frame_timestamp'], r['person']))
named_keys = [k for k in person_frames if k in real_to_label] named_keys = [k for k in person_frames if k in real_to_label]
st.markdown( st.markdown(
@@ -823,19 +824,28 @@ elif page == "👤 人物管理":
_meta_cache[event_id] = {} _meta_cache[event_id] = {}
return _meta_cache[event_id] return _meta_cache[event_id]
def person_photo(frames): def person_photo(key, frames):
"""头像优先挑有人脸的帧face_count 最大),其次按时间序第一张""" """头像挑选策略:
best, best_faces = None, -1 1. 优先『独照』——该帧只有当前人物一个标签且人脸数=1不会拿双人图当头像
for eid, fidx, _ in frames: 2. 无独照时退而求其次:人脸数最多的帧
3. 最后按时间序第一张兜底
"""
solo, best, best_faces = None, None, -1
for eid, fidx, _ts, person_str in frames:
meta = _load_meta(eid) meta = _load_meta(eid)
faces = int(meta.get(str(fidx), 0) or 0) faces = int(meta.get(str(fidx), 0) or 0)
if faces > best_faces: if faces == 1 and len(resolve_persons(person_str, alias_map)) == 1:
if solo is None:
solo = load_frame_b64(eid, fidx)
elif faces > best_faces:
b64 = load_frame_b64(eid, fidx) b64 = load_frame_b64(eid, fidx)
if b64: if b64:
best, best_faces = b64, faces best, best_faces = b64, faces
if solo:
return solo
if best: if best:
return best return best
for eid, fidx, _ in frames: for eid, fidx, _ts, _ps in frames:
b64 = load_frame_b64(eid, fidx) b64 = load_frame_b64(eid, fidx)
if b64: if b64:
return b64 return b64
@@ -888,7 +898,7 @@ elif page == "👤 人物管理":
is_named = key in real_to_label is_named = key in real_to_label
label = real_to_label.get(key, key) label = real_to_label.get(key, key)
feat = feat_map.get(label) or '暂无特征描述' feat = feat_map.get(label) or '暂无特征描述'
photo = person_photo(frames) photo = person_photo(key, frames)
first_ts = parse_ts(frames[0][2]) first_ts = parse_ts(frames[0][2])
last_ts = parse_ts(frames[-1][2]) last_ts = parse_ts(frames[-1][2])
first_str = first_ts.strftime('%m-%d %H:%M') if first_ts else '--' first_str = first_ts.strftime('%m-%d %H:%M') if first_ts else '--'