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

418 lines
13 KiB
Python

#!/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())