#!/usr/bin/env python3 """ 提取女性最多的畫面並標記人臉 """ import cv2 import numpy as np import json 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(f"- `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(f"📊 統計摘要:") 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(f"📁 生成文件:") print(f" - 標記圖像: {output_dir}/female_faces_frame_*.jpg") print(f" - 縮略圖: {output_dir}/female_faces_frame_*_thumbnail.jpg") print(f" - 分析報告: {report_path}") print() print(f"🔍 查看結果:") print(f" ls -la {output_dir}/") print(f" open {output_dir}/female_faces_report.md") else: print("❌ 未找到任何女性人臉畫面") if __name__ == "__main__": main()