✨博客主页:王乐予🎈
✨年轻人要:Living for the moment(活在当下)!💪
🏆推荐专栏:【图像处理】【千锤百炼Python】【深度学习】【排序算法】
目录
- 😺一、MediaPipe概述
- 😺二、MediaPipe人脸关键点检测概述
- 😺三、实现过程
😺一、MediaPipe概述
MediaPipe 是一款由 Google Research 开发并开源的多媒体机器学习模型应用框架。
MediaPipe目前支持的解决方案(Solution)及支持的平台如下图所示:
😺二、MediaPipe人脸关键点检测概述
MediaPipe Face Landmarker 任务允许检测图像和视频。可以使用此任务来识别人类的面部表情,应用面部滤镜和效果,并创建虚拟形象。该任务输出 3D 人脸标志。
MediaPipe人脸关键点检测模型包含了478个3D关键点,如下图所示:
人脸标记使用一系列模型来预进行预测。 第一个模型检测人脸,第二个模型在检测到的人脸上实现定位,第三个模型使用这些标记来识别面部特征。
本文将仅使用虹膜区域的关键点进行后续处理。
😺三、实现过程
人眼虹膜直径范围大概在11.7±0.5mm。因此我们可以利用相似三角形计算人眼与摄像头传感器的距离,如下图所示:
首先我们需要计算相机焦距,因此需要得到d、h2和h1三个参数。h1参数为11.7±0.5mm,h2参数可以通过计算得到,因此我们需要先拍摄一张图片,并且已知虹膜距传感器的距离。
"""
Calculate_Focal_Length.py
"""import mediapipe as mp
import numpy as np
import cv2
import math# 计算相机焦距: measured_distance: 物体到相机的距离; real_width: 物体实际宽度; width_in_rf_image: 物体在参考图像中的宽度
def focal_length_finder(measured_distance, real_width, width_in_rf_image):focal_length_value = (width_in_rf_image * measured_distance) / real_widthreturn focal_length_valuemp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(static_image_mode=True, # False处理视频,True处理单张图片max_num_faces=1,refine_landmarks=True,min_detection_confidence=0.5,min_tracking_confidence=0.5) # 静态图片不用设置
img = cv2.imread('./2.jpg')
height, width, channels = np.shape(img)
img_RGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
results = face_mesh.process(img_RGB)
if results.multi_face_landmarks:for face_landmarks in results.multi_face_landmarks:# 绘制虹膜left_eye_iris = [474, 475, 476, 477]right_eye_iris = [469, 470, 471, 472]for i in left_eye_iris: # 绿色点绘制左眼cv2.circle(img, (int(face_landmarks.landmark[i].x * width), int(face_landmarks.landmark[i].y * height)), 2, (0, 255, 0), -1)for i in right_eye_iris: # 蓝色点绘制右眼cv2.circle(img, (int(face_landmarks.landmark[i].x * width), int(face_landmarks.landmark[i].y * height)), 2, (255, 0, 0), -1)# 打印474点的坐标left_eye_iris_474_x, left_eye_iris_474_y = face_landmarks.landmark[474].x * width, face_landmarks.landmark[474].y * heightprint('left_eye_iris_474:', left_eye_iris_474_x, left_eye_iris_474_y)# 打印476点的坐标left_eye_iris_476_x, left_eye_iris_476_y = face_landmarks.landmark[476].x * width, face_landmarks.landmark[476].y * heightprint('left_eye_iris_476:', left_eye_iris_476_x, left_eye_iris_476_y)# 左眼虹膜直径-勾股定理计算474点和476点的斜边长度left_eye_iris_distance = math.sqrt((math.pow(left_eye_iris_476_x - left_eye_iris_474_x, 2) + math.pow(left_eye_iris_476_y - left_eye_iris_474_y, 2)))print('left_eye_iris_distance:', left_eye_iris_distance)# 打印469点的坐标right_eye_iris_469_x, right_eye_iris_469_y = face_landmarks.landmark[469].x * width, face_landmarks.landmark[469].y * heightprint('right_eye_iris_469:', right_eye_iris_469_x, right_eye_iris_469_y)# 打印471点的坐标right_eye_iris_471_x, right_eye_iris_471_y = face_landmarks.landmark[471].x * width, face_landmarks.landmark[471].y * heightprint('right_eye_iris_471:', right_eye_iris_471_x, right_eye_iris_471_y)# 右眼虹膜直径-勾股定理计算469点和471点的斜边长度right_eye_iris_distance = math.sqrt((math.pow(right_eye_iris_471_x - right_eye_iris_469_x, 2) + math.pow(right_eye_iris_471_y - right_eye_iris_469_y, 2)))print('right_eye_iris_distance:', right_eye_iris_distance)measured_distance = 76.2 # 厘米
real_width = 1.17 # 厘米left_width_in_rf_image = left_eye_iris_distance
right_width_in_rf_image = right_eye_iris_distanceleft_focal_point = focal_length_finder(measured_distance, real_width, left_width_in_rf_image)
right_focal_point = focal_length_finder(measured_distance, real_width, right_width_in_rf_image)print('左虹膜测定焦距:', left_focal_point)
print('右虹膜测定焦距:', right_focal_point)# 奥比中光相机焦距:x方向:577.3131205698876 y方向:578.1356175879147
# TTG相机焦距:x方向:922.4361169730964 y方向:918.8584080297207
这里我拍摄了一张图片,命名为2.jpg。通过计算人眼距相机距离为76.2cm,虹膜水平直径为1.17cm,通过代码计算可以得到像素空间下的虹膜直径。这样就可以计算出拍摄所用的相机焦距为920。
已知了相机焦距,通过下面代码就可以计算出人眼距离相机的实时距离:
"""
main.py
"""
import mediapipe as mp
import numpy as np
import cv2
import mathdef distance_finder(focal_length, real_iris_width, iris_width_in_frame):distance = (real_iris_width * focal_length) / iris_width_in_framereturn distancemp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(static_image_mode=False, # False处理视频,True处理单张图片max_num_faces=1,refine_landmarks=True,min_detection_confidence=0.5,min_tracking_confidence=0.5) # 静态图片不用设置mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_stylescap = cv2.VideoCapture(0)
while True:ret, img = cap.read()height, width, channels = np.shape(img)img_RGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)results = face_mesh.process(img_RGB)if results.multi_face_landmarks:for face_landmarks in results.multi_face_landmarks:# 绘制虹膜left_eye_iris = [474, 475, 476, 477]right_eye_iris = [469, 470, 471, 472]for i in left_eye_iris: # 绿色点绘制左眼cv2.circle(img, (int(face_landmarks.landmark[i].x * width), int(face_landmarks.landmark[i].y * height)), 2, (0, 255, 0), -1)for i in right_eye_iris: # 蓝色点绘制右眼cv2.circle(img, (int(face_landmarks.landmark[i].x * width), int(face_landmarks.landmark[i].y * height)), 2, (255, 0, 0), -1)# 打印474点的坐标left_eye_iris_474_x, left_eye_iris_474_y = face_landmarks.landmark[474].x * width, face_landmarks.landmark[474].y * heightprint('left_eye_iris_474:', left_eye_iris_474_x, left_eye_iris_474_y)# 打印476点的坐标left_eye_iris_476_x, left_eye_iris_476_y = face_landmarks.landmark[476].x * width, face_landmarks.landmark[476].y * heightprint('left_eye_iris_476:', left_eye_iris_476_x, left_eye_iris_476_y)# 左眼虹膜直径-勾股定理计算474点和476点的斜边长度left_eye_iris_distance = math.sqrt((math.pow(left_eye_iris_476_x - left_eye_iris_474_x, 2) + math.pow(left_eye_iris_476_y - left_eye_iris_474_y, 2)))print('left_eye_iris_distance:', left_eye_iris_distance)# 打印469点的坐标right_eye_iris_469_x, right_eye_iris_469_y = face_landmarks.landmark[469].x * width, face_landmarks.landmark[469].y * heightprint('right_eye_iris_469:', right_eye_iris_469_x, right_eye_iris_469_y)# 打印471点的坐标right_eye_iris_471_x, right_eye_iris_471_y = face_landmarks.landmark[471].x * width, face_landmarks.landmark[471].y * heightprint('right_eye_iris_471:', right_eye_iris_471_x, right_eye_iris_471_y)# 右眼虹膜直径-勾股定理计算469点和471点的斜边长度right_eye_iris_distance = math.sqrt((math.pow(right_eye_iris_471_x - right_eye_iris_469_x, 2) + math.pow(right_eye_iris_471_y - right_eye_iris_469_y, 2)))print('right_eye_iris_distance:', right_eye_iris_distance)# 计算距离left_distance = distance_finder(920, 1.17, left_eye_iris_distance)right_distance = distance_finder(920, 1.17, right_eye_iris_distance)print('left_distance:', left_distance)print('right_distance:', right_distance)cv2.imshow('faces', img)key = cv2.waitKey(1)if key == ord('q'):break
cap.release()