游乐游手机版
首页/AI热点日报/热点详情

从零开始教程如何使用Python OpenCV进行面部标志检测

类型:热点整理2026-07-07
面部标志检测:用OpenCV和树莓派实战68个关键点 面部标志检测,简单来说就是识别出脸上眉毛、眼睛、鼻子、嘴巴、下巴这些关键部位的位置。这项技术在很多场景中都有用武之地,比如人脸识别、表情分析、甚至美颜滤镜。今天咱们就用OpenCV和树莓派来实战一下,用dlib预训练的68个点面部标志检测器,配合

面部标志检测:用OpenCV和树莓派实战68个关键点

面部标志检测,简单来说就是识别出脸上眉毛、眼睛、鼻子、嘴巴、下巴这些关键部位的位置。这项技术在很多场景中都有用武之地,比如人脸识别、表情分析、甚至美颜滤镜。今天咱们就用OpenCV和树莓派来实战一下,用dlib预训练的68个点面部标志检测器,配合Python OpenCV把检测结果可视化出来。

所需组件

先看看需要哪些家伙:

硬件:树莓派3和Pi摄像头模块。

软件:OpenCV、dlib、imutils、numpy,还有Python3。OpenCV负责图像处理,数字图像处理最常见的应用包括物体检测、人脸识别和人数统计;dlib则提供预训练的机器学习算法;imutils让OpenCV的一些操作更简便。

Pi摄像头与树莓派的接线细节,可以参考之前的教程(这里不再赘述)。

在树莓派中安装OpenCV

安装之前先更新系统:

sudo apt-get update

接着安装OpenCV所需的依赖:

sudo apt-get install libhdf5-dev -y
sudo apt-get install libhdf5-serial-dev -y
sudo apt-get install libatlas-base-dev -y
sudo apt-get install libjasper-dev -y
sudo apt-get install libqtgui4 -y
sudo apt-get install libqt4-test -y

然后安装OpenCV:

pip3 install opencv-contrib-python==4.1.0.25

安装imutils(用于平移、旋转、调整大小、骨架化等图像处理):

pip3 install imutils

安装dlib(机器学习工具包,包含预训练面部标志检测器):

pip3 install dlib

安装NumPy(科学计算核心库):

pip3 install numpy

如何使用dlib检测面部部位

dlib的预训练面部标志检测器可以输出映射到面部结构的68个(x, y)坐标。该预测器在iBUG 300-W数据集上训练,结果可靠。下面这张图标注了每个坐标对应的面部区域:

对Raspberry Pi进行面部地标检测编程

完整代码在文章末尾给出,这里先拆解关键部分。

首先,导入所需库:

from imutils import face_utils
import numpy as np
import argparse
import imutils
import dlib
import cv2
from picamera.array import PiRGBArray
from picamera import PiCamera

初始化摄像头对象,设置分辨率为640×480,帧率30fps:

camera = PiCamera()
camera.resolution = (640, 480)
camera.framerate = 30
rawCapture = PiRGBArray(camera, size=(640, 480))

使用参数解析器指定面部标志预测器的路径:

ap = argparse.ArgumentParser()
ap.add_argument("-p", "--shape-predictor", required=True,
                help="面部地标预测路径")
args = vars(ap.parse_args())

初始化基于HOG的dlib面部检测器,并加载预训练的面部特征预测器:

detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(args["shape_predictor"])

使用capture_continuous从摄像头持续捕获帧:

for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
    image = frame.array
    cv2.imshow("Frame", image)
    key = cv2.waitKey(1) & 0xFF
    rawCapture.truncate(0)

按下键盘“S”键捕获当前帧。然后调整图像尺寸并转为灰度:

if key == ord("s"):
    image = imutils.resize(image, width=300)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

用dlib的检测器发现人脸:

rects = detector(gray, 1)

对每张检测到的人脸,用预测器计算68个面部标志,转换为NumPy数组:

for (i, rect) in enumerate(rects):
    shape = predictor(gray, rect)
    shape = face_utils.shape_to_np(shape)

遍历每个面部区域(如眉毛、眼睛、嘴巴等),在图像上标注名称,并在对应坐标画红点:

for (name, (i, j)) in face_utils.FACIAL_LANDMARKS_IDXS.items():
    clone = image.copy()
    cv2.putText(clone, name, (10, 30), cv2.FONT_HERSHEY_SIMPLEX,
                0.7, (0, 0, 255), 2)
    for (x, y) in shape[i:j]:
        cv2.circle(clone, (x, y), 1, (0, 0, 255), -1)

还可以将每个面部部分提取为单独的图像,通过计算边界框并resize到250像素:

(x, y, w, h) = cv2.boundingRect(np.array([shape[i:j]]))
roi = image[y:y + h, x:x + w]
roi = imutils.resize(roi, width=250, inter=cv2.INTER_CUBIC)

最后,显示该部分的单独图像和带标注的全图,按ESC键切换面部区域:

cv2.imshow("ROI", roi)
cv2.imshow("Image", clone)
cv2.waitKey(0)

测试面部识别器

创建一个文件夹,进入目录:

mkdir face-part-detector
cd face-part-detector

从官方链接下载shape_predictor_68_face_landmarks.dat文件,放入该目录。新建detect.py,粘贴下面的完整代码。

运行命令:

python3 detect.py --shape-predictor shape_predictor_68_face_landmarks.dat

你会看到一个实时摄像窗口。按下“S”键捕获一帧,红点会标注在面部区域(默认先显示嘴巴)。用ESC键切换到其他部位,比如眉毛、眼睛、鼻子等。


完整代码

from imutils import face_utils
import numpy as np
import argparse
import imutils
import dlib
import cv2
from picamera.array import PiRGBArray
from picamera import PiCamera
from PIL import Image

camera = PiCamera()
camera.resolution = (640, 480)
camera.framerate = 30
rawCapture = PiRGBArray(camera, size=(640, 480))

# 构造参数解析器并解析参数
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--shape-predictor", required=True,
                help="面部地标预测路径")
args = vars(ap.parse_args())

detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(args["shape_predictor"])

for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
    image = frame.array
    cv2.imshow("Frame", image)
    key = cv2.waitKey(1) & 0xFF
    rawCapture.truncate(0)

    if key == ord("s"):
        image = imutils.resize(image, width=300)
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        rects = detector(gray, 1)

        # 循环人脸检测
        for (i, rect) in enumerate(rects):
            # 确定面部区域的面部标志
            shape = predictor(gray, rect)
            shape = face_utils.shape_to_np(shape)

            # 分别循环面部部分
            for (name, (i, j)) in face_utils.FACIAL_LANDMARKS_IDXS.items():
                # 在图像上显示人脸部分的名称
                clone = image.copy()
                cv2.putText(clone, name, (10, 30), cv2.FONT_HERSHEY_SIMPLEX,
                            0.7, (0, 0, 255), 2)

                # 在特定的面部部分绘制圆圈
                for (x, y) in shape[i:j]:
                    cv2.circle(clone, (x, y), 1, (0, 0, 255), -1)

                # 提取人脸区域的ROI作为单独的图像
                (x, y, w, h) = cv2.boundingRect(np.array([shape[i:j]]))
                roi = image[y:y + h, x:x + w]
                roi = imutils.resize(roi, width=250, inter=cv2.INTER_CUBIC)

                # 显示特定的面部部分
                cv2.imshow("ROI", roi)
                cv2.imshow("Image", clone)
                cv2.waitKey(0)

        # 可视化所有面部地标
        for (x, y) in shape:
            cv2.circle(image, (x, y), 1, (0, 0, 255), -1)
        cv2.imshow("Image", image)
        cv2.waitKey(0)
来源:https://m.elecfans.com/article/1877051.html

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。