基于opencv+python手势识别人脸识别及对比系统
作者:唐陈倞男
2024年5月10日
作者本人是个大三学生由于有门课程是机器视觉,这算是我自己制作的期末作业吧,完全是从零开始一步一步摸索来的,整个程序是自己一个人做的所以如果有做得不好的地方请谅解,欢迎讨论问题,若有不会的有误的或者我没有讲清楚的地方请留言,我看到会尽量回复的
1. 人脸识别功能
def detect_faces_in_frame(self, frame):
# 在帧中检测人脸并绘制矩形框
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
face_results = self.mp_face_detection.process(frame_rgb)
face_detected = False
if face_results.detections:
for detection in face_results.detections:
bboxC = detection.location_data.relative_bounding_box
ih, iw, _ = frame.shape
x, y, w, h = int(bboxC.xmin * iw), int(bboxC.ymin * ih), int(bboxC.width * iw), int(bboxC.height * ih)
平滑处理
smoothing_alpha = 0.7
x = int(smoothing_alpha * self.prev_x + (1 - smoothing_alpha) * x)
y = int(smoothing_alpha * self.prev_y + (1 - smoothing_alpha) * y)
w = int(smoothing_alpha * self.prev_w + (1 - smoothing_alpha) * w)
h = int(smoothing_alpha * self.prev_h + (1 - smoothing_alpha) * h)
self.prev_x, self.prev_y, self.prev_w, self.prev_h = x, y, w, h
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
face_detected = True
if face_detected:
cv2.putText(frame, 'Faces are recognized', (30, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
else:
cv2.putText(frame, 'No face', (30, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
return frame
这个函数检测视频帧中的人脸并在检测到的人脸周围绘制矩形框。它使用了 MediaPipe 库中的人脸检测器。首先,将视频帧转换为 RGB 格式,然后使用人脸检测器检测人脸。如果检测到了人脸,则在每个检测到的人脸周围绘制一个矩形框,并使用平滑因子对矩形框进行平滑处理。最后,在视频帧上方添加文本以指示检测到的人脸数量。
1.1人脸识别:
1.1.1 RGB 格式图像处理
将输入的视频帧从 BGR 格式(OpenCV 默认格式)转换为 RGB 格式。MediaPipe 的模型需要输入 RGB 格式的图像进行处理。
1.1.2 人脸检测:
face_results = self.mp_face_detection.process(frame_rgb):
使用 MediaPipe 提供的人脸检测模型 mp_face_detection 对 RGB 格式的视频帧进行人脸检测。process 方法会返回检测到的人脸结果,包括每个检测到的人脸的位置信息。
关于这一方面之前我用的是级联分类器,但是我实验很多次之后,识别错误的概率很大,所以换成了我认为更好的mediapipe,具体感兴趣的话可以去网上搜一搜
1.1.3人脸检测标志:
face_detected = False:
初始化一个布尔变量 face_detected,用于标记当前帧是否检测到了人脸。
1.2关于平滑处理:
在人脸识别中,平滑处理通常用于减少检测结果的抖动或不稳定性,使其在连续帧之间更稳定。具体来说,平滑处理通常涉及到对当前帧的检测结果与前几帧的结果进行加权平均,从而使结果更加平滑。
在这个代码中,平滑处理应用于人脸检测的矩形框位置。具体算法如下:
对于每一帧检测到的人脸矩形框位置,使用一个指数加权移动平均方法进行平滑处理。
使用一个平滑因子(在代码中为 smoothing_alpha)来调节前一帧的位置和当前帧的位置之间的权重。这个平滑因子通常取值在 0 到 1 之间,值越接近 1,表示对前一帧的权重越大,值越接近 0,表示对当前帧的权重越大。
对于每一帧,使用下面的公式进行平滑处理:
smoothed_x = smoothing_alpha * prev_x + (1 - smoothing_alpha) * current_x
smoothed_y = smoothing_alpha * prev_y + (1 - smoothing_alpha) * current_y
smoothed_w = smoothing_alpha * prev_w + (1 - smoothing_alpha) * current_w
smoothed_h = smoothing_alpha * prev_h + (1 - smoothing_alpha) * current_h
其中,prev_x、prev_y、prev_w、prev_h 分别是前一帧矩形框的位置和尺寸,current_x、current_y、current_w、current_h 是当前帧矩形框的位置和尺寸。
最终,使用经过平滑处理的位置和尺寸来绘制人脸的矩形框,从而达到减少抖动的效果
2.人脸对比
这个函数用于比较当前帧中检测到的人脸与之前保存的人脸数据之间的相似度。首先,它检查是否选择了人脸识别功能。然后,它获取当前帧中检测到的人脸的关键点特征,并计算它们与之前保存的人脸数据的关键点之间的距离。最后,它选择距离最小的人脸作为匹配的人脸,并在界面上显示匹配的人脸名称。
2.1关于人脸对比:
def compare_faces_button_click(self):
ret, frame = self.cap.read()
# 检查是否选中了人脸识别功能
if self.selected_detections['face']:
if ret:
# 人脸关键点检测
current_face_features = self.get_face_features(frame)
if current_face_features is not None:
current_face_landmarks = current_face_features["landmarks"]
matched_face = None
min_distance = float('inf')
for face_name, saved_face_features in self.saved_faces.items():
saved_face_landmarks = saved_face_features["landmarks"]
distance = self.compare_face_landmarks(saved_face_landmarks, current_face_landmarks)
if distance < min_distance:
min_distance = distance
matched_face = face_name
if matched_face is not None:
self.update_info_label("人脸匹配", f"你好: {matched_face}")
else:
self.update_info_label("人脸匹配", "数据库中缺失该数据!")
else:
self.update_info_label("错误", "请先开启人脸识别功能!")
首先,通过 get_face_features 方法从当前帧中提取人脸的特征。如果成功提取到特征,则获取当前帧中的人脸关键点坐标。
然后,遍历已保存的人脸数据集 self.saved_faces,对每一个已保存的人脸进行比对。
对于每一个已保存的人脸,获取其特征数据中的人脸关键点坐标。
使用 compare_face_landmarks 方法计算当前帧中的人脸关键点坐标与已保存人脸的关键点坐标之间的距离(或者其他相似度度量),得到一个距离值。