计算机视觉入门(基础篇:利用mediapipe进行face mesh)

img
本代码基于 Advance Computer Vision with Python 进行修改,更加适合中国宝宝体质

我的相关代码及数据集已经上传GitHub仓库,欢迎使用 Advance-Computer-Vision-with-Python

Basics.py

import cv2
import mediapipe as mp
import time

# 打开视频文件
cap = cv2.VideoCapture(
    "E:\\Advance Computer Vision with Python\\main\\Chapter 3 Face Detection\\Videos\\3.mp4"
)
if not cap.isOpened():
    print("Error: Could not open video.")
    exit()

pTime = 0

# 初始化 MediaPipe 的绘图工具和面部网格模型
mpDraw = mp.solutions.drawing_utils  # 导入 MediaPipe 的绘图工具模块
mpFaceMesh = mp.solutions.face_mesh # 导入 MediaPipe 的面部网格模块,用于检测和处理面部特征点
faceMesh = mpFaceMesh.FaceMesh(max_num_faces=2) # 初始化面部网格模型,设置最多检测两张人脸
drawSpec = mpDraw.DrawingSpec(thickness=1, circle_radius=2) # 创建一个绘图规格对象,用于定义标志点和连接线的绘制样式
# thickness 指定线的厚度,circle_radius 指定标志点的半径

while True:
    print("Reading video frame...")
    success, img = cap.read()
    print("Read success:", success)
    if not success:
        print("Finished processing video or error occurred.")
        break

    # 将图像转换为 RGB
    imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    # 处理图像以检测面部网格
    results = faceMesh.process(imgRGB)

    if results.multi_face_landmarks:
        for faceLms in results.multi_face_landmarks:
            # 绘制面部网格
            mpDraw.draw_landmarks(img, faceLms, mpFaceMesh.FACEMESH_TESSELATION, drawSpec, drawSpec)
            # mpDraw.draw_landmarks 调用 MediaPipe 的绘图函数,用于在图像上绘制标志点和连接
            # img: 要在其上绘制标志点的图像
            # faceLms: 检测到的人脸标志点集合
            # mpFaceMesh.FACEMESH_TESSELATION: 指定要绘制的连接类型,这里是面部网格的细分连接
            # drawSpec: 定义标志点和连接线的绘制样式(如厚度和圆圈半径)
            # 后面两个drawSpec,第一个用于定义标志点(关键点)的绘制样式,比如圆圈的半径和颜色,第二个用于定义连接线的绘制样式,比如线的厚度和颜色
            # 可以选择分别定义:
            # drawSpecPoints = mpDraw.DrawingSpec(color=(0, 255, 0), thickness=1, circle_radius=2) # 绿色
            # drawSpecLines = mpDraw.DrawingSpec(color=(255, 0, 0), thickness=1) # 蓝色
            # 其中对于drawSpecLines 中定义 circle_radius=2 是没有效果的,circle_radius 只影响标志点(关键点)的绘制,而不会影响连接线的绘制,因此,在 drawSpecLines 中设置 circle_radius 没有意义

            for id, lm in enumerate(faceLms.landmark):
                # 获取图像的尺寸
                ih, iw, ic = img.shape
                x, y = int(lm.x * iw), int(lm.y * ih)
                # 打印每个标志点的 ID 和坐标
                print(id, x, y)

    # 计算并显示帧率
    cTime = time.time()
    fps = 1 / (cTime - pTime)
    pTime = cTime
    cv2.putText(
        img, f"FPS: {int(fps)}", (20, 70), cv2.FONT_HERSHEY_PLAIN, 5, (255, 0, 0), 5
    )

    cv2.namedWindow("Image", cv2.WINDOW_NORMAL)  # 创建可调整大小的窗口

    # 显示图像
    cv2.imshow("Image", img)
    cv2.waitKey(1)

cap.release()
cv2.destroyAllWindows()

FaceMeshModule.py

import cv2
import mediapipe as mp
import time


class FaceMeshDetector:
    def __init__(
        self, staticMode=False, maxFaces=2, minDetectionCon=0.5, minTrackCon=0.5
    ):
        # 初始化参数
        self.staticMode = staticMode  # 是否使用静态模式
        self.maxFaces = maxFaces  # 最大检测人脸数量
        self.minDetectionCon = minDetectionCon  # 最小检测置信度
        self.minTrackCon = minTrackCon  # 最小跟踪置信度

        # 初始化 MediaPipe 的绘图工具和面部网格模型
        self.mpDraw = mp.solutions.drawing_utils  # 绘图工具
        self.mpFaceMesh = mp.solutions.face_mesh  # 面部网格模块
        # self.faceMesh = self.mpFaceMesh.FaceMesh(
        #     self.staticMode, self.maxFaces, self.minDetectionCon, self.minTrackCon
        # )
        self.faceMesh = self.mpFaceMesh.FaceMesh(
            static_image_mode=self.staticMode,
            max_num_faces=self.maxFaces,
            min_detection_confidence=self.minDetectionCon,
            min_tracking_confidence=self.minTrackCon,
        )

        self.drawSpec = self.mpDraw.DrawingSpec(
            thickness=1, circle_radius=2
        )  # 绘图规格

    def findFaceMesh(self, img, draw=True):
        # 将图像转换为 RGB
        self.imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        # 处理图像以检测面部网格
        self.results = self.faceMesh.process(self.imgRGB)
        faces = []  # 存储检测到的面部特征点
        if self.results.multi_face_landmarks:
            for faceLms in self.results.multi_face_landmarks:
                if draw:
                    # 绘制面部网格
                    self.mpDraw.draw_landmarks(
                        img,
                        faceLms,
                        self.mpFaceMesh.FACEMESH_TESSELATION,
                        self.drawSpec,
                        self.drawSpec,
                    )
                face = []  # 存储单个人脸的特征点
                for id, lm in enumerate(faceLms.landmark):
                    ih, iw, ic = img.shape  # 获取图像的高、宽、通道数
                    x, y = int(lm.x * iw), int(lm.y * ih)  # 将归一化坐标转换为像素坐标
                    face.append([x, y])  # 添加特征点坐标
                faces.append(face)  # 添加到面部列表
        return img, faces  # 返回图像和面部特征点


def main():
    # 打开视频文件
    cap = cv2.VideoCapture(
        "E:\\Advance Computer Vision with Python\\main\\Chapter 3 Face Detection\\Videos\\4.mp4"
    )
    pTime = 0  # 上一帧的时间
    detector = FaceMeshDetector(maxFaces=2)  # 初始化面部网格检测器
    while True:
        success, img = cap.read()
        if not success:
            break
        img, faces = detector.findFaceMesh(img)  # 检测面部网格
        if len(faces) != 0:
            print(faces[0])  # 打印第一个面部的特征点
        cTime = time.time()  # 当前时间
        fps = 1 / (cTime - pTime)  # 计算帧率
        pTime = cTime  # 更新上一帧的时间
        cv2.putText(
            img, f"FPS: {int(fps)}", (20, 70), cv2.FONT_HERSHEY_PLAIN, 3, (0, 255, 0), 3
        )  # 在图像上显示帧率
        cv2.namedWindow("Image", cv2.WINDOW_NORMAL)  # 创建可调整大小的窗口
        cv2.imshow("Image", img)  # 显示图像
        cv2.waitKey(1)  # 等待键盘输入


if __name__ == "__main__":
    main()

mp.solutions.face_mesh

mpFaceMesh = mp.solutions.face_mesh 导入 MediaPipe 的面部网格模块,用于检测和处理面部特征点

faceMesh = mpFaceMesh.FaceMesh(max_num_faces=2) 初始化面部网格模型,设置最多检测两张人脸

results = faceMesh.process(imgRGB) 处理图像以检测面部网格

mpFaceMesh.FaceMesh() 类的参数有:self.staticMode, self.maxFaces, self.minDetectionCon, self.minTrackCon

  • staticMode:是否将每帧图像作为静态图像处理。如果为 True,每帧都会进行人脸检测;如果为 False,在检测到人脸后进行跟踪,速度更快
  • maxFaces:要检测的最大人脸数量
  • minDetectionCon:检测的最小置信度阈值。低于此值的人脸将被忽略
  • minTrackCon:跟踪的最小置信度阈值。低于此值的跟踪将被忽略

mp.solutions.drawing_utils

mpDraw = mp.solutions.drawing_utils 导入 MediaPipe 的绘图工具模块

drawSpec = mpDraw.DrawingSpec(thickness=1, circle_radius=2) 创建一个绘图规格对象,用于定义标志点和连接线的绘制样式,thickness 指定线的厚度,circle_radius 指定标志点的半径

mpDraw.draw_landmarks(img, faceLms, mpFaceMesh.FACEMESH_TESSELATION, drawSpec, drawSpec) mpDraw.draw_landmarks 调用 MediaPipe 的绘图函数,用于在图像上绘制标志点和连接

  • img: 要在其上绘制标志点的图像
  • faceLms: 检测到的人脸标志点集合
  • mpFaceMesh.FACEMESH_TESSELATION: 指定要绘制的连接类型,这里是面部网格的细分连接
  • drawSpec: 定义标志点和连接线的绘制样式(如厚度和圆圈半径),后面两个drawSpec,第一个用于定义标志点(关键点)的绘制样式,比如圆圈的半径和颜色,第二个用于定义连接线的绘制样式,比如线的厚度和颜色

源代码的小问题

这些bug直接运行是不会报错的,只有调试的时候才会报错

1、有个参数在新版本换名字了

原来:

原来

现在:

现在

2、有个位置传参需要修改成关键字传参

关键字传参

  • 21
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值