【youcans 的 OpenCV 学习课】23. 人脸检测:Haar 级联检测器

news2024/11/27 4:39:37

专栏地址:『youcans 的图像处理学习课』
文章目录:『youcans 的图像处理学习课 - 总目录』


【youcans 的 OpenCV 学习课】23. 人脸检测:Haar 级联检测器

    • 4. Haar 级联分类器
    • 5. Haar 人脸/人眼检测器
      • 5.1 OpenCV 中的级联分类器
      • 5.2 Haar 级联检测器的预训练模型
      • 5.3 人脸检测/人眼检测的实现步骤
      • 例程 17_6:使用 Haar 级联检测器检测人脸
      • 例程 17_7:使用 Haar 级联检测器检测人眼
      • 例程 17_8:使用 Haar 级联检测器检测人脸和人眼
      • 例程 17_9:使用 Haar 级联分类器进行视频人脸检测


4. Haar 级联分类器

基于 Haar 特征的级联分类器是 Paul Viola 在论文”Rapid Object Detection using a Boosted Cascade of Simple Features”中提出的一种目标检测方法。

Haar 级联分类器在每一级的节点中,使用 AdaBoost 算法学习一个高检测率低拒绝率的多层分类器。其特点是:

  1. 使用 Haar-like 输入特征,对矩形图像区域的和或者差进行阈值化。

  2. 使用积分图像计算 45°旋转区域的像素和,加速 Haar-like 输入特征的计算。

  3. 使用统计 Boosting 来创建二分类(人脸/非人脸)的分类器节点(高通过率,低拒绝率)。

  4. 将弱分类器并联组合起来,构成筛选式级联分类器。

在这里插入图片描述

各级的 Boosting 分类器对于有人脸的检测窗口都能通过,同时拒绝一小部分非人脸的检测窗口,并将通过的检测窗口传给下一个分类器。依次类推,最后一个分类器将几乎所有非人脸的检测窗口都拒绝掉,只剩下有人脸的检测窗口。因此,只要检测窗口区域通过了所有各级 Boosting 分类器,则认为检测窗口中有人脸。

在实际应用中输入图片的尺寸较大,需要进行多区域、多尺度的检测。多区域是要遍历图片的不同位置,多尺度是为了检测图片中不同大小的人脸。

在 Haar 级联分类人脸检测器中,主要利用了人脸的结构化特征:

  • 与脸颊相比,眼部颜色较深
  • 与眼睛相比,鼻梁区域较为明亮
  • 眼睛、嘴巴、鼻子的位置较为固定

通过这 5 个矩形区域的明暗关系,就可以形成对人脸的各个部分的判别特征。例如在下图中,第一个特征检测眼部和上脸颊之间的强度差异,第二个特征检测双眼的间距。

在这里插入图片描述

Haar 人脸检测训练很高,但对侧脸的检测性能较差。


5. Haar 人脸/人眼检测器

5.1 OpenCV 中的级联分类器

OpenCV 中定义了级联分类器类 cv::CascadeClassifier。在 Python 语言中,使用接口函数 cv.CascadeClassifier() 从文件创建分类器。

cv.CascadeClassifier(filename)
cv.CascadeClassifier.load(filename[, ]) → retval
cv.CascadeClassifier.read(node[, ]) → retval
cv.CascadeClassifier.empty([, ]) → retval

cv.CascadeClassifier.convert(oldcascade, newcascade[, ]) → retval
cv.CascadeClassifier.detectMultiScale(image[, scaleFactor=1.1, minNeighbors=3, flags=0, minSize=Size(), maxSize=Size()]) → objects

成员函数 cv.CascadeClassifier.load() 从文件加载级联分类器模型,成员函数 cv.CascadeClassifier.read() 从FileStorage 节点读取分类器,成员函数 cv.CascadeClassifier.empty()检测分类器是否加载成功。

成员函数 cv.CascadeClassifier.detectMultiScale() 用于执行对图像进行目标检测,成员函数 cv.CascadeClassifier.convert()


参数说明:

  • filename:加载分类器模型的文件路径和名称,字符串。
  • image:待检测的输入图像,CV_8U 格式。
  • scaleFactor:搜索窗口的缩放比例,默认值为1.1。
  • minNeighbors:表示构成检测目标的相邻矩形的最小个数,默认值为 3。
  • flags:版本兼容标志,默认值为 0。
  • minSize:检测目标的最小尺寸,元组 (h,w)。
  • maxSize:检测目标的最大尺寸,元组 (h,w)。
  • objects:返回值,检测目标的矩形边界框 ,是形如 (N,4) 的Numpy数组。

参数说明:

(1)返回值 objects 是形如 (N,4) 的Numpy数组,每行有 4个元素 (x, y, width, height) 表示矩形框的左上顶点坐标 (x,y) 和宽度 width、高度 height。

(2)加载的级联分类器模型文件,扩展名为 .xml。


5.2 Haar 级联检测器的预训练模型

OpenCV 提供了级联分类器的训练方法,也可以直接下载预训练模型后使用 load() 方法加载模型。

OpenCV 提供的 Haar 级联检测器的预训练模型位于 OpenCV 安装包的 \data\haarcascades文件夹,或者从 【GitHub】opencv/data at 4.x 下载。

在这里插入图片描述


OpenCV 提供的 haar 级联检测器的预训练模型包括:

haarcascade_eye.xml, 眼睛
haarcascade_eye_tree_eyeglasses.xml, 戴眼镜的眼睛
haarcascade_frontalcatface.xml, 正面猫脸
haarcascade_frontalcatface_extended.xml, 正面猫脸
haarcascade_frontalface_alt.xml, 正面人脸
haarcascade_frontalface_alt2.xml, 正面人脸
haarcascade_frontalface_alt_tree.xml, 正面人脸
haarcascade_frontalface_default.xml, 正面人脸
haarcascade_fullbody.xml, 人体
haarcascade_lefteye_2splits.xml, 左眼
haarcascade_license_plate_rus_16stages.xml, 
haarcascade_lowerbody.xml, 
haarcascade_profileface.xml, 
haarcascade_righteye_2splits.xml, 右眼
haarcascade_russian_plate_number.xml, 
haarcascade_smile.xml, 笑脸
haarcascade_upperbody.xml, 上身

5.3 人脸检测/人眼检测的实现步骤

使用 Haar 级联检测器检测图片中的人脸的步骤:

(1)创建一个 CascadeClassifier 级联分类器对象,使用 load() 方法从 .xml 文件加载级联分类器模型。

(2)读取待检测的图片。

(3)使用 detectMultiScale() 方法检测图片,返回检测到的面部或眼睛的边界矩形。

(4)将检测到的边界矩形绘制到检测图片上。


例程 17_6:使用 Haar 级联检测器检测人脸

使用 Haar 级联检测器检测图片中的人脸。

import numpy as np
import cv2 as cv

if __name__ == '__main__':
    # (6) 使用 Haar 级联分类器 预训练模型 检测人脸
    # 读取待检测的图片
    img = cv.imread("../images/img_group_02.jpg", flags=1)
    print(img.shape)

    # 加载 Haar 级联分类器 预训练模型
    model_path = "../data/haarcascade_frontalface_alt2.xml"
    face_detector = cv.CascadeClassifier(model_path)  # <class 'cv2.CascadeClassifier'>
    # 使用级联分类器检测人脸
    faces = face_detector.detectMultiScale(img, scaleFactor=1.1, minNeighbors=1,
                                           minSize=(30, 30), maxSize=(300, 300))
    print(faces.shape)  # (17, 4)
    print(faces[0])  # (x, y, width, height)

    # 绘制人脸检测框
    for x, y, width, height in faces:
        cv.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2, cv.LINE_8, 0)
    # 显示图片
    cv.imshow("faces", img)
    cv.waitKey(0)
    cv.destroyAllWindows()

在这里插入图片描述

Haar 级联检测器可以对人脸检出率较高,但有一定的错检率,即有些检测结果中并不是人脸。


例程 17_7:使用 Haar 级联检测器检测人眼

人眼检测的方法与人脸检测方法相同,只是使用了不同的预训练模型,例如 haarcascade_eye.xml。

由于眼睛比人脸的尺寸小,因此减小了检测函数 detectMultiScale() 的参数 minSize=(20, 20), maxSize。

import numpy as np
import cv2 as cv

if __name__ == '__main__':
    # (7) 使用 Haar 级联分类器 预训练模型 检测人眼
    # 读取待检测的图片
    img = cv.imread("../images/img_group_01.jpg", flags=1)
    print(img.shape)

    # 加载 Haar 级联分类器 预训练模型
    model_path = "../data/haarcascade_eye.xml"
    eye_detector = cv.CascadeClassifier(model_path)  # <class 'cv2.CascadeClassifier'>
    # 使用级联分类器检测人脸
    eyes = eye_detector.detectMultiScale(img, scaleFactor=1.1, minNeighbors=1,
                                           minSize=(20, 20), maxSize=(100, 100))
    print(eyes.shape)  # (51, 4)
    print(eyes[0])  # (x, y, width, height)

    # 绘制人脸检测框
    for x, y, width, height in eyes:
        cv.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2, cv.LINE_8, 0)
    # 显示图片
    cv.imshow("Haar_Cascade", img)
    # cv.imwrite("../images/imgSave3.png", img)
    cv.waitKey(0)
    cv.destroyAllWindows()

在这里插入图片描述


例程 17_8:使用 Haar 级联检测器检测人脸和人眼

为了提高检测效率,可以先检测人脸,再在人类窗口内检测人眼,不仅可以提高检测效率,而且可以提高检测精度。

import numpy as np
import cv2 as cv

if __name__ == '__main__':
    # (8) 使用 Haar 级联分类器 预训练模型 检测人脸和人眼
    # 读取待检测的图片
    img = cv.imread("../images/img_group_01.jpg", flags=1)
    print(img.shape)

    # 加载 Haar 级联分类器 预训练模型
    face_path = "../data/haarcascade_frontalface_alt2.xml"  # 人脸检测器
    face_detector = cv.CascadeClassifier(face_path)  # <class 'cv2.CascadeClassifier'>
    eye_path = "../data/haarcascade_eye.xml"  # 人眼检测器
    eye_detector = cv.CascadeClassifier(eye_path)  # <class 'cv2.CascadeClassifier'>
    # 使用级联分类器检测人脸
    faces = face_detector.detectMultiScale(img, scaleFactor=1.1, minNeighbors=2,
                                           minSize=(30, 30), maxSize=(300, 300))
    print(faces.shape)  # (15, 4)

    # 绘制人脸检测框
    for x, y, width, height in faces:
        cv.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2, cv.LINE_8, 0)
        # 在人脸区域内检测人眼
        roi = img[y:y + height, x:x + width]  # 提取人脸
        # 检测人眼
        eyes = eye_detector.detectMultiScale(roi, scaleFactor=1.1, minNeighbors=1,
                                             minSize=(20, 20), maxSize=(80, 80))
        # 绘制人眼
        for ex, ey, ew, eh in eyes:
            cv.rectangle(img, (x+ex, y+ey), (x+ex+ew, y+ey+eh), (255, 0, 0), 2)

    # 显示图片
    cv.imshow("Haar_Cascade", img)
    # cv.imwrite("../images/imgSave4.png", img)
    cv.waitKey(0)
    cv.destroyAllWindows()

在这里插入图片描述


例程 17_9:使用 Haar 级联分类器进行视频人脸检测

首先启动摄像头或读取视频文件,读取视频帧。然后将视频帧转换为灰度图像,使用 cascade级联检测器检测人脸。对于检测到的人脸,都加上一个矩形框。

import numpy as np
import cv2 as cv

if __name__ == '__main__':
    # (9) 使用 Haar 级联分类器检测视频流
    # 加载 Haar 级联分类器 预训练模型
    face_path = "../data/haarcascade_frontalface_default.xml"  # 人脸检测器
    face_detector = cv.CascadeClassifier(face_path)  # <class 'cv2.CascadeClassifier'>

    # 创建视频读取/捕获对象
    vedioRead = "../images/Megamind.avi"  # 读取视频文件的路径
    videoCap = cv.VideoCapture(vedioRead)  # 实例化 VideoCapture 类

    frameNum = 0  # 视频帧数初值
    # ret, frame = videoCap.read()  # 读取一帧图像
    # print("frame: ", frame.shape)  # (528, 720, 3)
    timef = 40  # 设置抽帧间隔
    plt.figure(figsize=(9, 5.6))
    while videoCap.isOpened():  # 检查视频捕获是否成功
        ret, frame = videoCap.read()  # 读取一帧图像, (528, 720, 3)
        if ret is True:
            frameNum += 1  # 读取视频的帧数
            gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)  # 灰度处理
            # 使用级联分类器检测人脸
            faces = face_detector.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=2,
                                                   minSize=(50, 50), maxSize=(300, 300))
            # 绘制人脸检测框
            for x, y, width, height in faces:
                cv.rectangle(frame, (x, y), (x + width, y + height), (0, 0, 255), 2, cv.LINE_8, 0)
            cv.imshow('frame', frame)  # 目标识别视频
            if (frameNum%timef==0 and 1<=frameNum//timef<= 6):  # 判断抽帧条件
                plt.subplot(2, 3, frameNum//timef), plt.axis('off')
                plt.title("{}. Face detector (f={})".format(frameNum//timef, frameNum))
                plt.imshow(cv.cvtColor(frame, cv.COLOR_BGR2RGB))
            if cv.waitKey(10)&0xFF == 27:  # 按 'Esc' 退出
                break
        else:
            print("Can't receive frame at frameNum {}.".format(frameNum))
            break

    print("frameNum: ", frameNum)
    # 释放资源
    videoCap.release()  # 关闭读取视频文件
    cv.destroyAllWindows()  # 关闭显示窗口
    plt.tight_layout()
    plt.show()

在这里插入图片描述



版权声明:

youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/130423104)
Copyright 2022 youcans, XUPT
欢迎关注 『youcans 的 OpenCV 学习课』 系列,持续更新

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

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

相关文章

OPNET Modeler 调试简介

在使用 OPNET Modeler 软件运行仿真时&#xff0c;经常会遇到错误&#xff0c;发现和定位错误所在的地方是解决错误的第一步&#xff0c;那么怎么定位错误呢&#xff0c;这个时候就需要采用仿真调试器 (OPNET Simulation Debugger&#xff0c;ODB)进行调试了。 在 OPNET 中&…

【模电实验】电路元件伏安特性的测绘及电源外特性的测量

实验2电路元件伏安特性的测绘及电源外特性的测量 实验目的 学习测量线性和非线性电阻元件伏安特性的方法&#xff0c;并绘制其特性曲线学习测量电源外特性的方法掌握运用伏安法判定电阻元件类型的方法学习使用直流电压表、电流表&#xff0c;掌握电压、电流的测量方法 实验原…

Java BIO(Blocking IO:同步并阻塞式IO)

1.基本介绍 1>.Java BIO就是传统的java io编程,其相关的类和接口在"java.io"包下; 2>.BIO(Blocking I/O): 同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理; 如果这个连接不做任何事情会造成(服务器)不必…

【C++】STL——list深度剖析 及 模拟实现

文章目录 前言1. list的介绍及使用1.1 list的介绍1.2 list的使用遍历插入删除数据Operations迭代器的功能分类list 的sort性能测试 2. list的模拟实现2.1 STL_list源码浏览2.2 基本结构实现2.3 思考&#xff1a;list迭代器是否可以用原生指针2.4 list迭代器的实现&#xff08;重…

RocketMQ5.1 NameServer 路由管理

文章目录 1. 路由管理核心组件介绍2. RouteInfoManager 路由表3. 路由管理3.1 注册 Broker3.2 注销 Broker3.3 拼凑 TopicRouteData 此文章基于 RocketMQ 5.1 版本进行分析&#xff0c;与 4.x 版本相比此文章分析的部分源码有很大的区别 1. 路由管理核心组件介绍 路由管理是指…

亚马逊、沃尔玛、ebay测评出现风控、砍单、封号怎么解决?

大家好&#xff0c;我是亚马逊测评珑哥&#xff0c;提前祝各位跨境朋友五一假期愉快。 很多卖家和工作室的朋友加珑哥&#xff0c;沟通中很多朋友都在问为什么测评中一直被砍单&#xff0c;封号是什么原因&#xff1f;其实测评不是你随便买个IP&#xff0c;或者买几个买家号就…

轻松掌握mysql慢查询定位与优化知识点

在这里插入图片描述 1、利用工具定位慢sql 1、运维工具Skywalking 1、定位到慢接口 2、追踪慢sql的执行情况 2、利用MySQL的日志定位慢sql 在调式阶段才开启慢日志的查询&#xff0c;因为会损耗一些性能。 3、分析是否正确使用了索引 当我们已经定位到具体哪个sql较慢时&…

【计算几何】帝国边界划分问题【Voronoi图的原理】

一、说明 Voronoi 单元也称为泰森多边形。 Voronoi 图在许多领域都有实际和理论应用&#xff0c;主要是在科学和技术领域&#xff0c;但也在视觉艺术领域使用。Voronoi 图以数学家 Georgy Voronoy 的名字命名&#xff0c;也称为 Voronoi 镶嵌、Voronoi 分解、Voronoi 分区或 Di…

减少过拟合:暂退法

文章目录 &#xff08;一&#xff09;过拟合&#xff08;二&#xff09;暂退法 &#xff08;一&#xff09;过拟合 1.过拟合产生的原因 (1)根本原因&#xff1a; 我们都知道模型参数的优化方式&#xff1a;反向传播更新梯度&#xff0c;然后随机梯度下降。 也非常清楚模型参…

【Java笔试强训 9】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、选择题 二、编程题 &#x1f525;另类加法…

弗洛伊德算法(求最短路径)

弗洛伊德算法介绍 和迪杰斯特拉算法一 样&#xff0c; 弗洛伊德(Floyd)算法也是一种用于寻找给定的加权图中顶点间最短路径的算法。弗洛伊德算法(Floyd)计算图中各个顶点之间的最短路径迪杰斯特拉算法用于计算图中某-一个顶点到其他项点的最短路径。弗洛伊德算法VS迪杰斯特拉算…

【数据库架构】PostgreSQL的最佳群集高可用性方案

如果您的系统依赖PostgreSQL数据库并且您正在寻找HA的集群解决方案&#xff0c;我们希望提前告知您这是一项复杂的任务&#xff0c;但并非不可能实现。 我们将讨论一些解决方案&#xff0c;您可以从中选择对您的容错要求。 PostgreSQL本身不支持任何多主群集解决方案&#xff0…

Python Unet ++ :医学图像分割,医学细胞分割,Unet医学图像处理,语义分割

一&#xff0c;语义分割&#xff1a;分割领域前几年的发展 图像分割是机器视觉任务的一个重要基础任务&#xff0c;在图像分析、自动驾驶、视频监控等方面都有很重要的作用。图像分割可以被看成一个分类任务&#xff0c;需要给每个像素进行分类&#xff0c;所以就比图像分类任务…

C++-FFmpeg-8-(1)基本概念与原理-rtsp-I、P、B 帧-DTS、PTS-

目录 1.rtsp是什么&#xff1f; 2. I、P、B 帧 3.DTS、PTS 4.rtsp协议抓包分析&#xff1f; 1.rtsp是什么&#xff1f; 流程&#xff1a; 鉴权&#xff1a; 2种 &#xff1a;basice64 Digest 哈希值 哈希值不可逆。nonce 做的单项散列&#xff08;MD5,SHA512&#xff0…

HTML(二) -- 表格设计

目录 1. 基本格式&#xff1a; 表格常用属性&#xff1a; 2. 表格标签 为什么使用表格&#xff1f; 简单通用、结构稳定数据显示的非常的规整、可读性非常好 1. 基本格式&#xff1a; <table style"border: 1px solid black;" border"1px">&l…

AWE2023什么值得看?智哪儿带你五大关键词读懂AWE2023

4月27至30日&#xff0c;2023年中国家电及消费电子博览会&#xff08;AWE 2023&#xff09;在上海浦东新国际博览中心开展。 作为与德国IFA、美国CES并肩的全球前三国际家电及消费电子展览会&#xff0c;时隔两年AWE终于重启。沉淀两年&#xff0c;它的规模也是历年最大&#x…

QT+OpenCV配置

QTOpenCV配置 1 下载CMake2 安装CMake3 下载OPenCV4 配置环境变量4.1 配置QT环境变量4.2 配置CMake环境变量4.3 重启电脑生效 5 CMake编译OPenCV5.1 解决报错 6 测试 1 下载CMake 链接&#xff1a;https://cmake.org/download/ 2 安装CMake 3 下载OPenCV 链接&#xff1a;htt…

本地elasticsearch中文分词器 ik分词器安装及使用

ElasticSearch 内置了分词器&#xff0c;如标准分词器、简单分词器、空白词器等。但这些分词器对我们最常使用的中文并不友好&#xff0c;不能按我们的语言习惯进行分词。 ik分词器就是一个标准的中文分词器。它可以根据定义的字典对域进行分词&#xff0c;并且支持用户配置自…

网络设备中VRRP协议和Linux服务器中keepalived的两个区别

1、什么是VRRP&#xff1f;keepalived又是什么&#xff1f; VRRP全称是Virtual Router Redundancy Protocol&#xff0c;即虚拟路由冗余协议。它的主要目的是在一个网络中提供冗余的路由。当一个三层网络设备或服务器出现故障时&#xff0c;VRRP可以确保网络仍能正常工作。VRR…

在.NET Core中正确使用HttpClient的方式

HttpClient 是 .NET Framework、.NET Core 或 .NET 5以上版本中的一个类&#xff0c;用于向 Web API 发送 HTTP 请求并接收响应。它提供了一些简单易用的方法&#xff0c;如 GET、POST、PUT 和 DELETE&#xff0c;可以很容易地构造和发送 HTTP 请求&#xff0c;并处理响应数据。…