OpenCV笔记整理【人脸检测之Harr级联分类器dlib库】

news2025/4/27 5:26:41

1. 级联分类器: OpenCV提供的级联分类器有Harr、HOG、LBP这3种,这些分类器以XML文件保存,这里主要演示Harr检测人脸(OpenCV提供的分类器不仅限于检测人脸,还包括下表特征检测,当然OpenCV还支持训练自己的级联分类器,这里不做说明。。。)。
在这里插入图片描述

2. 函数介绍:

object = cv2.CascadeClassifier(filename) 加载分类器

  • object:分类器对象。
  • filename:分类器xml路径+文件名。

object= faceCascade.detectMultiScale(img,scaleFactor,minNeighbors,minSize,maxSize) 检测对象

  • object:返回值(目标对象的x、y、w、h信息)。
  • scaleFactor:缩放比例。
  • minNeighbors:检测目标的相邻矩形的最小个数。默认为3,表示满足3个以上的检测标记才会认为是人脸。该值越大越准确,但是会导致一些人脸检测不到。
  • minSize:目标最小尺寸,小于会被忽略。

上代码:检测图片中的人脸

import cv2
# 1 原始图像处理
image = cv2.imread('model1.jpg')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)

# 2 加载分类器
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

# 3 人脸检测
faces = faceCascade.detectMultiScale(
    gray,
    scaleFactor = 1.01,
    minNeighbors = 15,
    minSize = (8,8))
    
# 4 打印输出的实现
print("发现{0}张人脸!".format(len(faces)))
print("其位置分别是:")
print(faces)

# 5 遍历检测对象
for(x,y,w,h) in faces:
  cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2) # 绘制矩形(x、y、w、h)
  
cv2.imshow("result",image)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行:
在这里插入图片描述
上代码:通过摄像头检测人脸

import cv2
# 1 加载分类器
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

# 2 处理摄像头视频
# 初始化摄像头
cap=cv2.VideoCapture(0,cv2.CAP_DSHOW)
# 处理每一帧
while True:
    # 读取一帧
    ret,image=cap.read()
    image=cv2.flip(image,1)
    # 没有读到,直接退出
    if ret is None:
        break
    # 灰度化(彩色BGR-->灰度Gray)    
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    
    # 人脸检测
    faces = faceCascade.detectMultiScale(gray,
                                         scaleFactor = 1.1,
                                         minNeighbors = 5,
                                         minSize = (5,5))
    # 处理每个人脸
    for(x,y,w,h) in faces:
      cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2) 
      # 提取人脸所在区域,单通道形式
      roi=gray[y:y+h,x:x+w] #image[起点,终点]

    # 显示结果
    cv2.imshow("dect",image)
    cv2.imshow("roi",cutFace)
    key=cv2.waitKey(25)
    if key==27:
        break
cap.release()
cv2.destroyAllWindows()

运行:
测试

3. dlib库检测人脸: 免费的开源库,虽然测试速度不及前面的Harr级联分类器,但是准确率非常高。

  • 检测人脸:
    detector=dlib.get_frontal_face_detector() 构造dlib检测器
    faces=detector(img,n) 检测人脸
    faces:人脸集合。
    n:上采样次数,图像会变大,但是准确率会提高,这个参数对速度影响极大。

上代码:

import cv2
import dlib

# dlib初始化
detector=dlib.get_frontal_face_detector()
# 读取原始图像
img=cv2.imread("imgs/3.jpg")
# 使用人脸检测器返回检测到的人脸框
faces=detector(img,1)

# 遍历人脸集合
for face in faces:
    # 获取人脸框的坐标
    x1=face.left()
    y1=face.top()
    x2=face.right()
    y2=face.bottom()
    # 绘制人脸框
    cv2.rectangle(img,(x1,y1),(x2,y2),(0,255,0),2)
# 显示捕获到的各个人脸框
cv2.imshow("result",img)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行:
在这里插入图片描述

  • 检测关键点:
    detector=dlib.get_frontal_face_detector() 构造dlib检测器
    faces=detector(img,n) 检测人脸
    predictor = dlib.shape_predictor(dat) 加载预测
    dat:模型文件
    predictor:预测器对象,返回68个脸部关键点。

上代码:

import numpy as np
import cv2
import dlib
# 读取图像
srcImg = cv2.imread("model.jpg")
img=srcImg.copy()
# Step 1:构造人脸检测器(dlib初始化)
detector = dlib.get_frontal_face_detector()
# Step 2:检测人脸框(使用人脸检测器返回检测到的人脸框)
faces = detector(img, 1)
# Step 3:载入模型(加载预测器)
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

index=0
# Step 4:获取每一张脸的关键点(实现检测)
for face in faces:
    index+=1
    # 检测当前人脸的关键点
    shape=predictor(img, face)

    # 下面对这句代码进行了分解
    # landmarks = np.matrix([[p.x, p.y] for p in shape.parts()])
    
    # 通过shape.parts()方法遍历关键点
    for i, p in enumerate(shape.parts()): 
        print('face:'+str(index)+' predictor:'+str(i)+' x:'+str(p.x)+' y:'+str(p.y))
        # 将关键点的x,y放入一个2列68行的矩阵中,需要知道的是,人脸的每个特征对应的关键点索引是固定的,比如36-42描述的右眼。
        landmarks = np.matrix([[p.x, p.y]])
        
        # Step 5:绘制每一张脸的关键点(绘制shape中的每个点)
        for idx, point in enumerate(landmarks):
            # 当前关键的坐标:[0,1]表示第0行第1个元素
            pos = (point[0, 0], point[0, 1])
            # 针对当前关键点,绘制一个实心圆
            cv2.circle(img, pos, 2, color=(0, 255, 0), thickness=-1)
            # 字体
            font = cv2.FONT_HERSHEY_SIMPLEX
            # 利用cv2.putText输出1-68,索引序号加1,显示时从1开始。
            cv2.putText(img, str(i + 1), pos, font, 0.4, (255, 255, 255), 1, cv2.LINE_AA)
            
# 绘制结果

cv2.imshow("img", img)
cv2.imshow("src", srcImg)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述

  • 勾勒五官轮廓:
    关键点检测实现步骤和前面一样,唯一不同的是:

脸部轮廓、眉毛这种起点和终点分开的区域,首先找到轮廓所在的关键点,然后使用点到点之间绘制直线的方式绘制边缘。
脸部眼睛、嘴巴这种起点和终点最终汇聚在一起的区域,首先找到轮廓所在的关键点,然后将这一组关键点坐标作为轮廓数组传入convexHull()函数进行凸包绘制。


凸包:找到图形最外侧的端点,然后将其连接起来。
凸包示例代码:

import cv2

img = cv2.imread("shape2.png")  # 读取原始图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转为灰度图像
ret, binary = cv2.threshold(gray, 127, 225, cv2.THRESH_BINARY)  # 二值化阈值处理
# 检测图像中出现的所有轮廓
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

hull = cv2.convexHull(contours[0])  # 获取轮廓的凸包
cv2.drawContours(img, [hull], -1, (0, 255, 0), 2)

cv2.imshow("img", img)  # 显示图像
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

凸包运行结果:
在这里插入图片描述

勾勒五官轮廓代码:

import numpy as np
import dlib
import cv2

# 模型初始化
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

# 自定义函数drawLine,将指定的点连接起来
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):
    # 注意,凸包用来绘制眼睛、嘴
    # 眼睛、嘴也可以用drawLine通过直线绘制
    # 但是,使用凸包绘制轮廓,更方便进行颜色填充等设置
    # 获取某个特定五官的点集
    Facial = shape[start:end]
    # 针对该五官构造凸包
    mouthHull = cv2.convexHull(Facial)
    # 把凸包轮廓绘制出来
    cv2.drawContours(image, [mouthHull], -1, (0, 255, 0), 2)

# 读取图像
srcImg=cv2.imread("model2.jpg")
image=srcImg.copy()
# 色彩空间转换彩色(BGR)-->灰度(Gray)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 获取人脸
faces = detector(gray, 3)
# 对检测到的rects,逐个遍历
for face in faces:
    # 针对脸部的关键点进行处理,构成坐标(x,y)形式
    shape = np.matrix([[p.x, p.y] for p in predictor(gray, face).parts()])

    # ============使用函数drawConexHull绘制嘴、眼睛=========================
    #获取嘴部的关键点集(在整个脸部索引中,其索引范围为[48,60],不包含61)
    drawConvexHull(48,59)
    # 嘴内部
    drawConvexHull(60,68)
    # 左眼
    drawConvexHull(42,48)
    # 右眼
    drawConvexHull(36,42)

    # ============使用函数drawLine绘制脸颊、眉毛、鼻子=========================
    # 将shape转换为np.array
    shape=np.array(shape)
    # 绘制脸颊,把脸颊的各个关键点(索引0-16,不含17)用线条连接起来
    drawLine(0,17)
    # 绘制左眉毛,通过将关键点连接实现(索引18-21)
    drawLine(17,22)
    # 绘制右眉毛(索引23-26)
    drawLine(22,27)
    # 鼻子(索引27-36)
    drawLine(27,36)

cv2.imshow("Frame", image)
cv2.imshow("Src",srcImg)
cv2.waitKey()
cv2.destroyAllWindows()

运行:
在这里插入图片描述


以上,如有错误,欢迎指正批评!

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

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

相关文章

Vim学习笔记【Ch02】

Vim学习笔记 系列笔记链接Ch02 Buffers, Windows, TabsBuffers什么是buffer查看所有bufferbuffer之间的切换删除buffer退出所有窗口 Windows窗口的创建窗口切换快捷键其他快捷键 Tabs什么是tabtab相关命令 window和buffer结合的3D移动小结 系列笔记链接 Ch00,Ch01 …

python介绍——入门

前言 Python 是一种面向对象的解释型计算机程序设计语言,它继承了传统编译语言的强大性和通用性,同时也借鉴了脚本语言和解释语言的易用性。今天我就来给大家简单介绍一下python: 一、python的起源 1989年的圣诞节期间,吉多▪范…

Redis底层学习(二)—存储类型-String篇

这里写目录标题 应用场景底层结构知识普及 应用场景 服务器命令: 1.单值缓存 存储key,value :SET key value2.对象缓存 存储key,value :SET key value(json 格式数据) 3.分布式锁 底层结构 我们可以通过命令查看 value…

C++ 学习 ::【基础篇:14】:C++ 类的基本成员函数:析构函数的作用 及 自定义析构函数情形

本系列 C 相关文章 仅为笔者学习笔记记录,用自己的理解记录学习!C 学习系列将分为三个阶段:基础篇、STL 篇、高阶数据结构与算法篇,相关重点内容如下: 基础篇:类与对象(涉及C的三大特性等&#…

scratch找食物 中国电子学会图形化编程 少儿编程 scratch编程等级考试一级真题和答案解析2023年5月

目录 scratch找食物 一、题目要求 1、准备工作 2、功能实现 二、案例分析

全志V3S嵌入式驱动开发(多按键输入驱动)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 前面我们说过,荔枝派的开发板上面,有4个按键本身不是通过gpio连接到soc上面的。它是通过ad的方法,连接到主芯片…

SpringCloud GateWay-Filter学习

3 Filter/过滤器 文章目录 3 Filter/过滤器1 GatewayFilter 使用 -- 路由过滤器2 GatewayFilter 使用 -- 自定义过滤器 路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应Spring Cloud Gateway 内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生 1 Gat…

华为OD机试真题B卷 Java 实现【IPv4地址转换成整数】,附详细解题思路

一、题目描述 存在一种虚拟 IPv4 地址,由4小节组成,每节的范围为0~255,以#号间隔, 虚拟 IPv4 地址可以转换为一个32位的整数,例如: 128#0#255#255,转换为32位整数的结果为2147549183&#xff0…

以技术实践赋能开源安全|2023开放原子全球开源峰会开源安全技术与实践分论坛即将启幕

作为数字化转型时代的重要技术和协作模式,开源软件在各行各业得到广泛应用,由此也引发了诸多与安全相关的问题。6月12日,2023开放原子全球开源峰会“开源安全技术与实践”分论坛将在北京经开区北人亦创国际会展中心举行。 本次分论坛由开放原…

为什么说 Go 语言字符串是不可变的?

原文链接: 为什么说 Go 语言字符串是不可变的? 最近有读者留言说,平时在写代码的过程中,是会对字符串进行修改的,但网上都说 Go 语言字符串是不可变的,这是为什么呢? 这个问题本身并不困难&am…

SAP-QM-物料主数据-质量管理视图字段解析

过账到质检库存:要勾选,否则收货后库存不进入质检库存HU检验:收货到启用HU管理的库位时产生检验批,例如某个成品物料是收货到C002库位,该库位启用了HU管理,那么此处要勾选。但是如果勾选了,却收…

30天学会vue.js?|vue.js 3 移动应用开发实战 阅读笔记

最近又在折腾vuejs, 计划用30天的时间来掌握这个前端语言。 大概用了一周时间看完这本书。 这本书需要有编程基础的同学阅读。如果从零开始学前端的话,个人不建议,书本内容跳跃性很大,甚至个人觉得有点凌乱。PS:阅读此书一定要配…

黑马Redis视频教程实战篇(五)

目录 一、达人探店 1.1、发布探店笔记 1.2、查看探店笔记 1.3、点赞功能 1.4、点赞排行榜 二、好友关注 2.1、关注和取消关注 2.2、共同关注 2.3、Feed流实现方案 2.4、推送到粉丝收件箱 2.4、实现分页查询收邮箱 一、达人探店 1.1、发布探店笔记 发布探店笔记 探…

自定义组件和样式学习

一、使用组件3步 例如:APP.vue中使用另外两个组件Left.vue,Right.vue (3个页面) 1.在APP.vue中用import *** from **** 导入Left.vue、Right.vue页面 2.在APP.vue的js中和data同级注册,components{Left,Rirght} 3.注册完后可在APP…

JAVA内存深度分析报告

文章目录 理论部分:1.Heap Memory(堆内存)2.Non-heap Memory(堆外内存)3.Direct Memory(直接内存) 实验部分:1.Platform MXBeans API 监控快照2.MetaSpace 快照:3.Native Memory 快照…

线程池的实现原理

线程池的实现原理 所谓线程池,通俗的理解就是有一个池子,里面存放着已经创建好的线程,当有任务提交给线程池执行时,池子中的某个线程会主动执行该任务。如果池子中的线程数量不够应付数量众多的任务时,则需要自动扩充…

华为OD机试真题B卷 Java 实现【素数之积】,附详细解题思路

一、题目描述 RSA加密算法在网络安全世界中无处不在,它利用了极大整数因数分解的困难度,数据越大,安全系数越高。 给定一个32位正整数,请对其进行因数分解,找出是哪两个素数的乘积。 二、输入描述 一个正整数num …

科普:什么是小米刷机中的FASTBOOT

目录 1. 什么是手机上的FASTBOOT模式?2. 如何进入与退出FASTBOOT模式?2.1 进入方式2.2 退出方式 3. 如何在PC端安装FASTBOOT驱动?4. 怎么开启FASTBOOT命令提示符?5. 目前FASTBOOT命令有哪些类型?6. 常用的FASTBOOT命令…

第五章 堆内存

文章目录 前言一、🚘 本地方法1、什么是本地方法2、为什么使用 Native Method 二、🚄 本地方法栈三、🚥 堆内存1、-Xms10m -Xmx10m 设置堆内存的大小2、内存细分3、设置堆空间的大小与OOMjps 查看Java程序进程jstat -gc 进程号 查看堆内存参数…

CMake构建大型C/C++项目:跨平台设计与高级应用

CMake构建大型C/C项目:跨平台设计与高级应用 一、跨平台设计(Cross-Platform Design)1.1 跨平台设计原理(Principles of Cross-Platform Design)1.2 跨平台设计1.2.1 CMake的跨平台特性1.2.2 使用CMake进行跨编译1.2.3…