feat: update Python processors and add utility scripts

- Update ASR, face, OCR, pose processors
- Add release pre-flight check script
- Add synonym generation, chunk processing scripts
- Add face recognition, stamp search utilities
This commit is contained in:
Warren
2026-04-30 15:07:49 +08:00
parent f4697396e4
commit 8f05a7c188
256 changed files with 60505 additions and 299 deletions

View File

@@ -0,0 +1,367 @@
#!/usr/bin/env python3
"""
測試人臉識別完整集成流程
"""
import os
import sys
import json
import numpy as np
from pathlib import Path
# 添加項目根目錄到 Python 路徑
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# 測試數據庫連接
try:
import psycopg2
from psycopg2.extras import Json
print("✅ psycopg2 已安裝")
except ImportError:
print("❌ psycopg2 未安裝,請運行: pip install psycopg2-binary")
sys.exit(1)
# 測試 InsightFace
try:
import insightface
print("✅ insightface 已安裝")
except ImportError:
print("❌ insightface 未安裝,請運行: pip install insightface")
sys.exit(1)
# 測試 ONNX Runtime
try:
import onnxruntime as ort
print("✅ onnxruntime 已安裝")
# 檢查可用的執行提供者
available_providers = ort.get_available_providers()
print(f"✅ 可用的執行提供者: {available_providers}")
# 檢查 MPS 支援
if "CoreMLExecutionProvider" in available_providers:
print("✅ CoreML (MPS) 支援可用")
elif "CUDAExecutionProvider" in available_providers:
print("✅ CUDA 支援可用")
else:
print("⚠️ 僅 CPU 支援可用")
except ImportError:
print("❌ onnxruntime 未安裝,請運行: pip install onnxruntime")
sys.exit(1)
def test_database_connection():
"""測試數據庫連接"""
print("\n=== 測試數據庫連接 ===")
try:
conn = psycopg2.connect(
host="localhost",
port=5432,
database="momentry",
user="accusys",
password="accusys",
)
cursor = conn.cursor()
# 檢查表是否存在
cursor.execute("""
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name LIKE 'face_%'
ORDER BY table_name;
""")
tables = cursor.fetchall()
print(f"✅ 找到 {len(tables)} 個人臉相關表:")
for table in tables:
print(f" - {table[0]}")
# 檢查函數是否存在
cursor.execute("""
SELECT proname
FROM pg_proc
WHERE proname LIKE '%face%'
ORDER BY proname;
""")
functions = cursor.fetchall()
print(f"✅ 找到 {len(functions)} 個人臉相關函數:")
for func in functions:
print(f" - {func[0]}")
# 測試插入和查詢
cursor.execute("""
SELECT find_or_create_face_identity(
'integration_test_001',
'Integration Test Person',
NULL,
'{"age": 25, "gender": "female", "test": true}'::jsonb,
'{"source": "integration_test"}'::jsonb
) AS identity_id;
""")
identity_id = cursor.fetchone()[0]
print(f"✅ 成功創建人臉身份ID: {identity_id}")
# 檢查插入的數據
cursor.execute("""
SELECT id, face_id, name, attributes->>'gender' as gender,
attributes->>'age' as age, attributes->>'test' as test
FROM face_identities
WHERE face_id = 'integration_test_001';
""")
result = cursor.fetchone()
print(
f"✅ 查詢結果: ID={result[0]}, FaceID={result[1]}, Name={result[2]}, Gender={result[3]}, Age={result[4]}, Test={result[5]}"
)
# 清理測試數據
cursor.execute(
"DELETE FROM face_identities WHERE face_id = 'integration_test_001';"
)
conn.commit()
print("✅ 清理測試數據完成")
cursor.close()
conn.close()
return True
except Exception as e:
print(f"❌ 數據庫連接測試失敗: {e}")
return False
def test_insightface_model():
"""測試 InsightFace 模型"""
print("\n=== 測試 InsightFace 模型 ===")
try:
# 創建測試圖像(隨機數據)
test_image = np.random.randint(0, 255, (640, 480, 3), dtype=np.uint8)
print(f"✅ 創建測試圖像: {test_image.shape}")
# 初始化模型
print("正在初始化 InsightFace 模型...")
model = insightface.app.FaceAnalysis(name="buffalo_l")
model.prepare(ctx_id=-1) # -1 表示 CPU
print("✅ InsightFace 模型初始化成功")
# 測試模型推理(使用隨機圖像)
print("正在進行模型推理測試...")
faces = model.get(test_image)
print(f"✅ 模型推理完成,檢測到 {len(faces)} 個人臉")
if len(faces) > 0:
face = faces[0]
print(f"✅ 人臉屬性:")
print(f" - 邊界框: {face.bbox}")
print(f" - 置信度: {face.det_score:.4f}")
print(
f" - 嵌入向量維度: {face.embedding.shape if hasattr(face, 'embedding') else 'N/A'}"
)
if hasattr(face, "age"):
print(f" - 年齡: {face.age}")
if hasattr(face, "gender"):
print(f" - 性別: {face.gender}")
if hasattr(face, "pose"):
print(f" - 姿態: {face.pose}")
return True
except Exception as e:
print(f"❌ InsightFace 模型測試失敗: {e}")
return False
def test_face_processor():
"""測試人臉處理器"""
print("\n=== 測試人臉處理器 ===")
try:
# 導入處理器
from scripts.face_recognition_processor import FaceRecognitionProcessor
# 初始化處理器
print("正在初始化人臉識別處理器...")
processor = FaceRecognitionProcessor()
# 加載模型(不使用 MPS
print("正在加載模型...")
processor.load_models(use_mps=False)
print(f"✅ 處理器初始化成功")
print(f" - 啟用識別: {processor.enable_recognition}")
print(f" - 啟用追蹤: {processor.enable_tracking}")
print(f" - 啟用聚類: {processor.enable_clustering}")
# 創建測試視頻數據
test_video_data = {
"video_path": "/tmp/test_video.mp4", # 虛擬路徑
"video_uuid": "test_video_001",
"frame_count": 100,
"fps": 30.0,
}
print(f"✅ 創建測試視頻數據: {test_video_data['video_uuid']}")
# 測試處理器方法
print("測試處理器方法...")
# 測試人臉檢測
test_image = np.random.randint(0, 255, (640, 480, 3), dtype=np.uint8)
detections = processor.detect_faces(test_image)
print(f"✅ 人臉檢測測試完成,檢測到 {len(detections)} 個人臉")
if len(detections) > 0:
detection = detections[0]
print(f"✅ 檢測結果示例:")
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)}")
else:
print(f" - 嵌入向量: N/A")
return True
except Exception as e:
print(f"❌ 人臉處理器測試失敗: {e}")
import traceback
traceback.print_exc()
return False
def test_api_endpoints():
"""測試 API 端點配置"""
print("\n=== 測試 API 端點配置 ===")
try:
# 檢查 Rust 代碼編譯
print("檢查 Rust 代碼編譯狀態...")
# 讀取 API 代碼
api_file = os.path.join(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
"src",
"api",
"face_recognition.rs",
)
if os.path.exists(api_file):
with open(api_file, "r") as f:
content = f.read()
# 檢查關鍵函數是否存在(根據實際代碼)
endpoints = [
"register_face_api",
"recognize_faces",
"search_faces",
"get_face_details",
"list_faces",
"delete_face",
"get_recognition_results",
"store_recognition_results",
]
found_endpoints = []
for endpoint in endpoints:
if endpoint in content:
found_endpoints.append(endpoint)
print(f"✅ 找到 {len(found_endpoints)}/{len(endpoints)} 個 API 端點:")
for endpoint in found_endpoints:
print(f" - {endpoint}")
if len(found_endpoints) == len(endpoints):
print("✅ 所有 API 端點都已定義")
else:
missing = set(endpoints) - set(found_endpoints)
print(f"⚠️ 缺少端點: {missing}")
# 檢查路由配置
server_file = os.path.join(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
"src",
"api",
"server.rs",
)
if os.path.exists(server_file):
with open(server_file, "r") as f:
content = f.read()
if "face_recognition" in content and "merge" in content:
print("✅ API 路由已正確配置")
else:
print("⚠️ API 路由配置可能不完整")
return True
except Exception as e:
print(f"❌ API 端點測試失敗: {e}")
return False
def main():
"""主測試函數"""
print("=" * 60)
print("人臉識別集成測試")
print("=" * 60)
tests = [
("數據庫連接", test_database_connection),
("InsightFace 模型", test_insightface_model),
("人臉處理器", test_face_processor),
("API 端點配置", test_api_endpoints),
]
results = []
for test_name, test_func in tests:
try:
success = test_func()
results.append((test_name, success))
except Exception as e:
print(f"{test_name} 測試異常: {e}")
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🎉 所有測試通過!人臉識別集成準備就緒。")
return 0
else:
print(f"\n⚠️ 有 {len(results) - passed} 個測試失敗,請檢查問題。")
return 1
if __name__ == "__main__":
sys.exit(main())