opencv-mediapipe人脸检测-颜值打分+摄像头实时

本文介绍了如何利用Mediapipe库实现摄像头实时的人脸颜值评估,通过计算五官比例、三庭比例、达芬奇比例等指标,详细展示了关键点检测、面部特征分析和美观度计算的过程。

颜值打分

定义可视化图像函数
导入三维人脸关键点检测模型
导入可视化函数和可视化样式
将图像模型输入,获取预测结果
BGR转RGB
将RGB图像输入模型,获取预测结果
预测人人脸个数
获取脸上关键点轮廓的坐标,并且将相应的坐标标注出来,在标注点之间绘制连线(例如:左眼左眼角的识别点标号为33号)

# 颜值打分--五眼指标
import cv2 as cv
import  mediapipe as mp
import numpy as np
from tqdm import tqdm
import time
import  matplotlib.pyplot as plt

# 定义可视化图像函数
def look_img(img):
    img_RGB=cv.cvtColor(img,cv.COLOR_BGR2RGB)
    plt.imshow(img_RGB)
    plt.show()

# 导入三维人脸关键点检测模型
mp_face_mesh=mp.solutions.face_mesh
# help(mp_face_mesh.FaceMesh)

model=mp_face_mesh.FaceMesh(
    static_image_mode=True,#TRUE:静态图片/False:摄像头实时读取
    refine_landmarks=True,#使用Attention Mesh模型
    max_num_faces=40,
    min_detection_confidence=0.5, #置信度阈值,越接近1越准
    min_tracking_confidence=0.5,#追踪阈值
)


# 导入可视化函数和可视化样式
mp_drawing=mp.solutions.drawing_utils
# mp_drawing_styles=mp.solutions.drawing_styles
draw_spec=mp_drawing.DrawingSpec(thickness=2,circle_radius=1,color=[66,77,229])

img=cv.imread("img.png")


# 将图像模型输入,获取预测结果

# BGR转RGB
img_RGB=cv.cvtColor(img,cv.COLOR_BGR2RGB)
scaler=1
h,w=img.shape[0],img.shape[1]
# 将RGB图像输入模型,获取预测结果

results=model.process(img_RGB)
# # 预测人人脸个数
# len(results.multi_face_landmarks)
#
# print(len(results.multi_face_landmarks))

if results.multi_face_landmarks:
    for face_landmarks  in results.multi_face_landmarks:
        mp_drawing.draw_landmarks(
            image=img,
            landmark_list=face_landmarks,
            connections=mp_face_mesh.FACEMESH_CONTOURS,
            landmark_drawing_spec=draw_spec,
            connection_drawing_spec=draw_spec
        )
        for idx, coord in enumerate(face_landmarks.landmark):
            cx = int(coord.x * w)
            cy = int(coord.y * h)
            img = cv.putText(img, ' FACE DELECTED', (25, 50), cv.FONT_HERSHEY_SIMPLEX, 0.1,
                             (218, 112, 214), 1, 1)
            img = cv.putText(img, str(idx), (cx, cy), cv.FONT_HERSHEY_SIMPLEX, 0.3,
                             (218, 112, 214), 1, 1)

else:
    img = cv.putText(img, 'NO FACE DELECTED', (25, 50), cv.FONT_HERSHEY_SIMPLEX, 1.25,
                     (218, 112, 214), 1, 8)
look_img(img)

cv.imwrite('face_id.jpg',img)

# 连轮廓最左侧点
FL=results.multi_face_landmarks[0].landmark[234];
FL_X,FL_Y=int(FL.x*w),int(FL.y*h);FL_Color=(234,0,255)
img=cv.circle(img,(FL_X,FL_Y),20,FL_Color,-1)
look_img(img)


# 脸上侧边缘
FT=results.multi_face_landmarks[0].landmark[10];#  10 坐标为上图中标注的点的序号
FT_X,FT_Y=int(FT.x*w),int(FT.y*h);FT_Color=(231,141,181)
img=cv.circle(img,(FT_X,FT_Y),20,FT_Color,-1)
look_img(img)


# 下侧边缘
FB=results.multi_face_landmarks[0].landmark[152];#  152 坐标为上图中标注的点的序号
FB_X,FB_Y=int(FB.x*w),int(FB.y*h);FB_Color=(231,141,181)
img=cv.circle(img,(FB_X,FB_Y),20,FB_Color,-1)
look_img(img)

# 右侧
FR=results.multi_face_landmarks[0].landmark[454];#  454 坐标为上图中标注的点的序号
FR_X,FR_Y=int(FR.x*w),int(FR.y*h);FR_Color=(0,255,0)
img=cv.circle(img,(FR_X,FR_Y),20,FR_Color,-1)
look_img(img)

# 左眼左眼角
ELL=results.multi_face_landmarks[0].landmark[33];#  33坐标为上图中标注的点的序号
ELL_X,ELL_Y=int(ELL.x*w),int(ELL.y*h);ELL_Color=(0,255,0)
img=cv.circle(img,(ELL_X,ELL_Y),20,ELL_Color,-1)
look_img(img)

#左眼右眼角
ELR=results.multi_face_landmarks[0].landmark[133];#  133坐标为上图中标注的点的序号
ELR_X,ELR_Y=int(ELR.x*w),int(ELR.y*h);ELR_Color=(0,255,0)
img=cv.circle(img,(ELR_X,ELR_Y),20,ELR_Color,-1)
look_img(img)

# 右眼左眼角362
ERL=results.multi_face_landmarks[0].landmark[362];#  133坐标为上图中标注的点的序号
ERL_X,ERL_Y=int(ERL.x*w),int(ERL.y*h);ERL_Color=(233,255,128)
img=cv.circle(img,(ERL_X,ERL_Y),20,ERL_Color,-1)
look_img(img)

# 右眼右眼角263
ERR=results.multi_face_landmarks[0].landmark[263];#  133坐标为上图中标注的点的序号
ERR_X,ERR_Y=int(ERR.x*w),int(ERR.y*h);ERR_Color=(23,255,128)
img=cv.circle(img,(ERR_X,ERR_Y),20,ERR_Color,-1)
look_img(img)


# 从左往右六个点的横坐标
Six_X=np.array([FL_X,ELL_X,ELR_X,ERL_X,ERR_X,FR_X])

# 从最左到最右的距离
Left_Right=FR_X-FL_X
# 从左向右六个点的间隔的五个距离一并划归
Five_Distance=100*np.diff(Six_X)/Left_Right

# 两眼宽度的平均值
Eye_Width_Mean=np.mean((Five_Distance[1],Five_Distance[3]))

# 五个距离分别与两眼宽度均值的差
Five_Eye_Diff=Five_Distance-Eye_Width_Mean

# 求L2范数,作为颜值的指标
Five_Eye_Metrics=np.linalg.norm(Five_Eye_Diff)

cv.line(img,(FL_X,FT_Y),(FL_X,FB_Y),FL_Color,3)
cv.line(img,(ELL_X,FT_Y),(ELL_X,FB_Y),ELL_Color,3)
cv.line(img,(ELR_X,FT_Y),(ELR_X,FB_Y),ELR_Color,3)
cv.line(img,(ERL_X,FT_Y),(ERL_X,FB_Y),ERL_Color,3)
cv.line(img,(ERR_X,FT_Y),(ERR_X,FB_Y),ERR_Color,3)
cv.line(img,(FR_X,FT_Y),(FR_X,FB_Y),FR_Color,3)
cv.line(img,(FL_X,FT_Y),(FR_X,FT_Y),FT_Color,3)
cv.line(img,(FL_X,FB_Y),(FR_X,FB_Y),FB_Color,3)

scaler=1
img = cv.putText(img, 'Five Eye Metrics{:.2f}'.format(Five_Eye_Metrics), (25, 50), cv.FONT_HERSHEY_SIMPLEX, 1,
                 (218, 112, 214), 6, 6)
img = cv.putText(img, 'Distance 1{:.2f}'.format(Five_Eye_Diff[0]), (25, 100), cv.FONT_HERSHEY_SIMPLEX, 1,
                 (218, 112, 214), 5, 5)
img = cv.putText(img, 'Distance 1{:.2f}'.format(Five_Eye_Diff[2]), (25, 150), cv.FONT_HERSHEY_SIMPLEX, 1,
                 (218, 112, 214), 4, 4)
img = cv.putText(img, 'Distance 1{:.2f}'.format(Five_Eye_Diff[4]), (25, 200), cv.FONT_HERSHEY_SIMPLEX,1,
                 (218, 112, 214), 3, 4)
look_img(img)
cv.imwrite("yanzhi.jpg",img)




在这里插入图片描述

摄像头实时检测颜值打分

最后一部分代码是调用摄像头的模板,可以直接使用
关键步骤在代码注释中有体现

import cv2 as cv
import  mediapipe as mp
import numpy as np
from tqdm import tqdm
import time
import  matplotlib.pyplot as plt

# 定义可视化图像函数
def look_img(img):
    img_RGB=cv.cvtColor(img,cv.COLOR_BGR2RGB)
    plt.imshow(img_RGB)
    plt.show()

# 导入三维人脸关键点检测模型
mp_face_mesh=mp.solutions.face_mesh
# help(mp_face_mesh.FaceMesh)

model=mp_face_mesh.FaceMesh(
    static_image_mode=False,#TRUE:静态图片/False:摄像头实时读取
    refine_landmarks=True,#使用Attention Mesh模型
    max_num_faces=5,
    min_detection_confidence=0.5, #置信度阈值,越接近1越准
    min_tracking_confidence=0.5,#追踪阈值
)


# 导入可视化函数和可视化样式
mp_drawing=mp.solutions.drawing_utils
# mp_drawing_styles=mp.solutions.drawing_styles
draw_spec=mp_drawing.DrawingSpec(thickness=2,circle_radius=1,color=[66,77,229])
landmark_drawing_spec=mp_drawing.DrawingSpec(thickness=1,circle_radius=2,color=[66,77,229])
# 轮廓可视化
connection_drawing_spec=mp_drawing.DrawingSpec(thickness=2,circle_radius=1,color=[233,155,6])



# 处理帧函数
def process_frame(img):
    start_time = time.time()
    scaler = 1
    h, w = img.shape[0], img.shape[1]
    img_RGB = cv.cvtColor(img, cv.COLOR_BGR2RGB)
    results = model.process(img_RGB)
    if results.multi_face_landmarks:
        # for face_landmarks in results.multi_face_landmarks:
            # 连轮廓最左侧点
            FL = results.multi_face_landmarks[0].landmark[234];
            FL_X, FL_Y = int(FL.x * w), int(FL.y * h);
            FL_Color = (234, 0, 255)
            img = cv.circle(img, (FL_X, FL_Y), 5, FL_Color, -1)
            look_img(img)

            # 脸上侧边缘
            FT = results.multi_face_landmarks[0].landmark[10];  # 10 坐标为上图中标注的点的序号
            FT_X, FT_Y = int(FT.x * w), int(FT.y * h);
            FT_Color = (231, 141, 181)
            img = cv.circle(img, (FT_X, FT_Y), 5, FT_Color, -1)
            look_img(img)

            # 下侧边缘
            FB = results.multi_face_landmarks[0].landmark[152];  # 152 坐标为上图中标注的点的序号
            FB_X, FB_Y = int(FB.x * w), int(FB.y * h);
            FB_Color = (231, 141, 181)
            img = cv.circle(img, (FB_X, FB_Y), 5, FB_Color, -1)
            look_img(img)

            # 右侧
            FR = results.multi_face_landmarks[0].landmark[454];  # 454 坐标为上图中标注的点的序号
            FR_X, FR_Y = int(FR.x * w), int(FR.y * h);
            FR_Color = (0, 255, 0)
            img = cv.circle(img, (FR_X, FR_Y), 5, FR_Color, -1)
            look_img(img)

            # 左眼左眼角
            ELL = results.multi_face_landmarks[0].landmark[33];  # 33坐标为上图中标注的点的序号
            ELL_X, ELL_Y = int(ELL.x * w), int(ELL.y * h);
            ELL_Color = (0, 255, 0)
            img = cv.circle(img, (ELL_X, ELL_Y), 5, ELL_Color, -1)
            look_img(img)

            # 左眼右眼角
            ELR = results.multi_face_landmarks[0].landmark[133];  # 133坐标为上图中标注的点的序号
            ELR_X, ELR_Y = int(ELR.x * w), int
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值