✨博客主页:王乐予🎈
✨年轻人要:Living for the moment(活在当下)!💪
🏆推荐专栏:【图像处理】【千锤百炼Python】【深度学习】【排序算法

😺一、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_width
    return focal_length_value

mp_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 * height
            print('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 * height
            print('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 * height
            print('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 * height
            print('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_distance

left_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 math

def distance_finder(focal_length, real_iris_width, iris_width_in_frame):
    distance = (real_iris_width * focal_length) / iris_width_in_frame
    return distance

mp_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_styles

cap = 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 * height
            print('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 * height
            print('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 * height
            print('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 * height
            print('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()
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐