177 lines
6.2 KiB
Python
177 lines
6.2 KiB
Python
import cv2
|
||
import time
|
||
import argparse
|
||
import numpy as np
|
||
from face_utils import FaceDetector, FaceRecognizer, draw_face_box
|
||
from face_db import FaceDatabase
|
||
from voice_prompt import VoicePrompt
|
||
|
||
def parse_args():
|
||
"""解析命令行参数"""
|
||
parser = argparse.ArgumentParser(description='人脸识别应用')
|
||
parser.add_argument('--camera', type=int, default=0, help='摄像头索引')
|
||
parser.add_argument('--confidence', type=float, default=0.5, help='人脸检测置信度阈值')
|
||
parser.add_argument('--similarity', type=float, default=0.6, help='人脸相似度阈值')
|
||
parser.add_argument('--display_width', type=int, default=640, help='显示窗口宽度')
|
||
parser.add_argument('--display_height', type=int, default=480, help='显示窗口高度')
|
||
return parser.parse_args()
|
||
|
||
def main():
|
||
"""人脸识别应用主函数"""
|
||
args = parse_args()
|
||
|
||
# 初始化组件
|
||
print("正在初始化人脸识别系统...")
|
||
voice = VoicePrompt()
|
||
detector = FaceDetector(conf_thres=args.confidence)
|
||
recognizer = FaceRecognizer(detector=detector, similarity_threshold=args.similarity)
|
||
db = FaceDatabase()
|
||
|
||
# 加载已知人脸特征
|
||
known_faces = db.get_all_features()
|
||
if not known_faces:
|
||
print("警告: 数据库中没有注册的人脸,请先运行注册程序")
|
||
voice.speak("数据库中没有注册的人脸,请先运行注册程序", block=True)
|
||
else:
|
||
print(f"已加载 {len(known_faces)} 个人脸特征")
|
||
|
||
# 打开摄像头
|
||
cap = cv2.VideoCapture(args.camera)
|
||
if not cap.isOpened():
|
||
print("无法打开摄像头")
|
||
return
|
||
|
||
# 设置摄像头分辨率
|
||
cap.set(cv2.CAP_PROP_FRAME_WIDTH, args.display_width)
|
||
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, args.display_height)
|
||
|
||
print("系统初始化完成,开始人脸识别...")
|
||
voice.speak("人脸识别系统已启动", block=True)
|
||
|
||
# 跟踪识别状态,避免重复语音提示
|
||
recognized_persons = {} # {person_id: last_recognition_time}
|
||
recognition_cooldown = 5.0 # 同一个人识别成功后的冷却时间(秒)
|
||
|
||
# 绘制UI相关
|
||
font = cv2.FONT_HERSHEY_SIMPLEX
|
||
font_scale = 0.6
|
||
line_thickness = 2
|
||
fps_history = []
|
||
|
||
try:
|
||
while True:
|
||
# 计时(用于计算FPS)
|
||
start_time = time.time()
|
||
|
||
# 读取摄像头帧
|
||
ret, frame = cap.read()
|
||
if not ret:
|
||
print("无法获取摄像头画面")
|
||
break
|
||
|
||
# 镜像翻转以便更直观
|
||
frame = cv2.flip(frame, 1)
|
||
|
||
# 创建显示帧
|
||
display_frame = frame.copy()
|
||
|
||
# 检测人脸
|
||
faces = detector.detect_faces(frame)
|
||
|
||
# 处理每个检测到的人脸
|
||
for face_box in faces:
|
||
# 识别人脸
|
||
result = recognizer.identify_face(frame, known_faces, face_box[:4])
|
||
|
||
# 如果识别成功
|
||
if result:
|
||
person_id, name, similarity = result
|
||
|
||
# 绘制人脸框和标签(绿色表示识别成功)
|
||
draw_face_box(display_frame, face_box, name, similarity, color=(0, 255, 0))
|
||
|
||
# 检查是否需要播放语音提示(避免频繁重复)
|
||
current_time = time.time()
|
||
if (person_id not in recognized_persons or
|
||
current_time - recognized_persons[person_id] > recognition_cooldown):
|
||
|
||
# 更新识别时间
|
||
recognized_persons[person_id] = current_time
|
||
|
||
# 播放语音提示
|
||
voice.speak(f"您好,{name}", block=False)
|
||
print(f"识别成功: {name} (相似度: {similarity:.2f})")
|
||
else:
|
||
# 未识别的人脸使用红色框
|
||
draw_face_box(display_frame, face_box, "未知", color=(0, 0, 255))
|
||
|
||
# 计算并显示FPS
|
||
end_time = time.time()
|
||
fps = 1.0 / (end_time - start_time)
|
||
fps_history.append(fps)
|
||
if len(fps_history) > 30:
|
||
fps_history.pop(0)
|
||
avg_fps = sum(fps_history) / len(fps_history)
|
||
|
||
cv2.putText(
|
||
display_frame,
|
||
f"FPS: {avg_fps:.1f}",
|
||
(10, 30),
|
||
font,
|
||
font_scale,
|
||
(0, 255, 255),
|
||
line_thickness
|
||
)
|
||
|
||
# 显示数据库信息
|
||
cv2.putText(
|
||
display_frame,
|
||
f"数据库: {len(known_faces)} 个人脸",
|
||
(10, 60),
|
||
font,
|
||
font_scale,
|
||
(0, 255, 255),
|
||
line_thickness
|
||
)
|
||
|
||
# 显示操作指南
|
||
cv2.putText(
|
||
display_frame,
|
||
"按ESC退出, 按R刷新数据库",
|
||
(10, display_frame.shape[0] - 10),
|
||
font,
|
||
font_scale,
|
||
(255, 255, 255),
|
||
line_thickness
|
||
)
|
||
|
||
# 显示图像
|
||
cv2.imshow("人脸识别系统", display_frame)
|
||
|
||
# 按键处理
|
||
key = cv2.waitKey(1) & 0xFF
|
||
|
||
# 按ESC键退出
|
||
if key == 27:
|
||
break
|
||
|
||
# 按R键刷新数据库
|
||
elif key == ord('r'):
|
||
print("正在刷新人脸数据库...")
|
||
known_faces = db.get_all_features()
|
||
print(f"已刷新: 加载了 {len(known_faces)} 个人脸特征")
|
||
voice.speak("已刷新人脸数据库", block=False)
|
||
|
||
except Exception as e:
|
||
print(f"发生错误: {e}")
|
||
|
||
finally:
|
||
# 释放资源
|
||
cap.release()
|
||
cv2.destroyAllWindows()
|
||
db.close()
|
||
print("人脸识别系统已关闭")
|
||
|
||
if __name__ == "__main__":
|
||
main()
|