实操教程|使用 Opencv 简化面部地标检测

极市平台

共 9811字,需浏览 20分钟

 · 2021-08-01

↑ 点击蓝字 关注极市平台

者丨磐怼怼
来源丨深度学习与计算机视觉
编辑丨极市平台

极市导读

 

今天我们将使用 OpenCV 和 MediaPipe 来检测图像中的468个面部地标。>>加入极市CV技术交流群,走在计算机视觉的最前沿

OpenCV 是用于计算机视觉、机器学习和图像处理的跨平台开源库,我们可以使用它来开发实时计算机视觉应用程序。它主要用于图像或视频处理以及分析,包括对象检测、面部检测等。

面部地标用于定位和表示面部的重要区域,例如:

  • 嘴巴
  • 眼睛
  • 眉毛
  • 鼻子
  • 下颌线等

应用

面部地标有许多应用,例如为人熟知的换脸、面部变形、头部姿势估计等。

换脸

如果我们在两张不同的脸上估计了面部地标特征点,我们可以将一张脸与另一张脸对齐,然后我们可以将一张脸克隆到另一张脸上。

面部变形

面部地标可用于通过对齐可变形的面部来生成中间图像。

头部姿势估计

一旦我们知道了一些面部地标点,那么我们也可以估计头部的姿势。

MediaPipe Face Mesh

即使在移动设备上,MediaPipe Face Mesh 也可以实时估计 468 个 3D 面部地标。通过应用机器学习 (ML) 来推断 3D 表面几何形状,它只需要单个相机输入,而无需专用的深度传感器。它提供了更好的实时性能。

面部地标模型

3D 面部地标模型使用迁移学习,并在具有不同目标的网络上进行训练:该网络预测合成渲染数据上的 3D 地标坐标。由此产生的网络在现实世界的数据上表现得相当好。

3D 地标网络将输入作为裁剪的视频帧,而无需额外的深度输入。该模型输出 3D 点的位置,在输入中合理对齐。

几何管线

几何管线是一个关键组件,它估计 3D Metric 空间内的几何对象。在每一帧上,分别执行以下步骤:

  • 得到Metric 3D空间坐标,即将面部地标屏幕坐标转换为Metric 3D空间坐标。
  • 面部姿态变换矩阵被估计为来自标准面部度量界标的刚性线性映射,然后将其发送到运行时面部度量界标中,以最小化两者之间的差异。
  • 运行时面部度量地标创建一个面部网格。

让我们来实现它

首先,让我们检查我们的网络摄像头 ID 是否工作正常,并在输出屏幕上打印每秒帧数 (fps)。

import cv2  
import time
cap = cv2.VideoCapture\(0\)
pTime = 0
while True:
success, img = cap.read\(\)
imgRGB = cv2.cvtColor\(img, cv2.COLOR\_BGR2RGB\)
cTime = time.time\(\)
fps = 1/\(cTime-pTime\)
pTime = cTime
cv2.putText\(img, f'FPS:\{int\(fps\)\}', \(2070\), cv2.FONT\_HERSHEY\_SIMPLEX, 1, \(02550\), 2\)
cv2.imshow\("Test", img\)
cv2.waitKey\(1\)

如果你有网络摄像头,它应该会打开一个窗口,否则你可以在VideoCapture功能中指定视频路径而不是零。

在左上角,你可以看到 FPS(变化),如下所示。

现在让我们创建一个新的 python 文件并开始创建我们的面部地标检测模块。

安装所需的模块。

pip install opencv-python  
pip install mediapipe
import cv2  
import mediapipe as mp
import time
cap = cv2.VideoCapture\(0\)
pTime = 0
NUM\_FACE = 2

mpDraw = mp.solutions.drawing\_utils
mpFaceMesh = mp.solutions.face\_mesh
faceMesh = mpFaceMesh.FaceMesh\(max\_num\_faces=NUM\_FACE\)
drawSpec = mpDraw.DrawingSpec\(thickness=1, circle\_radius=1\)

在上面的代码中,我们从网络摄像头获取输入,变量NUM\_FACE表示有多少面部要从帧中检测和定位面部地标。

要绘制面部点,我们使用mpDraw变量。我们将使用mp.solutions.face\_mesh来创建面部网格。

为了控制连接线和点的粗细,我们将使用drawSpec

while True:  
    success, img = cap.read\(\)
    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.FACE\_CONNECTIONS, drawSpec, drawSpec\)
for id,lm in enumerate\(faceLms.landmark\):  
print\(lm\)
ih, iw, ic = img.shape
x,y = int\(lm.x\*iw\), int\(lm.y\*ih\)
# uncomment the below line to see the 468 facial landmark
# cv2.putText\(img, str\(id\), \(x, y\), cv2.FONT\_HERSHEY\_SIMPLEX, 0.3, \(0, 255, 0\), 1\)
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\_SIMPLEX, 1, \(0,255,0\), 2\)
cv2.imshow\("Test", img\)
cv2.waitKey\(1\)

然后在 while 循环中读取帧并将帧转换为 RGB,将该图像传递给*faceMesh.process(),* 然后在面部绘制检测到的地标。

为了看到468 个面部地标,取消对for loop 中的cv2.putText\(\)函数的注释。语句 print \(id, x, y\)将打印出 id 和坐标。然后输出如下。

图片

现在为了创建一个模块,以便我们可以在不同的项目中使用它,首先我们需要创建一个包含函数的类。

import cv2  
import mediapipe as mp
import time
NUM\_FACE = 2  


class FaceLandMarks\(\):
    def \_\_init\_\_\(self, staticMode=False,maxFace=NUM\_FACE, minDetectionCon=0.5, minTrackCon=0.5\):
        self.staticMode = staticMode
        self.maxFace =  maxFace
        self.minDetectionCon = minDetectionCon
        self.minTrackCon = minTrackCon

        self.mpDraw = mp.solutions.drawing\_utils
        self.mpFaceMesh = mp.solutions.face\_mesh
        self.faceMesh = self.mpFaceMesh.FaceMesh\(self.staticMode, self.maxFace, self.minDetectionCon, self.minTrackCon\)
        self.drawSpec = self.mpDraw.DrawingSpec\(thickness=1, circle\_radius=1\)

    def findFaceLandmark\(self, img, draw=True\):
        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.FACE\_CONNECTIONS, self.drawSpec, self.drawSpec\)

                face = \[\]
                for id, lm in enumerate\(faceLms.landmark\):
                    # print\(lm\)
                    ih, iw, ic = img.shape
                    x, y = int\(lm.x \* iw\), int\(lm.y \* ih\)
                    #cv2.putText\(img, str\(id\), \(x,y\), cv2.FONT\_HERSHEY\_SIMPLEX, 0.3, \(0,255,0\), 1\)
                    #print\(id, x, y\)
                    face.append\(\[x,y\]\)
                faces.append\(face\)
        return img, faces


def main\(\):
    cap = cv2.VideoCapture\(0\)
    pTime = 0
    detector = FaceLandMarks\(\)
    while True:
        success, img = cap.read\(\)
        img, faces = detector.findFaceLandmark\(img\)
        if len\(faces\)\!=0:
            print\(len\(faces\)\)
        cTime = time.time\(\)
        fps = 1 / \(cTime - pTime\)
        pTime = cTime
        cv2.putText\(img, f'FPS:\{int\(fps\)\}', \(2070\), cv2.FONT\_HERSHEY\_SIMPLEX, 1, \(02550\), 2\)
        cv2.imshow\("Test", img\)
        cv2.waitKey\(1\)


if \_\_name\_\_ == "\_\_main\_\_":
    main\(\)

结论

在上面的代码中,函数名称是*“findFaceLandmarks”,它检测面部地标并执行与上述相同的功能。类“FaceLandMarks()”* 取静态模式中,面部的最大数量和最小检测置信度和最小的跟踪置信度。然后创建 函数来运行代码。

完整代码:https://github.com/BakingBrains/Face_LandMark_Detection

参考

https://www.youtube.com/watch?v=V9bzew8A1tc&t=2125s
https://learnopencv.com/facial-landmark-detection/
https://google.github.io/mediapipe/solutions/face_mesh.html

如果觉得有用,就请分享到朋友圈吧!

△点击卡片关注极市平台,获取最新CV干货

公众号后台回复“ICCV2021”获取最新论文合集


极市干货
YOLO教程:一文读懂YOLO V5 与 YOLO V4大盘点|YOLO 系目标检测算法总览全面解析YOLO V4网络结构
实操教程:PyTorch vs LibTorch:网络推理速度谁更快?只用两行代码,我让Transformer推理加速了50倍PyTorch AutoGrad C++层实现
算法技巧(trick):深度学习训练tricks总结(有实验支撑)深度强化学习调参Tricks合集长尾识别中的Tricks汇总(AAAI2021
最新CV竞赛:2021 高通人工智能应用创新大赛CVPR 2021 | Short-video Face Parsing Challenge3D人体目标检测与行为分析竞赛开赛,奖池7万+,数据集达16671张!


CV技术社群邀请函 #

△长按添加极市小助手
添加极市小助手微信(ID : cvmart4)

备注:姓名-学校/公司-研究方向-城市(如:小极-北大-目标检测-深圳)


即可申请加入极市目标检测/图像分割/工业检测/人脸/医学影像/3D/SLAM/自动驾驶/超分辨率/姿态估计/ReID/GAN/图像增强/OCR/视频理解等技术交流群


每月大咖直播分享、真实项目需求对接、求职内推、算法竞赛、干货资讯汇总、与 10000+来自港科大、北大、清华、中科院、CMU、腾讯、百度等名校名企视觉开发者互动交流~



觉得有用麻烦给个在看啦~  


浏览 10
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报