diff --git a/config.yaml b/config.yaml index 8ab9456..0de4239 100644 --- a/config.yaml +++ b/config.yaml @@ -44,4 +44,9 @@ logging: level: "INFO" # DEBUG, INFO, WARNING, ERROR file: "face_recognition.log" max_bytes: 10485760 # 10MB - backup_count: 5 \ No newline at end of file + backup_count: 5 + + +# 中文字体设置 +display: + font_path: "/usr/share/fonts/truetype/noto/NotoMono-Regular.ttf" \ No newline at end of file diff --git a/main.py b/main.py index b64bfb3..99a7ea6 100644 --- a/main.py +++ b/main.py @@ -12,6 +12,7 @@ from compreface import CompreFace from compreface.service import RecognitionService, DetectionService import time from collections import defaultdict +from PIL import Image, ImageDraw, ImageFont class FaceRecognitionSystem: @@ -66,6 +67,12 @@ class FaceRecognitionSystem: self.last_fps_time = time.time() self.fps_counter = 0 + # 加载中文字体 + self.font_path = self._get_chinese_font() + self.font_small = ImageFont.truetype(self.font_path, 20) + self.font_medium = ImageFont.truetype(self.font_path, 24) + self.font_large = ImageFont.truetype(self.font_path, 28) + self.logger.info("人脸识别系统初始化完成") def _setup_logging(self): @@ -95,6 +102,51 @@ class FaceRecognitionSystem: self.logger.addHandler(file_handler) self.logger.addHandler(console_handler) + def _get_chinese_font(self) -> str: + """获取中文字体路径""" + import platform + import os + + system = platform.system() + + # Windows系统 + if system == "Windows": + font_paths = [ + "C:/Windows/Fonts/msyh.ttc", # 微软雅黑 + "C:/Windows/Fonts/simhei.ttf", # 黑体 + "C:/Windows/Fonts/simsun.ttc", # 宋体 + ] + # macOS系统 + elif system == "Darwin": + font_paths = [ + "/System/Library/Fonts/PingFang.ttc", # 苹方 + "/System/Library/Fonts/STHeiti Medium.ttc", # 黑体 + "/Library/Fonts/Arial Unicode.ttf", + ] + # Linux系统 + else: + font_paths = [ + "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc", + "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc", + ] + + # 查找可用的字体 + for font_path in font_paths: + if os.path.exists(font_path): + self.logger.info(f"使用中文字体: {font_path}") + return font_path + + # 如果没找到,尝试使用配置文件中的字体路径 + if 'font_path' in self.config.get('display', {}): + custom_font = self.config['display']['font_path'] + if os.path.exists(custom_font): + self.logger.info(f"使用自定义字体: {custom_font}") + return custom_font + + # 默认使用一个基本字体(不支持中文,但至少不会报错) + self.logger.warning("未找到中文字体,将使用默认字体(可能无法显示中文)") + return "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf" + def _init_compreface(self): """初始化CompreFace SDK""" cf_config = self.config['compreface'] @@ -221,6 +273,20 @@ class FaceRecognitionSystem: return elapsed >= cooldown + def cv2_add_chinese_text(self, img: np.ndarray, text: str, position: Tuple[int, int], + font: ImageFont.FreeTypeFont, text_color: Tuple[int, int, int]) -> np.ndarray: + """在OpenCV图像上添加中文文本""" + # 转换为PIL图像 + img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) + draw = ImageDraw.Draw(img_pil) + + # 绘制文本 + draw.text(position, text, font=font, fill=text_color) + + # 转换回OpenCV格式 + img = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR) + return img + def draw_info_on_frame(self, frame: np.ndarray) -> np.ndarray: """在帧上绘制检测和识别信息""" display_frame = frame.copy() @@ -255,21 +321,20 @@ class FaceRecognitionSystem: # 准备文本 text_lines = [ - f"Name: {name}", - f"Role: {role}", - f"Similarity: {similarity:.2%}" + f"姓名: {name}", + f"角色: {role}", + f"相似度: {similarity:.2%}" ] # 计算文本背景框 - font = cv2.FONT_HERSHEY_SIMPLEX - font_scale = 0.6 - font_thickness = 2 + line_height = 35 padding = 10 - line_height = 30 - # 绘制文本背景 + # 计算所需的背景高度 bg_height = len(text_lines) * line_height + padding * 2 bg_y_start = max(0, y_min - bg_height - 10) + + # 绘制文本背景 cv2.rectangle( display_frame, (x_min, bg_y_start), @@ -285,39 +350,34 @@ class FaceRecognitionSystem: 2 ) - # 绘制文本 + # 使用PIL绘制中文文本 for i, text in enumerate(text_lines): - y_pos = bg_y_start + padding + (i + 1) * line_height - 5 - cv2.putText( + y_pos = bg_y_start + padding + i * line_height + display_frame = self.cv2_add_chinese_text( display_frame, text, (x_min + padding, y_pos), - font, - font_scale, - (255, 255, 255), - font_thickness + self.font_medium, + (255, 255, 255) ) # 绘制状态信息面板 - panel_height = 180 + panel_height = 200 panel_bg = np.zeros((panel_height, w, 3), dtype=np.uint8) panel_bg[:] = (40, 40, 40) # 状态信息 - font = cv2.FONT_HERSHEY_SIMPLEX - font_scale = 0.5 - font_thickness = 1 - text_color = (255, 255, 255) - y_offset = 25 - x_offset = 10 + y_offset = 30 + x_offset = 15 + line_spacing = 30 status_texts = [ - f"FPS: {self.display_info['fps']:.1f}", - f"Frame: {self.display_info['frame_count']}", - f"Quality: {self.display_info['quality']:.1f}", - f"Face Detected: {'Yes' if self.display_info['face_detected'] else 'No'}", - f"Robot Speaking: {'Yes' if self.robot_status['is_speaking'] else 'No'}", - f"Robot Thinking: {'Yes' if self.robot_status['is_thinking'] else 'No'}", + f"帧率: {self.display_info['fps']:.1f} FPS", + f"帧数: {self.display_info['frame_count']}", + f"质量: {self.display_info['quality']:.1f}", + f"检测到人脸: {'是' if self.display_info['face_detected'] else '否'}", + f"机器人说话: {'是' if self.robot_status['is_speaking'] else '否'}", + f"机器人思考: {'是' if self.robot_status['is_thinking'] else '否'}", ] # 如果人脸持续出现,显示倒计时 @@ -325,17 +385,16 @@ class FaceRecognitionSystem: elapsed = (datetime.now() - self.face_present_start).total_seconds() face_duration = self.config['face_detection']['face_present_duration'] remaining = max(0, face_duration - elapsed) - status_texts.append(f"Recognition in: {remaining:.1f}s") + status_texts.append(f"识别倒计时: {remaining:.1f}秒") + # 使用PIL绘制中文状态文本 for i, text in enumerate(status_texts): - cv2.putText( + panel_bg = self.cv2_add_chinese_text( panel_bg, text, - (x_offset, y_offset + i * 25), - font, - font_scale, - text_color, - font_thickness + (x_offset, y_offset + i * line_spacing), + self.font_small, + (255, 255, 255) ) # 将面板添加到画面底部 @@ -442,8 +501,26 @@ class FaceRecognitionSystem: self.logger.info("开始处理视频流") - # 创建显示窗口 - cv2.namedWindow('Face Recognition System', cv2.WINDOW_NORMAL) + # 创建显示窗口并最大化 + window_name = 'Face Recognition System' + cv2.namedWindow(window_name, cv2.WINDOW_NORMAL) + + # 设置窗口为全屏或最大化 + # 方法1: 全屏模式 + # cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) + + # 方法2: 最大化窗口(推荐) + cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_NORMAL) + # 获取屏幕分辨率并设置窗口大小 + try: + import screeninfo + screen = screeninfo.get_monitors()[0] + cv2.resizeWindow(window_name, screen.width, screen.height) + cv2.moveWindow(window_name, 0, 0) + except: + # 如果screeninfo不可用,尝试设置一个较大的窗口 + cv2.resizeWindow(window_name, 1920, 1080) + self.logger.warning("无法获取屏幕分辨率,使用默认窗口大小") try: while True: @@ -585,7 +662,7 @@ class FaceRecognitionSystem: # 绘制信息并显示 display_frame = self.draw_info_on_frame(frame) - cv2.imshow('Face Recognition System', display_frame) + cv2.imshow(window_name, display_frame) # 检查键盘输入 key = cv2.waitKey(1) & 0xFF