From 7766cfc9beca1d5b348b1081dcca0cc584adfe37 Mon Sep 17 00:00:00 2001 From: Tian jianyong <11429339@qq.com> Date: Thu, 18 Dec 2025 14:50:03 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=A7=92=E5=BA=A6=E6=B5=8B?= =?UTF-8?q?=E9=87=8F=EF=BC=8C=E5=BB=B6=E9=95=BF=E4=BA=8C=E7=BB=B4=E7=A0=81?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.yaml | 2 +- face_rec.py | 103 ++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 77 insertions(+), 28 deletions(-) diff --git a/config.yaml b/config.yaml index cacce64..a416ad2 100644 --- a/config.yaml +++ b/config.yaml @@ -21,7 +21,7 @@ websocket: # 二维码设置 qrcode: image_path: "preview_qrcode_sota.png" # 二维码图片路径 - display_duration: 10 # 显示持续时间(秒) + display_duration: 30 # 显示持续时间(秒) video: path: "exhibition.mp4" # 视频文件路径 diff --git a/face_rec.py b/face_rec.py index 01f397f..0f9c6bd 100644 --- a/face_rec.py +++ b/face_rec.py @@ -476,7 +476,23 @@ class FaceRecognitionSystem: return Image.composite(top, base, mask) def _draw_rounded_rect(self, draw, box, radius, fill, outline=None, width=0): - draw.rounded_rectangle(box, radius=radius, fill=fill, outline=outline, width=width) + # 兼容旧版本PIL,手动绘制圆角矩形 + x1, y1, x2, y2 = box + + # 绘制主体部分 + draw.rectangle([x1+radius, y1, x2-radius, y2], fill=fill, outline=outline, width=width) + draw.rectangle([x1, y1+radius, x2, y2-radius], fill=fill, outline=outline, width=width) + + # 绘制四个角的圆弧 + if radius > 0: + # 左上角 + draw.ellipse([x1, y1, x1+2*radius, y1+2*radius], fill=fill, outline=outline, width=width) + # 右上角 + draw.ellipse([x2-2*radius, y1, x2, y1+2*radius], fill=fill, outline=outline, width=width) + # 左下角 + draw.ellipse([x1, y2-2*radius, x1+2*radius, y2], fill=fill, outline=outline, width=width) + # 右下角 + draw.ellipse([x2-2*radius, y2-2*radius, x2, y2], fill=fill, outline=outline, width=width) def _draw_shadow(self, image, box, radius, offset=(0, 4), blur=10, shadow_color=(0,0,0,50)): # Create a separate shadow layer @@ -1242,38 +1258,71 @@ class FaceRecognitionSystem: def detect_faces(self, frame: np.ndarray) -> Optional[Dict[str, Any]]: """检测人脸""" try: + import requests + # 将帧编码为JPEG _, img_encoded = cv2.imencode('.jpg', frame) - - # 调用CompreFace检测API - result = self.detection_service.detect(img_encoded.tobytes()) - - if result and 'result' in result and len(result['result']) > 0: - faces = result['result'] - - # 过滤掉太小的人脸 - min_size = self.config['face_detection']['min_face_size'] - valid_faces = [] + + # 构建CompreFace REST API URL + api_url = f"{self.config['compreface']['host']}:{self.config['compreface']['port']}/api/v1/detection/detect" + + # 准备请求参数 + params = { + 'face_plugins': 'pose' # 启用pose插件 + } + + # 准备请求头 + headers = { + 'x-api-key': self.config['compreface']['detection_api_key'] + } + + # 发送请求 + files = { + 'file': ('image.jpg', img_encoded.tobytes(), 'image/jpeg') + } + + response = requests.post(api_url, headers=headers, files=files, params=params) + + if response.status_code == 200: + result = response.json() - # 获取角度阈值 - max_yaw = self.config['face_detection'].get('max_yaw', 30.0) - max_pitch = self.config['face_detection'].get('max_pitch', 30.0) + if result and 'result' in result and len(result['result']) > 0: + faces = result['result'] - for face in faces: - # 检查人脸尺寸 - face_width = face['box']['x_max'] - face['box']['x_min'] - face_height = face['box']['y_max'] - face['box']['y_min'] + # 过滤掉太小的人脸 + min_size = self.config['face_detection']['min_face_size'] + valid_faces = [] - if face_width >= min_size and face_height >= min_size: - # 临时记录face数据,查看是否有pose信息 - self.logger.debug(f"检测到人脸数据: {list(face.keys())}") - if 'pose' in face: - self.logger.debug(f"Pose数据: {face['pose']}") - valid_faces.append(face) + # 获取角度阈值 + max_yaw = self.config['face_detection'].get('max_yaw', 30.0) + max_pitch = self.config['face_detection'].get('max_pitch', 30.0) - if valid_faces: - # 返回第一个(最大的)人脸 - return valid_faces[0] + for face in faces: + # 检查人脸尺寸 + face_width = face['box']['x_max'] - face['box']['x_min'] + face_height = face['box']['y_max'] - face['box']['y_min'] + + if face_width >= min_size and face_height >= min_size: + # 检查人脸角度 + pose = face.get('pose', {}) + yaw = pose.get('yaw', 0.0) + pitch = pose.get('pitch', 0.0) + + # 记录pose数据 + self.logger.debug(f"检测到人脸数据: {list(face.keys())}") + if 'pose' in face: + self.logger.debug(f"Pose数据: yaw={yaw:.1f}°, pitch={pitch:.1f}°, roll={pose.get('roll', 0.0):.1f}°") + + # 判断是否为正脸 + if abs(yaw) <= max_yaw and abs(pitch) <= max_pitch: + valid_faces.append(face) + self.logger.debug(f"人脸角度检查通过: yaw={yaw:.1f}°, pitch={pitch:.1f}°") + else: + self.logger.debug(f"人脸角度超出范围,跳过: yaw={yaw:.1f}°(阈值±{max_yaw}°), pitch={pitch:.1f}°(阈值±{max_pitch}°)") + + if valid_faces: + # 返回第一个(最大的)人脸 + return valid_faces[0] return None