OpenCV4学习笔记(42)——基于HOG特征检测与SVM线性分类器的行人检测模型

今天要整理记录的内容是关于HOG特征检测和SVM线性分类器在OpenCV中的联合使用,并实现OpenCV自带的一个演示案例——行人检测。

  • 图像的HOG特征

那么先来了解一下什么是图像的HOG特征,HOG(Histogram of Oriented Gradient——面向梯度直方图)特征的大致计算方式如下:

1、对图像使用默认Size(64,128) 的窗口win进行开窗,在该窗口中选择默认的Size(16,16)的块区域block。

2、在块区域block中划分出默认的Size(8,8)大小的四个区域cell。

3、对每个区域cell都去构建一个将0°~360°分为9个区间bin的面向梯度直方图,该直方图中每个区间范围为40°,区间值为属于该区间的像素数量。
再对区域cell中的每个像素点计算梯度,并按照梯度方向(化为角度)将每个像素点放入该像素点所属区域cell的面向梯度直方图中的相应区间bin内。

4、统计每个区域cell的面向梯度直方图的九个区间值并作归一化处理,将处理后的九个区间值组合起来就得到了该区域cell的HOG特征。
接着遍历每个区域cell来得到每个区域cell的HOG特征,然后再组合起来得到这四个cell所属的块区域block的HOG特征。

5、遍历每个块区域block来得到每个块区域block的HOG特征,然后再组合起来就得到每个窗口win的HOG特征。

6、通过窗口win来对整幅图像进行开窗,遍历图像从而得到完整图像的HOG特征。

图像的HOG特征具有比较好的几何不变性和光照不变性,所以只要行人基本保持直立的姿态,就能忽视其肢体上的一些微小运动,从而实现对行人特征的检测。

  • SVM线性分类器

SVM线性分类器是属于机器学习中的内容,这里引用百度百科上的一个介绍:

支持向量机(Support Vector Machine, SVM)是一类按监督学习(supervised learning)方式对数据进行二元分类的广义线性分类器(generalized linear classifier),其决策边界是对学习样本求解的最大边距超平面(maximum-margin hyperplane) [1-3] 。
SVM使用铰链损失函数(hinge loss)计算经验风险(empirical risk)并在求解系统中加入了正则化项以优化结构风险(structural risk),是一个具有稀疏性和稳健性的分类器 [2] 。SVM可以通过核方法(kernel method)进行非线性分类,是常见的核学习(kernel learning)方法之一 [4] 。
SVM被提出于1964年,在二十世纪90年代后得到快速发展并衍生出一系列改进和扩展算法,在人像识别、文本分类等模式识别(pattern recognition)问题中有得到应用 [5-6] 。

说白了,SVM(Support Vector Machine)支持向量机是一种寻求最大分类间隔的机器学习方法,SVM就是寻找一个分离数据正确且抗噪声强的稳健超平面(分类面),也即在不同类数据之间定位一个能够分离出不同类别数据的平面。

本人才疏学浅,这里就不对机器学习的内容进行深入研究了,下面来看看在OpenCV中怎么把HOG特征和SVM线性分类器相结合并实现行人检测。

其实,HOG+SVM进行行人检测已经是相当成熟的算法了,而在OpenCV中更是已经集成了这种检测算法。
所以我们只需要创建HOG特征检测器就可以加载OpenCV自带的行人检测模型了,再对图像进行多尺度的HOG特征检测,就能够实现一个简单的行人检测了。

其中,对图像进行多尺度的HOG特征检测的API是detectMultiScale(),其参数含义如下:
(1)参数Img:表示输入图像;
(2)参数foundLocations:表示包含检测对象的矩形框;
(3)参数hitThreshold:表示SVM距离度量,默认用0表示,表示特征与SVM分类超平面之间距离的阈值;
(4)参数winStride:表示进行开窗时的窗口步长;
(5)参数padding:表示块区域block的大小;
(6)参数scale:表示尺度空间的缩放系数;
(7)参数finalThreshold:最终阈值,默认为2.0;
(8)参数useMeanshiftGrouping:表示是否使用分组算法;默认为false,不建议使用,速度太慢。

对于detectMultiScale()这个API来说,其参数窗口步长winStride与缩放系数Scale对检测结果影响最大。特别是缩放系数Scale,小的尺度变化有利于检出低分辨率对象,同时也会导致目标误检的情况发生,而大的尺度变化可以避免误检但是可能会导致对象漏检的情况发生。

下面看一下代码演示:

	//利用OpenCV自带的 HOG+SVM 行人检测模型,实现行人检测
	Mat tem = imread("D:\\opencv_c++\\opencv_tutorial\\data\\images\\pedestrian.png");
	HOGDescriptor *hog = new HOGDescriptor;			//创建HOG检测器
	hog->setSVMDetector(hog->getDefaultPeopleDetector());			//设置SVM线性分类器,使用自带行人检测模型
	vector<Rect>objects;				//包含检测目标的矩形框
	hog->detectMultiScale(tem, objects, 0.0, Size(4, 4), Size(8, 8), 1.25, 2.0, false);		//进行多尺度的HOG特征检测
	//参数Img:表示输入图像
	//参数foundLocations:表示包含检测对象的矩形框
	//参数hitThreshold:表示SVM距离度量,默认用0表示,表示特征与SVM分类超平面之间的距离
	//	参数winStride:表示窗口步长
	//参数padding:表示填充
	//	参数scale:表示尺度空间的缩放系数
	//	参数finalThreshold:最终阈值,默认为2.0
	//	参数useMeanshiftGrouping:是否使用分组算法;默认为false,不建议使用,速度太慢。
	//窗口步长winStride与缩放系数Scale对结果影响最大,特别是Scale;
	//小的尺度变化有利于检出低分辨率对象,同时也会导致目标误检情况发生,大的尺度变化可以避免误检但是可能会导致对象漏检。
	for (int i = 0; i < objects.size(); i++)
	{
		rectangle(tem, objects[i], Scalar(0, 255, 0), 1, 8, 0);
	}
	imshow("tem", tem);

通过上述代码,就可以实现简单的行人检测了,下面是效果图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

从上述图像可以看出,使用OpenCV自带的HOG+SVM行人检测模型能够将图像中的行人检测出来并用矩形框标记,而且在简单的图像中还能有比较好的效果。但是,一旦图像中的场景变得复杂了,这种OpenCV自带的行人检测模型就显得效果比较差了,出现了不少误检和漏检的问题,虽然可能通过参数调节能够改善检测效果,但不可否认的是这种行人检测算法的鲁棒性是比较差的。

但它给我们提供了进行目标检测的思路,那就是如果我们想要进行自定义目标的检测,就可以自己制作数据集,然后训练我们自己的SVM分类器,从而实现特定目标的检测。下一次笔记就来实现通过训练SVM分类器来进行自定义目标检测,那今天的笔记就到此结束啦。

PS:本人的注释比较杂,既有自己的心得体会也有网上查阅资料时摘抄下的知识内容,所以如有雷同,纯属我向前辈学习的致敬,如果有前辈觉得我的笔记内容侵犯了您的知识产权,请和我联系,我会将涉及到的博文内容删除,谢谢!

发布了49 篇原创文章 · 获赞 71 · 访问量 5139

猜你喜欢

转载自blog.csdn.net/weixin_45224869/article/details/105516506