Haar特征和级联分类器目标检测介绍及应用

news2024/11/26 18:34:46

文章目录

  • Haar特征和级联分类器目标检测介绍及应用
    • 1. Haar特征
    • 2. 级联分类器
    • 3. 实现步骤
    • 4.尝试训练自己的级联分类器
    • 4. 应用示例

Haar特征和级联分类器目标检测介绍及应用

Haar特征和级联分类器是一种经典的目标检测算法,适用于检测物体在图像中的位置、大小和姿态等。本教程将详细介绍Haar特征和级联分类器的原理、实现和应用。

1. Haar特征

Haar特征是一种图像处理中的特征提取方法,用于描述图像中的纹理、边缘和线条等特征。基于Haar小波变换的思想,Haar特征将图像划分成不同大小、不同形状的小矩形区域,对每个区域内的像素进行加权求和得到一个特定的Haar特征值。这些Haar特征值可以作为分类器的输入,例如在人脸识别中就可以用Haar特征检测人脸的位置、大小和方向等信息。

Haar特征经常用在人脸识别中,它可以通过训练一个分类器来检测人脸的各种属性。Haar特征的计算速度相对较快,并且在处理大量数据时表现稳定,使其成为计算机视觉领域中比较受欢迎的特征提取方法之一。

2. 级联分类器

级联分类器(Cascade Classifier)是一种基于Haar特征的对象检测算法,最早由Paul Viola和Michael Jones在2001年的论文中提出。级联分类器主要用于人脸检测,但也可以用于识别其它物体。级联分类器具有高检测精度和快速检测速度的特点。

级联分类器的实现依赖于AdaBoost算法。AdaBoost是一种集成学习方法,可以将多个弱分类器组合成一个强分类器。级联分类器由多个弱分类器组成,每个弱分类器加强一次过滤效果。

级联分类器的检测过程分为多个步骤。首先是图像预处理,将图像转换为灰度图像,然后进行归一化和直方图均衡化。接着,级联分类器将在图像的不同位置和不同大小的窗口中,对每个窗口进行Haar特征的计算。Haar特征是一种计算图像中黑白相间矩形框的差值的方法。计算得到的Haar特征值会被送入AdaBoost分类器进行分类,如果分类器的输出值大于预设的阈值,则认为当前窗口中有目标物体。如果级联分类器中的所有弱分类器都通过了当前窗口的验证,则认为整个级联分类器检测到了目标物体。

级联分类器的训练过程需要大量的正负样本。正样本是指需要检测的目标物体的图片,而负样本是指与目标物体相似但不包含目标物体的图片。在训练过程中,级联分类器会通过不断增加弱分类器的数量和调整阈值,提高检测精度。

基于级联分类器的人脸检测系统由若干级联分类器组成,每个级联分类器的弱分类器数量和阈值都不同。在每个级联分类器中,通过精细调整弱分类器的数量和阈值,使得分类器的检测精度能够达到较高的水平。整个检测系统的优点是快速高效,适合实时应用。

3. 实现步骤

以下是使用OpenCV实现Haar特征和级联分类器目标检测的基本步骤:

  1. 收集和准备训练数据。需要使用大量的正样本和负样本,其中正样本是包含目标的图像区域,负样本是不包含目标的图像区域。还需要把训练数据集划分为训练集和测试集,并将其分别转换为XML格式。
  2. 训练级联分类器。可以使用OpenCV提供的trainCascadeClassifier函数进行训练,需要设置许多参数,如Haar特征的类型和数量、正负样本比例、学习率等。训练过程需要一定时间,根据数据集的大小不同可能需要数个小时到数天不等。
  3. 使用级联分类器进行目标检测。加载训练好的级联分类器XML文件,使用OpenCV提供的detectMultiScale函数对图像进行检测,会返回检测到的目标位置和大小。

4.尝试训练自己的级联分类器

以下是一个基于OpenCV4的级联分类器训练的Python代码示例,你可以参考这个例子来训练你自己的级联分类器。在这个例子中,我们将训练一个可以检测人脸的级联分类器。

首先需要将正负样本从数据集文件夹中读入,我们将正样本命名为"Positive",负样本命名为"Negative",在训练级联分类器时,需要准备一些负样本。正样本是需要构建检测器检测位置的目标。

import cv2
import os
 
# 设置正负样本文件夹路径
pos_dir = 'Positive/'
neg_dir = 'Negative/'
 
# 用于存储正样本文件名和路径的列表
pos_files = []
for filename in os.listdir(pos_dir):
    if filename.endswith('.jpg'):
        pos_files.append(pos_dir + filename)
 
# 用于存储负样本文件名和路径的列表
neg_files = []
for filename in os.listdir(neg_dir):
    if filename.endswith('.jpg'):
        neg_files.append(neg_dir + filename)
 
# 加载正样本的图片
pos_images = []
for file in pos_files:
    img = cv2.imread(file, 0) # 将图片转换为灰度图像
    pos_images.append(img)
 
# 加载负样本的图片
neg_images = []
for file in neg_files:
    img = cv2.imread(file, 0)
    neg_images.append(img)

接下来,我们可以定义训练级联分类器所需的参数。这些参数包括Haar特征的类型和数量、正负样本比例、学习率等。这些参数的设置不仅受到数据集的影响,也需要多次尝试和优化。

# 设置训练参数
num_pos = len(pos_images)   # 正样本数量
num_neg = len(neg_images)   # 负样本数量
num_features = 200          # 特征数量
pos_weight = float(num_neg) / float(num_pos)   # 正负样本比例
num_stages = 20             # 分类器级联层数
min_hit_rate = 0.995        # 分类器的最小检测率
max_false_alarm_rate = 0.5  # 最大假阳率
learning_rate = 0.05        # 学习率

接下来,我们可以使用trainCascadeClassifier函数来训练级联分类器。在训练过程中,模型会不断地调整Haar特征,设定阈值,去除不必要的特征,最终形成具有适应性与推广性的级联分类器。在训练级联分类器时,需要耐心等待,可能需要数小时或更长时间才能训练出一个合适的分类器。

# 训练级联分类器
cascade = cv2.CascadeClassifier()
cascade_params = cv2.CascadeClassifier_TrainParams()
cascade_params.featureParams.maxCatCount = 2
cascade_params.featureParams.maxNumFeatures = num_features
cascade_params.featureParams.minNodeSize = (1,1)
cascade_params.featureParams.maxDepth = 1
cascade_params.boostType = cv2.CASCADE_BOOST_REAL
cascade_params.weightTrimRate = 0.95
cascade_params.minHitRate = min_hit_rate
cascade_params.maxFalseAlarmRate = max_false_alarm_rate  
cascade_params.stageType = cv2.CASCADE_STAGE_TYPE_HAAR
cascade_params.classifierType = cv2.CASCADE_CLASSIFIER_TYPE_REAL_HAAR
cascade_params.stages = num_stages
cascade_params.weakCount = 100
cascade_params.completeTrainingSet = False
cascade.train(pos_images, neg_images, None, None, cascade_params)
 
# 保存级联分类器
cascade.save('face_cascade.xml')

在训练完成后,级联分类器将被保存在当前目录下的face_cascade.xml文件中,可以随时调用它进行人脸检测。

4. 应用示例

Haar特征和级联分类器目标检测算法可以应用于很多领域,如人脸检测、车牌识别、行人检测等。其中,最为著名的应用之一就是OpenCV中的人脸检测,该算法可以实现实时、准确的人脸检测,适用于视频监控、自拍美容等应用场景。以下是使用OpenCV实现人脸检测的代码示例:

# 导入OpenCV库和urllib库
import cv2
import urllib.request

# 设置图像 URL 和文件名
url = 'http://www.lenna.org/lena_std.tif'
filename = 'lena.png'

# 通过网络下载图像,并将其保存到本地
urllib.request.urlretrieve(url, filename)

# 读取图片并转为灰度图
img = cv2.imread('lena.jpg') # 读取图片文件,返回numpy数组
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 将彩色图片转换为灰度图片

# 从GitHub中下载预训练的人脸分类器XML文件
url = 'https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_default.xml'
filename = 'haarcascade_frontalface_default.xml' # 声明下载的文件名
urllib.request.urlretrieve(url, filename) # 将文件从url下载并保存到本地

# 加载预训练的Haar特征分类器,用于人脸检测
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

# 在灰度图片中检测人脸
# 参数1:待检测图片,参数2:缩放比例因子,参数3:目标大小范围
faces = face_cascade.detectMultiScale(gray, 1.3, 5)

# 在人脸矩形区域绘制矩形
# 参数1:需要绘制矩形的图片,参数2:矩形左上角的坐标,参数3:矩形右下角的坐标,参数4:矩形线条颜色,参数5:矩形线条粗细
for (x, y, w, h) in faces:
    cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)

# 显示图片
# 参数1:需要显示的图片窗口名称,参数2:需要显示的图片
cv2.imshow('image', img)
cv2.waitKey(0) # 等待用户按下任意键以关闭窗口

检测结果如下所示:
请添加图片描述

这段代码的主要作用是使用OpenCV库实现人脸检测,步骤如下:

  1. 读取图片文件,使用cv2.imread()函数读取指定路径下的图片,返回一个numpy数组表示该图片;
  2. 将彩色图片转换为灰度图片,使用cv2.cvtColor()函数将读取出来的彩色图片转换为灰度图;
  3. 下载预训练的人脸分类器XML文件,使用urllib.request.urlretrieve()函数从GitHub上下载XML文件,保存到本地;
  4. 加载预训练的Haar特征分类器,使用cv2.CascadeClassifier()函数加载XML文件,得到一个分类器对象;
  5. 在灰度图片中检测人脸,使用CascadeClassifier.detectMultiScale()方法对灰度图片进行人脸检测,返回检测到的人脸位置;
  6. 在检测到的人脸上绘制矩形,使用cv2.rectangle()函数在原图片上绘制矩形框,标出人脸位置;
  7. 显示人脸检测结果图片,使用cv2.imshow()函数将图片显示在窗口中,最后使用cv2.waitKey()函数等待用户按下任意键,关闭窗口。

为了使用Python展示Haar检测中的积分操作,我们可以使用OpenCV库中的cv2.integral函数来计算输入图像的积分图。以下是一个示例代码,演示如何生成积分图并将其可视化显示:

# 导入必要的库
import cv2
import numpy as np
from matplotlib import pyplot as plt
import urllib.request

# 设置图像 URL 和文件名
url = 'http://www.lenna.org/lena_std.tif'
filename = 'lena.png'

# 通过网络下载图像,并将其保存到本地
urllib.request.urlretrieve(url, filename)

# 读取图像并转换为灰度图像
img = cv2.imread('lena.png')    # 加载图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)    # 转换为灰度图像

# 计算积分图
integral_img = cv2.integral(gray)    # 计算积分图

# 显示原始图像和对应的积分图
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(8, 4))    # 创建子图
ax1.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))    # 显示原始图像
ax1.set_title('Original Image')    # 设置图像标题
ax2.imshow(integral_img, cmap='gray')    # 显示积分图
ax2.set_title('Integral Image')    # 设置积分图标题
plt.show()    # 输出图像

代码运行结果如下所示:
请添加图片描述

代码通过网络下载一个名为 lena.png 的图像文件,并计算了它的积分图。积分图是一种预处理方法,用于在图像中快速计算子矩形区域的和。

首先,通过导入必要的库:cv2numpy、和 matplotlib 来让这份代码能够正常运行。并且通过 urllib 模块,通过给定的图像 URL 下载图像并存储在名为 lena.png 的本地文件中。

然后,使用 cv2.imread 函数读入图像,并使用 cv2.cvtColor 函数将其转换为灰度图像,为计算积分图做准备。

接下来,使用 cv2.integral 函数计算灰度图像的积分图,并存储在 integral_img 变量中。

最后,使用 Matplotlib 中的 subplots 函数创建一个包含两个子图的窗口,其中左侧显示原始图像,右侧显示计算得到的积分图像。在显示积分图时,使用 cmap='gray' 参数将其显示为灰度图像。设置标题后,最后显示窗口中的两个图像。

在这个示例中,我们首先读取了一张图像,并将其转换为灰度图像。接着,我们使用cv2.integral函数计算输入图像的积分图。积分图的大小与原始图像相同,并且每个像素都表示原始图像中该位置及其左上角的所有像素值的总和。最后,我们使用Matplotlib库将原始图像和积分图在一起可视化显示出来。可以看到,积分图中每个位置的值都代表了原始图像中对应位置及其左上角区域的像素值的总和。

值得注意的是,在Haar特征计算中,积分图有助于快速计算位于任意矩形区域内的像素值之和,从而避免了对该区域内的每个像素进行逐一计算。这可以使Haar特征的计算速度更快。

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

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

相关文章

卷积神经网络算法解读

神经网络算法解读 机器学习流程: 数据获取特征工程建立模型评估与应用 图像数据是一个矩阵300 * 100 * 3 线性函数分类方法:分类(wxb线性回归) 损失函数:预测值与实际值之间的差异值 softmax分类器: 神…

(Python)Jupyter Notebook无法运行代码,且提示error和自动保存失败时如何操作?无法链接内核?

目录 一、报错情形 1、运行代码时跳转下一行,无法执行代码。 2、在修改文件名是提示失败,出现“error”字样。 二、深层原因 三、解决方案 四.建议使用原环境 Anaconda的Jupyter Notebook作为优秀的网页编辑器,非常适用于编写Python程序…

ubuntu16.04升级到20.04后报错 By not providing “FindEigen.cmake“

编译问题: CMake Error at modules/perception/lidar/CMakeLists.txt:14 (find_package): By not providing "FindEigen.cmake" in CMAKE_MODULE_PATH this project has asked CMake to find a package configuration file provided by "Eigen&…

黑马Redis入门到实战(基础篇)

Redis基础篇 Redis的类型和常见命令以及客户端使用 目录 1 .初识Redis 1 .1 .认识NoSQL 1 .1 .1 .结构化与非结构化 1 .1 .2 .关联和非关联 1 .1 .3 .查询方式 1 .1 .4 .事务 1 .1 .5 .总结 1 .2 .认识Redis 1 .3 .安装Redis 1 .3 .1 .依赖库 1 .3 .2 .上传安装包并解压 1 .3 .…

音视频八股文(8)-- h264 AnnexB三层结构

NALU(Network Abstract Layer Unit) ⾳视频编码在流媒体和⽹络领域占有重要地位;流媒体编解码流程⼤致如下图所示: H264简介 H.264从1999年开始,到2003年形成草案,最后在2007年定稿有待核实。在ITU的标准⾥称为H.264&#xff0c…

使用QtInstallerFramework制作安装包总结

一、linux下使用QtInstallerFramework制作安装包 4.0.1版本的QtInstallerFramework-linux-x64.run在linux中运行报错: libdbus-1.so.3 no version information availabe 换成3.0.4版本的就好了:https://download.qt.io/official_releases/qt-installer-…

GEE:MODIS计算遥感指数(NDVI、BSI、NDSI、EVI、LSWI、SIPI、EBI等)

作者:_养乐多_ 本文将介绍如何使用Google Earth Engine(GEE)进行遥感影像分析,具体地,使用MODIS数据集计算和可视化几种植被指数,以评估植被生长的状况,或者作为随机森林分类器训练需要的特征变量。 主要包括,NDVI、BSI、NDSI、EVI、LSWI、SIPI、EBI等。 NDVI(Normal…

【PCIE体系结构六】TLP路由

👉个人主页:highman110 👉作者简介:一名硬件工程师,持续学习,不断记录,保持思考,输出干货内容 参考书籍:PCI_Express体系结构导读 目录 TLP路由 地址路由 ID路由 隐式路…

介绍一款idea神级插件【Bito-ChatGPT】而且免费!

什么是Bito? Bito是一款在IntelliJ IDEA编辑器中的插件,Bito插件是由ChatGPT团队开发的,它是ChatGPT团队为了提高开发效率而开发的一款工具。ChatGPT团队是一支专注于自然语言处理技术的团队,他们开发了一款基于GPT的自然语言处理…

云原生CAx软件: HTTP基础知识汇总

随着云原生(Cloud Native)的兴起,面向服务架构(Service-Oriented Architecture,SOA)、微服务(Microservice)、容器(Container)等相关概念与技术正在逐渐影响CAx(CAD/CAE/CAM)软件的架构设计与开发。 在云原生CAx软件中,首先需要把系统按照功…

vue3表单输入绑定

初识表单输入绑定 vue3可以帮助我们将vue定义的变量绑定到html表单元素上&#xff0c;并且监听到html表单元素修改值时&#xff0c;会将对应的vue定义的变量修改。 <!-- 将vue3定义的text绑定给inut元素, 当input元素发生input输入事件时, 将修改vue3定义的text --> <…

Linux常用操作命令

目录 一. Linux命令格式 二. 文件目录操作命令 文件目录操作命令 ls 文件目录操作命令 cd 文件目录操作命令 cat 文件目录操作命令 more 文件目录操作命令 tail 文件目录操作命令 mkdir 文件目录操作命令 rmdir 文件目录操作命令 rm 三. 拷贝移动命令 拷贝移动命令 …

STM32 学习笔记_6 定时器中断(上)

TIM 定时器是功能最强大&#xff0c;内容最复杂的32结构。 之前51用过的功能&#xff0c;定时产生中断。输出比较&#xff0c;常用于产生 PWM 波形&#xff0c;驱动电机等。输入捕获&#xff0c;测量方波频率。编码器&#xff0c;读取正交编码器的波形。 最大定时时间&#…

关于repeater录制的流量子调用的identity中带有~S的情况

前段时间同事问我&#xff0c;我们录制的流量中&#xff0c;尤其是dubbo的子调用显示经常他的末尾会带上一个小尾巴这个是什么意思呢&#xff0c;其实之前我没有太在意这个事情&#xff0c;只是同事这么疑问了&#xff0c;确实激起了好奇心&#xff0c;所以就差了下 到底是什么…

HTML(四) -- 多媒体设计

目录 1. 视频标签 2. 音频标签 3. 资源标签&#xff08;定义媒介资源 &#xff09; 1. 视频标签 属性值描述autoplayautoplay如果出现该属性&#xff0c;则视频在就绪后马上播放。controlscontrols表示添加标准的视频控制界面&#xff0c;包括播放、暂停、快进、音量等…

交叉熵损失函数与参数更新计算实例(节点分类为例)

交叉熵损失与参数更新 数据准备 对于下面这样一个图网络网络&#xff1a; 假如我们得到了节点i的嵌入表示 z i z_i zi​数据如下&#xff1a; i d , x 0 , x 1 , x 2 , x 3 1 , 0.5 , 0.6 , 0.7 , 0.8 2 , 0.3 , 0.8 , 0.3 , 0.4 3 , 0.7 , 0.9 , 0.6 , 0.9 4 , 0.2 , 0.1…

【计算几何】判断一条线段和一段圆弧是否相交 C++代码实现

文章目录 一、前言二、线段与圆弧的代码表示2.1 线段代码表示2.2 圆弧代码表示 三、实现思路及数学推导3.1 第一步&#xff08;粗略判断&#xff09;3.2 第二步3.3 第三步 四、完整代码五、效果展示 一、前言 最近做项目&#xff0c;需要判断一条线段是否和一段圆弧相交&#…

利用Ad Hoc传感器网络上的局部信息组织全球坐标系(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 知道通信网络中节点的地理位置通常是有用的&#xff0c;但在每个节点上添加GPS接收器或其他复杂的传感器可能会很昂贵。 本文…

系统集成项目管理工程师 笔记(第14章 项目采购管理)

文章目录 采购管理包括如下几个过程14.2 编制采购计划 4621&#xff09;采购管理计划2&#xff09;采购工作说明书3&#xff09;采购文件14.2.3 工作说明书&#xff08;SOW&#xff09; 14.3 实施采购 47414.3.2 实施采购的方法和技术 476&#xff08;1&#xff09;投标人会议&…

深入篇【C++】类与对象:构造函数+析构函数

深入篇【C】类与对象&#xff1a;构造函数析构函数 ①.构造函数Ⅰ.概念Ⅱ.特性1.函数名和类型相同。2.无返回值&#xff0c;也不用写void。3.自动调用对应的构造函数。4.构造函数可重载5.编译器的无参构造6.编译器的无参构造特性7.声明时可缺省8.构造函数的调用9.默认构造函数 …