Files
momentry_core/scripts/test_end_to_end.py
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

418 lines
13 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
端到端人臉識別測試
測試完整的人臉識別流程:註冊 -> 識別 -> 搜索
"""
import os
import sys
import numpy as np
import cv2
# 添加項目根目錄到 Python 路徑
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
def create_test_image_with_faces():
"""創建帶有人臉的測試圖像"""
print("創建測試圖像...")
# 創建一個簡單的測試圖像640x480
img = np.zeros((480, 640, 3), dtype=np.uint8)
# 添加一些"人臉"(簡單的橢圓形)
# 人臉1
cv2.ellipse(img, (200, 200), (80, 100), 0, 0, 360, (255, 200, 150), -1)
cv2.ellipse(img, (170, 170), (15, 10), 0, 0, 360, (0, 0, 0), -1) # 左眼
cv2.ellipse(img, (230, 170), (15, 10), 0, 0, 360, (0, 0, 0), -1) # 右眼
cv2.ellipse(img, (200, 230), (30, 15), 0, 0, 360, (0, 0, 0), -1) # 嘴巴
# 人臉2
cv2.ellipse(img, (450, 300), (70, 90), 0, 0, 360, (200, 220, 180), -1)
cv2.ellipse(img, (420, 270), (12, 8), 0, 0, 360, (0, 0, 0), -1) # 左眼
cv2.ellipse(img, (480, 270), (12, 8), 0, 0, 360, (0, 0, 0), -1) # 右眼
cv2.ellipse(img, (450, 330), (25, 12), 0, 0, 360, (0, 0, 0), -1) # 嘴巴
# 保存測試圖像
test_image_path = "/tmp/test_face_image.jpg"
cv2.imwrite(test_image_path, img)
print(f"✅ 測試圖像已保存到: {test_image_path}")
return test_image_path, img
def test_face_registration():
"""測試人臉註冊"""
print("\n=== 測試人臉註冊 ===")
try:
from scripts.face_registration import FaceRegistration
# 創建測試圖像
image_path, img = create_test_image_with_faces()
# 初始化註冊器
print("初始化人臉註冊器...")
registration = FaceRegistration()
# 加載模型
print("加載模型...")
registration.load_models(use_mps=False)
# 註冊人臉
print("註冊人臉...")
result = registration.register_face(
image_path=image_path,
name="Test Person 1",
metadata={"source": "test", "age": 30, "gender": "male"},
)
if result["success"]:
print("✅ 人臉註冊成功")
print(f" - Face ID: {result.get('face_id')}")
print(f" - 嵌入向量維度: {len(result.get('embedding', []))}")
print(f" - 屬性: {result.get('attributes', {})}")
# 保存嵌入向量供後續測試使用
embedding = result.get("embedding", [])
if embedding:
np.save("/tmp/test_face_embedding.npy", embedding)
print("✅ 嵌入向量已保存")
return True, result
else:
print(f"❌ 人臉註冊失敗: {result.get('message', 'Unknown error')}")
return False, None
except Exception as e:
print(f"❌ 人臉註冊測試失敗: {e}")
import traceback
traceback.print_exc()
return False, None
def test_face_recognition():
"""測試人臉識別"""
print("\n=== 測試人臉識別 ===")
try:
from scripts.face_recognition_processor import FaceRecognitionProcessor
# 創建測試圖像
image_path, img = create_test_image_with_faces()
# 初始化處理器
print("初始化人臉識別處理器...")
processor = FaceRecognitionProcessor(
enable_recognition=True, enable_tracking=True, enable_clustering=True
)
# 加載模型
print("加載模型...")
processor.load_models(use_mps=False)
# 讀取圖像
print("讀取測試圖像...")
image = cv2.imread(image_path)
if image is None:
print("❌ 無法讀取測試圖像")
return False
# 檢測人臉
print("檢測人臉...")
detections = processor.detect_faces(image)
print(f"✅ 檢測到 {len(detections)} 個人臉")
if len(detections) > 0:
for i, detection in enumerate(detections):
print(f"\n人臉 {i + 1}:")
print(
f" - 位置: x={detection['x']}, y={detection['y']}, width={detection['width']}, height={detection['height']}"
)
print(f" - 置信度: {detection['confidence']:.4f}")
if "embedding" in detection and detection["embedding"] is not None:
embedding = detection["embedding"]
if hasattr(embedding, "shape"):
print(f" - 嵌入向量維度: {embedding.shape}")
else:
print(f" - 嵌入向量長度: {len(embedding)}")
if "attributes" in detection:
attrs = detection["attributes"]
print(f" - 屬性: {attrs}")
# 測試人臉追蹤(模擬多幀)
print("\n測試人臉追蹤...")
# 創建模擬幀數據
frames = [
{"frame_id": 1, "faces": detections},
{"frame_id": 2, "faces": detections}, # 簡單重複使用相同的檢測
]
tracked_frames = processor.track_faces(frames)
print(f"✅ 追蹤完成,處理了 {len(tracked_frames)}")
# 測試人臉聚類
print("\n測試人臉聚類...")
# 創建模擬多幀檢測數據
all_frames = []
for i in range(3): # 模擬3幀
frame_data = {
"frame_id": i + 1,
"faces": detections if i == 0 else [], # 只在第一幀有檢測
}
all_frames.append(frame_data)
clusters = processor.cluster_faces(all_frames)
print(f"✅ 創建 {len(clusters)} 個聚類")
return True
except Exception as e:
print(f"❌ 人臉識別測試失敗: {e}")
import traceback
traceback.print_exc()
return False
def test_database_operations():
"""測試數據庫操作"""
print("\n=== 測試數據庫操作 ===")
try:
import psycopg2
from psycopg2.extras import Json
# 連接數據庫
conn = psycopg2.connect(
host="localhost",
port=5432,
database="momentry",
user="accusys",
password="accusys",
)
cursor = conn.cursor()
# 測試1: 插入人臉檢測記錄
print("測試插入人臉檢測記錄...")
cursor.execute(
"""
INSERT INTO face_detections
(video_uuid, frame_number, timestamp_secs, face_id, x, y, width, height, confidence, attributes)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
RETURNING id;
""",
(
"test_video_001",
1,
0.0,
"test_face_001",
100,
100,
200,
200,
0.95,
Json({"age": 30, "gender": "male", "test": True}),
),
)
detection_id = cursor.fetchone()[0]
print(f"✅ 插入人臉檢測記錄成功ID: {detection_id}")
# 測試2: 查詢人臉檢測記錄
print("\n測試查詢人臉檢測記錄...")
cursor.execute(
"""
SELECT id, video_uuid, frame_number, face_id, confidence, attributes
FROM face_detections
WHERE id = %s;
""",
(detection_id,),
)
result = cursor.fetchone()
print("✅ 查詢結果:")
print(f" - ID: {result[0]}")
print(f" - 視頻UUID: {result[1]}")
print(f" - 幀號: {result[2]}")
print(f" - 人臉ID: {result[3]}")
print(f" - 置信度: {result[4]}")
print(f" - 屬性: {result[5]}")
# 測試3: 測試向量搜索函數
print("\n測試向量搜索函數...")
# 創建一個測試嵌入向量
test_embedding = np.random.randn(512).tolist()
# 首先插入一個帶有嵌入向量的人臉身份
cursor.execute(
"""
SELECT find_or_create_face_identity(
'test_search_001',
'Search Test Person',
%s::vector,
'{"age": 25, "gender": "female", "test": true}'::jsonb,
'{"source": "search_test"}'::jsonb
);
""",
(test_embedding,),
)
identity_id = cursor.fetchone()[0]
print(f"✅ 創建測試人臉身份ID: {identity_id}")
# 測試搜索相似人臉
cursor.execute(
"""
SELECT * FROM find_similar_faces(
%s::vector,
0.5, -- similarity_threshold
5 -- limit_count
);
""",
(test_embedding,),
)
similar_faces = cursor.fetchall()
print(f"✅ 找到 {len(similar_faces)} 個相似人臉")
for face in similar_faces:
print(f" - {face[0]}: {face[1]} (相似度: {face[2]:.4f})")
# 清理測試數據
print("\n清理測試數據...")
cursor.execute(
"DELETE FROM face_detections WHERE video_uuid = 'test_video_001';"
)
cursor.execute("DELETE FROM face_identities WHERE face_id LIKE 'test_%';")
conn.commit()
print("✅ 測試數據清理完成")
cursor.close()
conn.close()
return True
except Exception as e:
print(f"❌ 數據庫操作測試失敗: {e}")
import traceback
traceback.print_exc()
return False
def test_mps_acceleration():
"""測試 MPS 加速"""
print("\n=== 測試 MPS 加速 ===")
try:
import onnxruntime as ort
available_providers = ort.get_available_providers()
print(f"可用的執行提供者: {available_providers}")
if "CoreMLExecutionProvider" in available_providers:
print("✅ CoreML (MPS) 支援可用")
# 測試使用 MPS 初始化模型
from scripts.face_recognition_processor import FaceRecognitionProcessor
print("測試使用 MPS 初始化模型...")
processor = FaceRecognitionProcessor()
try:
processor.load_models(use_mps=True)
print("✅ MPS 模型加載成功")
# 測試推理
test_image = np.random.randint(0, 255, (640, 480, 3), dtype=np.uint8)
detections = processor.detect_faces(test_image)
print(f"✅ MPS 推理完成,檢測到 {len(detections)} 個人臉")
return True
except Exception as e:
print(f"⚠️ MPS 初始化失敗,回退到 CPU: {e}")
print("嘗試使用 CPU...")
processor.load_models(use_mps=False)
print("✅ CPU 模型加載成功")
return True
else:
print("⚠️ CoreML (MPS) 不可用,使用 CPU")
return True
except Exception as e:
print(f"❌ MPS 測試失敗: {e}")
return False
def main():
"""主測試函數"""
print("=" * 60)
print("端到端人臉識別測試")
print("=" * 60)
tests = [
("人臉註冊", test_face_registration),
("人臉識別", test_face_recognition),
("數據庫操作", test_database_operations),
("MPS 加速", test_mps_acceleration),
]
results = []
for test_name, test_func in tests:
try:
print(f"\n{'=' * 40}")
print(f"開始測試: {test_name}")
print(f"{'=' * 40}")
success = test_func()
results.append((test_name, success))
if success:
print(f"{test_name} 測試通過")
else:
print(f"{test_name} 測試失敗")
except Exception as e:
print(f"{test_name} 測試異常: {e}")
import traceback
traceback.print_exc()
results.append((test_name, False))
print("\n" + "=" * 60)
print("端到端測試結果摘要")
print("=" * 60)
passed = 0
for test_name, success in results:
status = "✅ 通過" if success else "❌ 失敗"
print(f"{test_name}: {status}")
if success:
passed += 1
print(f"\n總計: {passed}/{len(results)} 個測試通過")
if passed == len(results):
print("\n🎉 所有端到端測試通過!人臉識別系統完全可用。")
print("\n下一步:")
print("1. 啟動 Momentry 服務器")
print("2. 使用 API 端點進行人臉註冊和識別")
print("3. 測試視頻處理功能")
return 0
else:
print(f"\n⚠️ 有 {len(results) - passed} 個測試失敗,請檢查問題。")
return 1
if __name__ == "__main__":
sys.exit(main())