Python人脸识别实战——基于Dlib和OpenCV的人脸识别与关键点检测(附完整代码和结果图)

news2024/10/12 11:14:30

Python人脸识别实战——基于Dlib和OpenCV的人脸识别与关键点检测(附完整代码和结果图)


关于作者


作者:小白熊

作者简介:精通python、matlab、c#语言,擅长机器学习,深度学习,机器视觉,目标检测,图像分类,姿态识别,语义分割,路径规划,智能优化算法,数据分析,各类创新融合等等。

联系邮箱:xbx3144@163.com

科研辅导、知识付费答疑、个性化定制以及其他合作需求请联系作者~



1 引言


  在这篇博文中,博主将展示如何使用Python中的Dlib库对人脸进行关键点检测,并利用OpenCV绘制关键点。人脸关键点检测是计算机视觉领域的一项重要任务。我们可以通过检测人脸上的特定位置(如眼睛、鼻子、嘴唇等)来分析面部特征。在这篇文章中,我们将基于Dlib库的预训练模型shape_predictor_68_face_landmarks.dat,结合OpenCV进行人脸关键点的绘制。



2 模型理论

2.1 人脸识别

  人脸识别是定位图像或视频中的人脸的过程。经典的HOG(Histogram of Oriented Gradients,方向梯度直方图)特征提取方法是Dlib中的核心方法之一。

  • HOG特征:HOG是一种用于对象检测的图像描述方法,它通过统计图像中局部区域的梯度方向来提取物体的形状特征。
  • SVM分类器:Dlib使用支持向量机(SVM)分类器来检测面部,HOG特征被送入SVM分类器进行人脸与非人脸的分类。

  Dlib的get_frontal_face_detector()方法基于HOG特征和SVM分类器,能够快速准确地检测出人脸的边界框。


2.2 关键点检测

  关键点检测属于回归任务,它根据输入的图像预测人脸上各个特定部位的坐标。Dlib使用的是经典的**回归树(Regression Tree)*算法,具体为*基于局部二值模式(Local Binary Features)特征的回归树模型

  • 回归树模型:这种模型在初始人脸检测的基础上,通过多次迭代逐步逼近真实的关键点位置。
  • 68关键点模型:Dlib提供了一个68个点的模型(shape_predictor_68_face_landmarks.dat),它能够精确定位包括脸部轮廓、眉毛、眼睛、鼻子、嘴唇等部位的68个点。

2.3 工作流程

  1. 输入图像:提供一张待检测的图像。
  2. 人脸检测:使用HOG特征提取与SVM分类器检测人脸的边界框。
  3. 关键点预测:基于回归树模型,对人脸区域内的68个关键点进行预测。
  4. 关键点绘制:使用OpenCV对检测到的关键点进行绘制。



3 依赖库

我们需要以下库来实现这一功能:

  • dlib:用于人脸检测和关键点识别
  • opencv-python:用于加载图像并绘制关键点
  • numpy:用于处理数组和矩阵
  • warnings:用于忽略不必要的警告

可以通过以下命令安装这些库:

pip install opencv-python dlib numpy



4 代码讲解

4.1 导入所需模块

pythonCopy codeimport os
import cv2
import dlib
import numpy as np
import warnings

warnings.filterwarnings("ignore")  # 忽略警告

首先需要导入上述模块,并且为了保持输出的清晰性,我们使用warnings.filterwarnings("ignore")来忽略警告信息。


4.2 定义关键点类型及其颜色

pred_types = {
    'face': ((0, 17), (0.682, 0.780, 0.909, 0.5)),
    'eyebrow1': ((17, 22), (1.0, 0.498, 0.055, 0.4)),
    'eyebrow2': ((22, 27), (1.0, 0.498, 0.055, 0.4)),
    'nose': ((27, 31), (0.345, 0.239, 0.443, 0.4)),
    'nostril': ((31, 36), (0.345, 0.239, 0.443, 0.4)),
    'eye1': ((36, 42), (0.596, 0.875, 0.541, 0.3)),
    'eye2': ((42, 48), (0.596, 0.875, 0.541, 0.3)),
    'lips': ((48, 60), (0.596, 0.875, 0.541, 0.3)),
    'teeth': ((60, 68), (0.596, 0.875, 0.541, 0.4))
}

这个字典定义了各部分关键点的范围以及对应的颜色,用于后续绘制。


4.3 绘制关键点和连线的函数

我们定义了两个函数来实现关键点的绘制:

  • draw_line():用于绘制两个连续关键点之间的直线。
  • draw_line_circle():用于绘制一圈关键点的连线,适用于嘴唇、眼睛等区域。
def draw_line(img, shape, i):
    cv2.line(img, (shape.part(i).x, shape.part(i).y), 
             (shape.part(i + 1).x, shape.part(i + 1).y),
             color=(0, 255, 0), thickness=1, lineType=cv2.LINE_AA)

def draw_line_circle(img, shape, i, start, end):
    cv2.line(img, (shape.part(i).x, shape.part(i).y), 
             (shape.part(i + 1).x, shape.part(i + 1).y),
             color=(0, 255, 0), thickness=1, lineType=cv2.LINE_AA)
    cv2.line(img, (shape.part(start).x, shape.part(start).y), 
             (shape.part(end).x, shape.part(end).y),
             color=(0, 255, 0), thickness=1, lineType=cv2.LINE_AA)

4.4 人脸识别和关键点检测

  在dlib_face_keypoint_detector()函数中,我们使用Dlib预训练模型shape_predictor_68_face_landmarks.dat来加载人脸关键点检测模型。然后,我们使用detector来检测图像中的人脸,接着使用predictor来识别人脸的68个关键点。

下载人脸关键点检测模型: http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2

def dlib_face_keypoint_detector(img_path, save_result=True):
    detector = dlib.get_frontal_face_detector()
    predictor_path = './model/shape_predictor_68_face_landmarks.dat'
    predictor = dlib.shape_predictor(predictor_path)

    img = cv2.imread(img_path)
    dets = detector(img, 1)
    
    for k, d in enumerate(dets):
        shape = predictor(img, d)
        for i, point in enumerate(shape.parts()):
            x, y = point.x, point.y
            cv2.circle(img, (x, y), 1, color=(255, 0, 255), thickness=1)
            cv2.putText(img, str(i + 1), (x, y), fontFace=cv2.FONT_HERSHEY_SCRIPT_SIMPLEX,
                        fontScale=0.3, color=(255, 255, 0))
            
            # 连接关键点
            if i + 1 < 17:  # face
                draw_line(img, shape, i)
            elif 17 < i + 1 < 22:  # eyebrow1
                draw_line(img, shape, i)
            elif 22 < i + 1 < 27:  # eyebrow2
                draw_line(img, shape, i)
            elif 27 < i + 1 < 31:  # nose
                draw_line(img, shape, i)
            elif 31 < i + 1 < 36:  # nostril
                draw_line(img, shape, i)
            elif 36 < i + 1 < 42:  # eye1
                draw_line_circle(img, shape, i, 36, 42 - 1)
            elif 42 < i + 1 < 48:  # eye2
                draw_line_circle(img, shape, i, 42, 48 - 1)
            elif 48 < i + 1 < 60:  # lips
                draw_line_circle(img, shape, i, 48, 60 - 1)
            elif 60 < i + 1 < 68:  # teeth
                draw_line_circle(img, shape, i, 60, 68 - 1)

    cv2.imshow('detect keypoints', img)
    if save_result:
        save_filename = img_path.split('.')[0] + '_keypoint.' + img_path.split('.')[1]
        cv2.imwrite(save_filename, img)
    cv2.waitKey(0)

4.5 运行程序

运行主函数,img_path是待识别图片的路径。

if __name__ == '__main__':
    dlib_face_keypoint_detector('./images/test.jpg')



5 结果展示


原图:

原图



运行代码后,程序会在图像上绘制人脸的矩形框和68个关键点。每个关键点将被标注序号,并且相关部分(如眼睛、嘴巴)会被连成线:

人脸识别



6 完整代码

import os
import cv2
import dlib
import numpy as np
import warnings

warnings.filterwarnings("ignore")


pred_types = {'face': ((0, 17), (0.682, 0.780, 0.909, 0.5)),
              'eyebrow1': ((17, 22), (1.0, 0.498, 0.055, 0.4)),
              'eyebrow2': ((22, 27), (1.0, 0.498, 0.055, 0.4)),
              'nose': ((27, 31), (0.345, 0.239, 0.443, 0.4)),
              'nostril': ((31, 36), (0.345, 0.239, 0.443, 0.4)),
              'eye1': ((36, 42), (0.596, 0.875, 0.541, 0.3)),
              'eye2': ((42, 48), (0.596, 0.875, 0.541, 0.3)),
              'lips': ((48, 60), (0.596, 0.875, 0.541, 0.3)),
              'teeth': ((60, 68), (0.596, 0.875, 0.541, 0.4))
              }

def draw_line(img, shape, i):
    cv2.line(img, pt1=(shape.part(i).x, shape.part(i).y), pt2=(shape.part(i + 1).x, shape.part(i + 1).y),
             color=(0, 255, 0), thickness=1, lineType=cv2.LINE_AA)


def draw_line_circle(img, shape, i, start, end):
    cv2.line(img, pt1=(shape.part(i).x, shape.part(i).y), pt2=(shape.part(i + 1).x, shape.part(i + 1).y),
             color=(0, 255, 0), thickness=1, lineType=cv2.LINE_AA)

    cv2.line(img, pt1=(shape.part(start).x, shape.part(start).y), pt2=(shape.part(end).x, shape.part(end).y),
             color=(0, 255, 0), thickness=1, lineType=cv2.LINE_AA)

def dlib_face_keypoint_detector(img_path, save_result=True):
    # 检测人脸框
    detector = dlib.get_frontal_face_detector()
    
    predictor_path = './model/shape_predictor_68_face_landmarks.dat'

    # 检测人脸关键点
    predictor = dlib.shape_predictor(predictor_path)

    img = cv2.imread(img_path)
    print("Processing file: {}".format(img_path))
    dets = detector(img, 1)
    print("Number of faces detected: {}".format(len(dets)))
    for k, d in enumerate(dets):
        x1 = d.left()
        y1 = d.top()
        x2 = d.right()
        y2 = d.bottom()
        print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format(k, x1, y1, x2, y2))
        cv2.rectangle(img, (x1, y1), (x2, y2), color=(0, 255, 255), thickness=1, lineType=cv2.LINE_AA)
        shape = predictor(img, d)
        print(shape.num_parts) 
        print(shape.rect)  
        print(
            shape.parts())  
        print("Part 0: {}, Part 1: {} ...".format(shape.part(0), shape.part(1)))

        landmarks = np.matrix([[p.x, p.y] for p in shape.parts()])
        # 绘制所有的关键点
        for i, point in enumerate(shape.parts()):
            x = point.x
            y = point.y
            cv2.circle(img, (x, y), 1, color=(255, 0, 255), thickness=1, lineType=cv2.LINE_AA)
            cv2.putText(img, str(i + 1), (x, y), fontFace=cv2.FONT_HERSHEY_SCRIPT_SIMPLEX,
                        fontScale=0.3, color=(255, 255, 0))

            # 连接关键点
            if i + 1 < 17:  # face
                draw_line(img, shape, i)
            elif 17 < i + 1 < 22:  # eyebrow1
                draw_line(img, shape, i)
            elif 22 < i + 1 < 27:  # eyebrow2
                draw_line(img, shape, i)
            elif 27 < i + 1 < 31:  # nose
                draw_line(img, shape, i)
            elif 31 < i + 1 < 36:  # nostril
                draw_line(img, shape, i)
            elif 36 < i + 1 < 42:  # eye1
                draw_line_circle(img, shape, i, 36, 42 - 1)
            elif 42 < i + 1 < 48:  # eye2
                draw_line_circle(img, shape, i, 42, 48 - 1)
            elif 48 < i + 1 < 60:  # lips
                draw_line_circle(img, shape, i, 48, 60 - 1)
            elif 60 < i + 1 < 68:  # teeth
                draw_line_circle(img, shape, i, 60, 68 - 1)

    cv2.imshow('detect keypoints', img)
    if save_result:
        dir, filename = os.path.split(img_path)
        save_filename = os.path.join(dir, filename.split('.')[0] + '_keypoint' + '.' + filename.split('.')[1])
        cv2.imwrite(save_filename, img)
    cv2.waitKey(0)


if __name__ == '__main__':
    dlib_face_keypoint_detector('./images/test.jpg')



7 总结

  通过这篇文章,我们展示了如何利用Dlib和OpenCV来检测和绘制人脸关键点。这项技术可以广泛应用于人脸识别、表情分析和美颜效果等领域。你可以根据自己的需求进行调整或扩展。如果你有任何问题或建议,欢迎留言讨论!


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2207806.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于FPGA的以太网设计(一)

以太网简介 以太网&#xff08;Ethernet&#xff09;是一种计算机局域网技术。IEEE组织的IEEE 802.3标准制定了以太网的技术标准&#xff0c;它规定了包括物理层的连线、电子信号和介质访问控制的内容。以太网是目前应用最普遍的局域网技术&#xff0c;取代了其他局域网标准如…

在线深度学习:爱奇艺效果广告分钟级模型优化

01# 背景 在效果广告投放场景中&#xff0c;媒体侧需要准确衡量每次请求的价值&#xff0c;模型预估值在广告竞价中扮演着核心角色。模型预估精度的提升&#xff0c;是改善媒体侧变现效率、提升广告收益的核心技术驱动力。 此前&#xff0c;爱奇艺效果广告预估模型为小时级模型…

爬虫设计思考之二

“所谓爬虫,其本质是一种计算机程序,它的行为看起来就像是蜘蛛在网上面爬行一样,顺着互联网这个“网”,一条线一条线地“爬行”。 一、认识爬虫 爬虫这个词对于非专业人士比较的陌生&#xff0c;但是实际却和我们的生活息息相关。例如我们国内经常使用的百度浏览器搜索&#x…

Qt-系统处理鼠标相关事件(57)

目录 使用 按下事件 释放事件 双击事件 移动事件 滚轮事件 使用 按下事件 实现下面的功能 鼠标在此处点击&#xff0c;就可以获取鼠标位置 添加函数 提升函数 手册中找到这个函数的原型 重写该函数 定义 重写 这里有一个细节需要注意&#xff0c;因为这里的标准点击…

单服务器基于 Nginx 负载均衡 + Docker Compose 提高并发量

背景信息 开发需求 单服务器的多服务管理 多服务器的集群管理可参考博主 docker swarm 的技术分享《基于 docker swarm 和 NVIDIA MIG 部署并行 AI 推理服务》 根据服务请求量和服务器规模的匹配程度&#xff0c;多服务器集群的性能对于目前来说过剩&#xff0c;故有了本研究的…

c#-出现类型初始值设定项引发异常的解决方案

当出现该问题时&#xff0c;通常摸不着头脑&#xff0c;无法定位到该问题所在行。 我们可以找到应发异常的类&#xff0c;例如我上面类为YY_Model.DefaultConfig。 打开这个类文件&#xff0c;加一个断点&#xff0c;一行行运行&#xff0c;到哪里突然跳出该文件&#xff0c;则…

Python脚本实现发送QQ邮件

需要发件人邮箱地址、授权码和收件人邮箱地址 1、登录QQ邮箱后台&#xff0c;点击右上角设置&#xff0c;下拉找到第三方服务&#xff0c;开启SMTP服务&#xff0c;复制生成的授权码 2、新建一个python文件&#xff0c;输入以下源码&#xff0c;更替参数后运行即可 import smt…

【计算机网络 - 基础问题】每日 3 题(三十六)

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞…

无缝数据流动:跨域数据交换的高效策略

大型企业为了业务拓展需要&#xff0c;会在全国乃至全球各地设立分公司和办事机构&#xff0c;以便更好地处理当地事务&#xff0c;并进行市场的开拓和客户维护&#xff0c;因此大型企业都会面临跨域数据交换的场景。 跨域数据交换时&#xff0c;需要考虑多方面的问题&#xff…

使用机器学习边缘设备的快速目标检测

论文标题&#xff1a;Fast Object Detection with a Machine Learning Edge Device 中文标题&#xff1a;使用机器学习边缘设备的快速目标检测 作者信息&#xff1a; Richard C. Rodriguez, MSDA Information Systems and Cyber Security Department, The University of Tex…

IEEE新晋“水刊”,非OA,2个月可录,毕业神刊比《IEEE Access》更保险!

本期解析&#xff1a;综合类 本期解析IEEE旗下的【综合类-仪器仪表】SCI 优点&#xff1a; 审稿速度快&#xff0c;快的2-4个月录用&#xff1b; 非OA&#xff0c;国人友好&#xff0c;录用率高&#xff1b; 缺点&#xff1a; 出版周期可能较长 期刊简介 IEEE Sensors Jou…

【Java】jvisualvm工具

jdk8及以下版本自带&#xff0c;在jdk的bin目录下&#xff0c;jvisualvm.exe jdk8以上去官网下载&#xff1a;https://visualvm.github.io/index.html 本地的会自动获取&#xff0c;发布在服务器上的用远程进行连接&#xff0c;发布的程序需配置JVM参数&#xff0c;如下 -Dcom…

Linux下的文件打包、压缩和解压缩

文章目录 打包、压缩、解压缩整体介绍数据压缩gzip示例压缩单个文件压缩多个文件保留原始文件并压缩递归压缩目录解压缩文件查看gz压缩文件的内容 bzip2示例压缩单个文件压缩多个文件压缩目录下的文件解压缩文件查看bz2压缩文件的内容 命令行选项总结 zip示例压缩文件解压缩文件…

vue3学习之插槽slot

关于slot web组件内部的占位符&#xff0c;可以使用自己的标记填充这个占位符 &#xff0c;具名插槽就是在slot标签上添加name属性&#xff08;https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/slot&#xff09; vue3官方文档&#xff1a;https://cn.vuejs.org/gui…

微星主板安装系统进不去系统及bios办法

大部分原因是由于主板bios内部开启了 快速启动 选项导致的 可通过另外一个方式进入bios 1.打开控制面板--windows更新-高级启动-点立即重启 之后会进入疑难解答 ---高级----固件设置---点重启就会进入bios了 2.安装系统时注意事项&#xff1a;一般uefi启动对应的是gpt分区&…

柒拾伍- AI内容农场生产文章自动发布至公众号 (一)

一、内容农场 X AI 看过很多的新闻说 AI 产生 内容 污染网络&#xff0c;我也想试一下到底能污染成怎样。 然后为了编写爆款的内容&#xff0c;我选用这个 内容农场 的种子是来源于 微博热搜&#xff0c;让生长出来的垃圾文章更加火爆 涉及内容不能放 二、编写代码 关于代…

上半年净利下滑85%,光峰科技能否靠“上车”扭转局面?

尽管车载业务环比增了3倍&#xff0c;光峰科技今年上半年的净利润依然同比下滑了85%。 根据光峰科技发布的半年报显示&#xff0c;今年上半年&#xff0c;光峰科技营业收入为10.81亿元&#xff0c;同比微增0.76%&#xff1b;实现归属上市公司股东的净利润为1090.96万元&#x…

Java智能匹配灵活用工高效人力资源管理系统小程序源码

智能匹配灵活用工高效人力资源管理系统 &#x1f4bc;&#x1f680; &#x1f680; 开篇&#xff1a;职场新风尚&#xff0c;智能匹配引领变革 在这个瞬息万变的时代&#xff0c;职场也在经历着前所未有的变革。传统的用工模式已难以满足现代企业的需求&#xff0c;而“智能匹…

【兼容多端】UNIAPP popper气泡弹层vue3+typescript unibest

最近要实习一个泡泡弹层。看了下市场的代码&#xff0c;要么写的不怎么好&#xff0c;要么过于复杂。于是拿个轮子自己加工。200行代码撸了个弹出层组件。兼容H5和APP和小程序。 功能&#xff1a; 1)只支持上下左右4个方向的弹层不支持侧边靠齐 2)不对屏幕边界适配 3)支持弹层…

[含文档+PPT+源码等]精品基于asp.net实现的原生Andriod病例管理随访系统[包运行成功+永久免费答疑辅导]

基于ASP.NET实现的原生Android病例管理随访系统背景&#xff0c;可以从以下几个方面进行阐述&#xff1a; 一、技术背景 ASP.NET技术框架 ASP.NET是由微软开发的一种用于构建动态Web应用程序和服务的开源服务器端Web应用框架。它提供了一套丰富的工具和库&#xff0c;支持多种…