当前位置: 首页 > article >正文

《计算机视觉》—— 基于dlib库的人脸关键部位的轮廓检测

文章目录

  • 一、检测的思想
  • 二、代码实现

一、检测的思想

  • 在代码中我们将基于dlib库中的方法,调用别人已经训练好的人脸关键点定位模型,实现对人脸关键点的定位,这里我们将调用使用68个关键点来对人脸进行关键点定位的模型。
  • 68个关键点定位后的效果如下图:
    在这里插入图片描述
  • 显示出的这68个关键点旁边的数字,对应的是它们的索引号,其中脸部的几个关键部位都是由固定的关键点所定位,如下所述:
    • [0~16]:这17个关键点用于脸颊的关键点定位
    • [17~21]:这5个关键点用于左眉毛的关键点定位
    • [22~26]:这5个关键点用于右眉毛的关键点定位
    • [27~35]:这9个关键点用于鼻子的关键点定位
    • [36~41]:这6个关键点用于左眼睛的关键点定位
    • [42~47]:这6个关键点用于右眼睛的关键点定位
    • [48~59]:这12个关键点用于嘴外部的关键点定位
    • [60~67]:这8个关键点用于嘴内部的关键点定位
  • 人脸关键点定位的实现可以通过以下链接内容了解:
    • https://blog.csdn.net/weixin_73504499/article/details/142990867?spm=1001.2014.3001.5501
  • 根据每个人脸关键部位的关键点画出各部位的轮廓,效果如下:
    在这里插入图片描述

二、代码实现

  • 眼睛和嘴的绘制方式与其他部位有所不同,嘴和眼睛用凸包的形式画出轮廓

    • 凸包:在二维欧几里得空间中,凸包可以想象为一条刚好包着所有点的橡皮圈。换句话说,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集中所有的点。
  • 在检测轮廓之前需要对人脸进行检测,以下链接是基于dlib库的人脸检测

    • https://blog.csdn.net/weixin_73504499/article/details/142977202?spm=1001.2014.3001.5501
  • 眼睛和嘴的绘制函数如下:

    def drawConvexHull(start, end):
        # 将指定的点构成一个凸包,绘制成轮廓,一般眼睛、嘴使用凸包来绘制
        Facial = shape[start: end + 1]  # shape --> 包含了68个关键点坐标
        mouthHull = cv2.convexHull(Facial)  # 凸包函数 --> 返回凸包的顶点
        # 绘制出轮廓
        cv2.drawContours(image, [mouthHull], -1, (0, 255, 0), 2)
    
  • 其他部位的绘制函数如下:

    def drawLine(start, end):  # 将指定的点连接起来
        pts = shape[start: end]  # 获取点集 shape --> 包含了68个关键点坐标
        for l in range(1, len(pts)):  # 将每个点坐标转换为元组的形式,再用线连起来 
            ptA = tuple(pts[l - 1])
            ptB = tuple(pts[l])
            # 用连线的函数画出轮廓
            cv2.line(image, ptA, ptB, (0, 255, 0), 2)
    
  • 完整代码如下:

    import numpy as np
    import dlib
    import cv2
    
    """ 绘制眉毛、鼻子、脸颊的轮廓 """
    def drawLine(start, end):  # 将指定的点连接起来
        pts = shape[start: end]  # 获取点集 shape --> 包含了68个关键点坐标
        for l in range(1, len(pts)):  # 将每个点坐标转换为元组的形式,再用线连起来
            ptA = tuple(pts[l - 1])
            ptB = tuple(pts[l])
            # 用连线的函数画出轮廓
            cv2.line(image, ptA, ptB, (0, 255, 0), 2)
    
    
    """ 绘制眼睛和嘴巴的轮廓 """
    def drawConvexHull(start, end):
        # 将指定的点构成一个凸包,绘制成轮廓,一般眼睛、嘴使用凸包来绘制
        Facial = shape[start: end + 1]  # shape --> 包含了68个关键点坐标
        mouthHull = cv2.convexHull(Facial)  # 凸包函数 --> 返回凸包的顶点
        # 绘制出轮廓
        cv2.drawContours(image, [mouthHull], -1, (0, 255, 0), 2)
    
    
    image = cv2.imread('kobe_2.jpg')    # 读取图片
    detector = dlib.get_frontal_face_detector()  # 构造脸部位置检测器
    faces = detector(image, 0)  # 检测人脸方框位置
    # 获取人脸关键点定位模型
    predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
    
    for face in faces:  # 对获取到得到 faces ,逐个遍历
        shape = predictor(image, face)  # 获取68个关键点
        # 将关键点转换为坐标(x, y)的形式
        shape = np.array([[p.x, p.y] for p in shape.parts()])
    
        drawConvexHull(36, 41)  # 绘制右眼凸包
        drawConvexHull(42, 47)  # 绘制左眼凸包
        drawConvexHull(48, 59)  # 绘制嘴外部凸包
        drawConvexHull(60, 67)  # 绘制嘴内部凸包
    
        drawLine(0, 17)  # 绘制脸颊点线
        drawLine(17, 22)  # 绘制左眉毛点线
        drawLine(22, 27)  # 绘制右眉毛点线
        drawLine(27, 36)  # 绘制鼻子点线
    
    # 显示结果
    cv2.imshow("Frame", image)
    cv2.waitKey()
    # 关闭窗口
    cv2.destroyAllWindows()
    
  • 结果如下:
    在这里插入图片描述

  • 以下是通过打开电脑的摄像头,对画面中出现的人脸进行关键部位的轮廓检测,完整代码如下:

    def drawLine(start, end):  
        pts = shape[start: end] 
        for l in range(1, len(pts)):
            ptA = tuple(pts[l - 1])
            ptB = tuple(pts[l])
            cv2.line(image, ptA, ptB, (0, 255, 0), 2)
    
    
    def drawConvexHull(start, end):
        Facial = shape[start: end + 1]
        mouthHull = cv2.convexHull(Facial) 
        cv2.drawContours(image, [mouthHull], -1, (0, 255, 0), 2)
    
    
    cap = cv2.VideoCapture(0)   # 0-->打开电脑自带的摄像头, 1-->打开电脑外接的摄像头
    
    detector = dlib.get_frontal_face_detector()  # 构造脸部位置检测器
    
    # 获取人脸关键点定位模型
    predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
    
    if not cap.isOpened():  # 判断摄像头是否正常打开
        print("Cannot open camera")
        exit()
    
    while True:  # 若正常打开摄像头则对摄像头拍摄的每一帧画面进行循环处理
        ret, image = cap.read()  # 如果正确读取一帧图像,ret为True, image-->读取的画面
        image = cv2.flip(image, 1)  # 图片翻转,水平翻转(镜像)
        # 如果没有正确读取到图像,则退出循环
        if not ret:
            print("不能读取摄像头")
            break
    
        faces = detector(image, 0)  # 检测人脸方框位置
    
        for face in faces:  # 对获取到得到 faces ,逐个遍历
            shape = predictor(image, face)  # 获取关键点
            # 将关键点转换为坐标(x, y)的形式
            shape = np.array([[p.x, p.y] for p in shape.parts()])
    
            drawConvexHull(36, 41)  # 绘制右眼凸包
            drawConvexHull(42, 47)  # 绘制左眼凸包
            drawConvexHull(48, 59)  # 绘制最外部凸包
            drawConvexHull(60, 67)  # 绘制嘴内部凸包
    
            drawLine(0, 17)  # 绘制脸颊点线
            drawLine(17, 22)  # 绘制左眉毛点线
            drawLine(22, 27)  # 绘制右眉毛点线
            drawLine(27, 36)  # 绘制鼻子点线
        
        cv2.imshow("Frame", image)
        
        # 检查是否按下ESC键(ASCII码27),如果按下则退出循环
        if cv2.waitKey(10) == 27:
            break
    
    # 释放摄像头资源
    cap.release()
    # 关闭所有OpenCV创建的窗口
    cv2.destroyAllWindows()
    

http://www.kler.cn/news/363809.html

相关文章:

  • 初识知识图谱
  • Android 图片相识度比较(pHash)
  • 关于写查询接口的一些理解
  • HCIP--1
  • 负载均衡服务器攻击怎么解决最有效?
  • 常用 SQL 语句的大全
  • 【MySQL】详解表的约束
  • 【途牛旅游网-注册/登录安全分析报告】
  • vue2.x中的数据劫持
  • 视频剪辑和转换gif一体化UI页面【可以解决gif体积过大】
  • 【YOLOv11】制作使用YOLOv11的docker环境
  • 一道面试题:为什么要使用Docker?
  • Java项目-基于springboot框架的智慧外贸系统项目实战(附源码+文档)
  • COVON全意卫生巾凭借其轻薄、透气、绵柔的特点,在东南亚市场上迅速走红
  • 攻坚金融关键业务系统,OceanBase亮相2024金融科技大会
  • 调整Android板子的分辨率
  • 内网python smtplib用ssh隧道通过跳板机发邮件
  • 微积分复习笔记 Calculus Volume 1 - 3.2 he Derivative as a Function
  • 【Linux学习】(3)Linux的基本指令操作
  • 关闭或开启Win11系统的自动更新
  • springboot接口Get请求实体类入参
  • VirtualBox、VMware安装Linux后重启再次进入安装界面的问题解决
  • 微信小程序用开发工具在本地真机调试可以正常访问摄像头,发布了授权后却无法访问摄像头,解决方案
  • 钡铼技术R10工业4G路由服务智慧城市建设
  • Tauri(读音:踹你)开发简介:1.创建和运行第一个app
  • 20241021给荣品RD-RK3588-AHD开发板刷荣品预编译的Android12之后使用GPStest测试板载GPS