Files
momentry_core/scripts/extract_female_faces.py
T
Warren e75c4d6f07 cleanup: remove dead code and duplicate docs
- Remove session-ses_2f27.md (161KB raw session log)
- Remove 49 ROOT_* duplicate files across REFERENCE/
- Remove 14 duplicate files between REFERENCE/ root and history/
- Remove asr_legacy.rs (dead code, replaced by asr.rs)
- Remove src/core/worker/ (duplicate JobWorker)
- Remove src/core/layers/ (empty directory)
- Remove 4 .bak files in src/
- Remove 7 dead private methods in worker/processor.rs
- Remove backup directory from git tracking
2026-05-04 01:31:21 +08:00

356 lines
12 KiB
Python

#!/usr/bin/env python3
"""
提取女性最多的畫面並標記人臉
"""
import cv2
import os
from datetime import datetime
def draw_female_faces(image_path, frame_number, output_dir="/tmp/female_faces"):
"""在圖像上標記女性人臉"""
# 創建輸出目錄
os.makedirs(output_dir, exist_ok=True)
# 讀取圖像
image = cv2.imread(image_path)
if image is None:
print(f"❌ 無法讀取圖像: {image_path}")
return None
# 從數據庫獲取女性人臉信息
import psycopg2
conn = psycopg2.connect(
host="localhost",
port=5432,
database="momentry",
user="accusys",
password="accusys",
)
cursor = conn.cursor()
cursor.execute(
"""
SELECT x, y, width, height, confidence,
(attributes->>'age')::numeric as age
FROM face_detections
WHERE frame_number = %s
AND attributes->>'gender' = 'female'
ORDER BY confidence DESC
""",
(frame_number,),
)
female_faces = cursor.fetchall()
cursor.close()
conn.close()
if not female_faces:
print(f"❌ 在幀 {frame_number} 中未找到女性人臉")
return None
print(f"✅ 在幀 {frame_number} 中找到 {len(female_faces)} 個女性人臉")
# 複製圖像用於標記
marked_image = image.copy()
# 標記每個人臉
for i, (x, y, w, h, confidence, age) in enumerate(female_faces):
# 繪製邊界框(粉色表示女性)
color = (255, 105, 180) # 粉色
thickness = 3
# 繪製矩形邊界框
cv2.rectangle(marked_image, (x, y), (x + w, y + h), color, thickness)
# 添加標籤
label = f"女 {i + 1}"
if age:
label += f" ({int(age)}歲)"
label += f" {confidence:.1%}"
# 計算標籤位置
label_size, baseline = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.7, 2)
label_y = max(y - 10, label_size[1] + 10)
# 繪製標籤背景
cv2.rectangle(
marked_image,
(x, label_y - label_size[1] - 10),
(x + label_size[0] + 10, label_y + 5),
color,
-1, # 填充
)
# 繪製標籤文字
cv2.putText(
marked_image,
label,
(x + 5, label_y - 5),
cv2.FONT_HERSHEY_SIMPLEX,
0.7,
(255, 255, 255), # 白色文字
2,
)
print(
f" 人臉 {i + 1}: 位置 [{x},{y},{w},{h}], 置信度 {confidence:.1%}, 年齡 {int(age) if age else '未知'}"
)
# 添加標題
title = f"女性最多的畫面 - 幀 {frame_number} - {len(female_faces)} 個女性"
title_size, _ = cv2.getTextSize(title, cv2.FONT_HERSHEY_SIMPLEX, 1.2, 3)
# 繪製標題背景
cv2.rectangle(
marked_image,
(10, 10),
(10 + title_size[0] + 20, 10 + title_size[1] + 20),
(0, 0, 0), # 黑色背景
-1,
)
# 繪製標題
cv2.putText(
marked_image,
title,
(20, 20 + title_size[1]),
cv2.FONT_HERSHEY_SIMPLEX,
1.2,
(255, 255, 255), # 白色文字
3,
)
# 添加時間戳信息
timestamp = frame_number / 59.94 # 假設 59.94 FPS
minutes = int(timestamp // 60)
seconds = int(timestamp % 60)
time_info = f"時間: {minutes:02d}:{seconds:02d}"
cv2.putText(
marked_image,
time_info,
(20, 60 + title_size[1]),
cv2.FONT_HERSHEY_SIMPLEX,
0.8,
(200, 200, 200), # 淺灰色
2,
)
# 保存標記後的圖像
output_path = os.path.join(output_dir, f"female_faces_frame_{frame_number}.jpg")
cv2.imwrite(output_path, marked_image)
print(f"✅ 已保存標記圖像: {output_path}")
# 創建縮略圖(便於查看)
height, width = marked_image.shape[:2]
scale = 800 / width
thumbnail = cv2.resize(marked_image, (800, int(height * scale)))
thumbnail_path = os.path.join(
output_dir, f"female_faces_frame_{frame_number}_thumbnail.jpg"
)
cv2.imwrite(thumbnail_path, thumbnail)
print(f"✅ 已保存縮略圖: {thumbnail_path}")
return {
"original_image": image_path,
"marked_image": output_path,
"thumbnail": thumbnail_path,
"frame_number": frame_number,
"timestamp_seconds": timestamp,
"timestamp_formatted": f"{minutes:02d}:{seconds:02d}",
"female_count": len(female_faces),
"female_faces": [
{
"index": i + 1,
"x": int(x),
"y": int(y),
"width": int(w),
"height": int(h),
"confidence": float(confidence),
"age": int(age) if age else None,
}
for i, (x, y, w, h, confidence, age) in enumerate(female_faces)
],
}
def create_female_faces_report(female_frames_info, output_dir="/tmp/female_faces"):
"""創建女性人臉報告"""
report_path = os.path.join(output_dir, "female_faces_report.md")
with open(report_path, "w", encoding="utf-8") as f:
f.write("# 女性人臉分析報告\n\n")
f.write(f"生成時間: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
f.write("## 📊 統計摘要\n\n")
total_females = sum(info["female_count"] for info in female_frames_info)
f.write(f"- **總女性人臉數**: {total_females}\n")
f.write(f"- **分析畫面數**: {len(female_frames_info)}\n")
f.write(
f"- **女性最多畫面**: {max(female_frames_info, key=lambda x: x['female_count'])['female_count']} 個女性\n\n"
)
f.write("## 🖼️ 女性最多的畫面\n\n")
for info in female_frames_info:
if info["female_count"] >= 2: # 只顯示有2個或以上女性的畫面
f.write(
f"### 幀 {info['frame_number']} - {info['timestamp_formatted']}\n\n"
)
f.write(f"- **女性數量**: {info['female_count']}\n")
f.write(
f"- **時間位置**: {info['timestamp_formatted']} ({info['timestamp_seconds']:.1f}秒)\n"
)
f.write(f"- **標記圖像**: `{os.path.basename(info['marked_image'])}`\n")
f.write(f"- **縮略圖**: `{os.path.basename(info['thumbnail'])}`\n\n")
f.write("#### 人臉詳細信息\n\n")
f.write("| 編號 | 位置 (x,y,w,h) | 置信度 | 年齡 |\n")
f.write("|------|----------------|--------|------|\n")
for face in info["female_faces"]:
position = (
f"{face['x']},{face['y']},{face['width']},{face['height']}"
)
confidence = f"{face['confidence']:.1%}"
age = str(face["age"]) if face["age"] else "未知"
f.write(
f"| {face['index']} | {position} | {confidence} | {age} |\n"
)
f.write("\n")
# 添加圖像引用
f.write(f"![女性人臉畫面]({os.path.basename(info['thumbnail'])})\n\n")
f.write(
f"*圖像大小: 原始 {os.path.getsize(info['original_image']):,} bytes, 標記 {os.path.getsize(info['marked_image']):,} bytes*\n\n"
)
f.write("## 📁 生成文件\n\n")
f.write("以下文件已生成:\n\n")
for info in female_frames_info:
if info["female_count"] >= 2:
f.write(
f"- `{os.path.basename(info['marked_image'])}` - 標記女性人臉的完整圖像\n"
)
f.write(
f"- `{os.path.basename(info['thumbnail'])}` - 縮略圖(800px寬)\n"
)
f.write("- `female_faces_report.md` - 本報告文件\n\n")
f.write("## 🔍 分析說明\n\n")
f.write("1. **邊界框顏色**: 粉色 (RGB: 255,105,180) 表示女性人臉\n")
f.write("2. **標籤格式**: `女 [編號] ([年齡]歲) [置信度]`\n")
f.write("3. **置信度**: 人臉檢測的準確度,越高越好\n")
f.write("4. **年齡**: 基於深度學習模型的估計,可能有±5歲誤差\n")
f.write("5. **時間位置**: 從視頻開始計算的時間\n\n")
f.write("## 🎬 視頻內容分析\n\n")
# 根據女性分布推測視頻內容
multi_female_frames = [
info for info in female_frames_info if info["female_count"] >= 2
]
if multi_female_frames:
f.write("根據女性人臉分布,視頻可能包含:\n\n")
f.write("1. **社交場合**: 多個女性同時出現,可能是聚會或社交活動\n")
f.write("2. **對話場景**: 女性之間的對話或互動\n")
f.write("3. **群體鏡頭**: 包含多個女性的群體畫面\n")
f.write(
f"4. **女性主導場景**: 在 {len(multi_female_frames)} 個畫面中有2個或以上女性\n"
)
else:
f.write("視頻中女性主要單獨出現,可能包含:\n\n")
f.write("1. **單人鏡頭**: 女性單獨出現的特寫\n")
f.write("2. **分散場景**: 女性分散在不同的畫面中\n")
f.write("3. **配角角色**: 女性可能不是主要角色\n")
print(f"✅ 報告已生成: {report_path}")
return report_path
def main():
print("=" * 70)
print("提取女性最多的畫面")
print("=" * 70)
# 輸出目錄
output_dir = "/tmp/female_faces"
# 找到女性最多的幾個畫面
female_frames = [
19778, # 3個女性(最多)
17980, # 2個女性
62930, # 2個女性
66526, # 2個女性
70122, # 2個女性
71920, # 2個女性
]
print(f"分析以下幀的女性人臉: {female_frames}")
print()
female_frames_info = []
for frame_number in female_frames:
image_path = (
f"/tmp/face_analysis_results/384b0ff44aaaa1f1_frame_{frame_number:06d}.jpg"
)
if os.path.exists(image_path):
print(f"處理幀 {frame_number}...")
info = draw_female_faces(image_path, frame_number, output_dir)
if info:
female_frames_info.append(info)
print()
else:
print(f"❌ 圖像文件不存在: {image_path}")
if female_frames_info:
# 創建報告
report_path = create_female_faces_report(female_frames_info, output_dir)
print("=" * 70)
print("✅ 提取完成!")
print("=" * 70)
# 顯示摘要
max_females = max(info["female_count"] for info in female_frames_info)
max_frame_info = [
info for info in female_frames_info if info["female_count"] == max_females
][0]
print("📊 統計摘要:")
print(f" - 總分析畫面: {len(female_frames_info)}")
print(f" - 女性最多畫面: 幀 {max_frame_info['frame_number']}")
print(f" - 女性數量: {max_females} 人")
print(f" - 時間位置: {max_frame_info['timestamp_formatted']}")
print()
print("📁 生成文件:")
print(f" - 標記圖像: {output_dir}/female_faces_frame_*.jpg")
print(f" - 縮略圖: {output_dir}/female_faces_frame_*_thumbnail.jpg")
print(f" - 分析報告: {report_path}")
print()
print("🔍 查看結果:")
print(f" ls -la {output_dir}/")
print(f" open {output_dir}/female_faces_report.md")
else:
print("❌ 未找到任何女性人臉畫面")
if __name__ == "__main__":
main()