【特征检测】HOG特征算法

简介

        HOGHistogram of Oriented Gridients的简写)特征检测算法,最早是由法国研究员Dalal等在CVPR-2005上提出来的,一种解决人体目标检测的图像描述子,是一种用于表征图像局部梯度方向和梯度强度分布特性的描述符。其主要思想是:在边缘具体位置未知的情况下,边缘方向的分布也可以很好的表示行人目标的外形轮廓。

        Dalal等提出的HOG+SVM算法,在进行行人检测取得了极大地成功后,更多新算法不断涌现,不过大都是以HOG+SVM的思路为主线。

HOG特征算法

        HOG特征检测算法的几个步骤:颜色空间归一化—>梯度计算—>梯度方向直方图—>重叠块直方图归一化—>HOG特征。下面分别对其进行介绍。

1、颜色空间归一化

        由于图像的采集环境、装置等因素,采集到的人脸图像效果可能不是很好,容易出现误检或漏检的情况,所以需要对采集到的人脸进行图像预处理,主要是处理光线太暗或太强的情况,这里有两次处理:图像灰度化、Gamma校正。

①图像灰度化

       对于彩色图像,将RGB分量转化成灰度图像,其转化公式为:


②Gamma校正

       在图像照度不均匀的情况下,可以通过Gamma校正,将图像整体亮度提高或降低。在实际中可以采用两种不同的方式进行Gamma标准化,平方根、对数法。这里我们采用平方根的办法,公式如下(其中γ=0.5):


代码:

  1. int main()  
  2. {  
  3.     Mat picture = imread("test.jpg", 0);//灰度  
  4.     Mat img;  
  5.     picture.convertTo(img, CV_32F); //转换成浮点  
  6.     sqrt(img, img);                 //gamma校正  
  7.     normalize(img, img, 0, 255, NORM_MINMAX, CV_8UC1);//归一化像素值[0,255]  
  8.     imshow("原图", picture);  
  9.     imshow("Gamma校正", img);  
  10.     waitKey();  
  11.   
  12.     return 0;  
  13. }  

结果:


2、梯度计算

对经过颜色空间归一化后的图像,求取其梯度及梯度方向。分别在水平和垂直方向进行计算,梯度算子为:


代码:

  1. /***************************************** 
  2. Copyright (c) 2015 Jingshuang Hu 
  3.  
  4. @filename:demo.cpp 
  5. @datetime:2015.08.06 
  6. @author:HJS 
  7. @e-mail:eleftheria@163.com 
  8. @blog:http://blog.csdn.net/hujingshuang 
  9. *****************************************/  
  10.   
  11. #include <iostream>  
  12. #include <cv.h>  
  13. #include <opencv2/core/core.hpp>  
  14. #include <opencv2/highgui/highgui.hpp>  
  15. #include <opencv2/imgproc/imgproc.hpp>  
  16.   
  17. using namespace cv;  
  18. using namespace std;  
  19.   
  20. int main()  
  21. {  
  22.     Mat picture = imread("test.jpg", 0);//灰度  
  23.     Mat img;  
  24.   
  25.     picture.convertTo(img, CV_32F); //转换成浮点  
  26.     sqrt(img, img);                 //gamma校正  
  27.     normalize(img, img, 0, 255, NORM_MINMAX, CV_32F);//归一化[0,255]浮点数  
  28.   
  29.     Mat gradient = Mat::zeros(img.rows, img.cols, CV_32F);//梯度  
  30.     Mat theta = Mat::zeros(img.rows, img.cols, CV_32F);//角度  
  31.   
  32.     for (int i = 1; i < img.rows - 1; i++)  
  33.     {  
  34.         for (int j = 1; j < img.cols - 1; j++)  
  35.         {  
  36.             float Gx, Gy;  
  37.   
  38.             Gx = img.at<float>(i, j + 1) - img.at<float>(i, j - 1);  
  39.             Gy = img.at<float>(i + 1, j) - img.at<float>(i - 1, j);  
  40.   
  41.             gradient.at<float>(i, j) = sqrt(Gx * Gx + Gy * Gy);//梯度模值  
  42.             theta.at<float>(i, j) = float(atan2(Gy, Gx) * 180 / CV_PI);//梯度方向[-180°,180°]  
  43.         }  
  44.     }  
  45.   
  46.     normalize(gradient, gradient, 0, 255, NORM_MINMAX, CV_8UC1);//归一化[0,255] 无符号整型  
  47.     normalize(img, img, 0, 255, NORM_MINMAX, CV_8UC1);  
  48.   
  49.     imshow("原图", picture);  
  50.     imshow("Gamma校正", img);  
  51.     imshow("梯度图", gradient);  
  52.     waitKey();  
  53.   
  54.     return 0;  
  55. }  

结果:

3、梯度方向直方图

        将图像划分成若干个cells(单元),8x8=64个像素为一个cell相邻的cell之间不重叠。在每个cell内统计梯度方向直方图,将所有梯度方向划分为9bin(即9维特征向量),作为直方图的横轴,角度范围所对应的梯度值累加值作为直方图纵轴,每个bin的角度范围如下。


4、重叠块直方图归一化

        以下有关计算,请认真分析假设有一幅图像大小为220x310,将其划分成若干个8x8cells,显然220÷8=27.5、310÷8=38.75不是整数,也就是说划分之后依然还有多余像素不能构成cell。处理办法是将图像缩放成能被8整除的长宽(如216x304),再划分。216÷8=27304÷8=38,因此,216x304的图像可以得到27x38cells,没有重叠。

  1. Mat picture = imread("test.jpg", 0);//灰度  
  2. resize(picture, picture, cvSize(int(picture.cols / 8) * 8, int(picture.rows / 8) * 8));//转化成能被8除尽的行、列  
        由于图像中光照情况和背景的变化多样,梯度值的变化范围会比较大,因而良好的特征标准化对于检测率的提高相当重要。标准化的方法多种多样,大多数的都是将celll放在block中,然后标准化每个block

        以上述缩放后的图像为例,共得到27x38cell,也就是将图像划分成了27x38个单元;将上下左右相邻的2x2cells当做一个block整体,如下所示(为方便观察,每个颜色框故意错开了一点),黑色8x8像素为一个cell粉红绿框都是一个block,即每个框内2x2cell组成一个block。故27x38cell可划分成26x37block,每个block16x16像素。相邻block之间是有重叠的,这样有效的利用了相邻像素信息,对检测结果有很大的帮助。


接下分别对每个block进行标准化,一个block内有4cell,每个cell9维特征向量,故每个block就由4x9=36维特征向量来表征。


由于L2-norm简单且在检测中效果相对较好,故一般采用它。

        经过上述对有重叠部分block的直方图归一化之后,将所有block的特征向量都组合起来,则形成26x37x36=34632维特征向量,这就是HOG特征,这个特征向量就可以用来表征整个图像了。

        实际上,在运用的时候,我们通常是选取一幅图像中的一个窗口来进行特征提取,依然以上述220X310大小图像为例,经过缩放处理后为216x304,但并不直接提取整个图像的HOG特征,而是用一个固定大小的窗口在图像上滑动,滑动的间隔为8个像素,OpenCV中默认的窗口大小为128x64(高128,宽64),即有(128÷8)x(64÷8)=16x8cell,也即有15x7block,这样一来一幅图像就可以取到(27-16)x(38-8)=11x30=330个窗口。现在提取每个窗口的HOG特征,则可得到105x36=3780HOG特征向量。

        将这3303780维的HOG特征当做测试样本,用支持向量机(SVM)分类器来判别出,这些窗口的HOG特征是否有行人,有行人的用矩形框标记起来。HOG行人特征及所对应的SVM分类器的参数,在opencv中已经训练好了,我们只需要得到HOG特征,然后调用SVM即可得到判别结果。

以上是个人对HOG算法的理解,若理解不到位或者有误的,请多多指教!

代码:

  1. /***************************************** 
  2. Copyright (c) 2015 Jingshuang Hu 
  3.  
  4. @filename:demo.cpp 
  5. @datetime:2015.08.06 
  6. @author:HJS 
  7. @e-mail:eleftheria@163.com 
  8. @blog:http://blog.csdn.net/hujingshuang 
  9. *****************************************/  
  10.   
  11. #include <iostream>  
  12. #include <opencv2/opencv.hpp>  
  13.   
  14. using namespace cv;  
  15. using namespace std;  
  16.   
  17. int main()  
  18. {  
  19.     Mat image = imread("test.jpg");  
  20.     // 1. 定义HOG对象  
  21.     HOGDescriptor hog(Size(64,128),Size(16,16),Size(8,8),Size(8,8),9);//HOG检测器,用来计算HOG描述子的  
  22.     // 2. 设置SVM分类器  
  23.     hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());   // 采用已经训练好的行人检测分类器  
  24.     // 3. 在测试图像上检测行人区域  
  25.     vector<cv::Rect> regions;  
  26.     hog.detectMultiScale(image, regions, 0, Size(8,8), Size(32,32), 1.05, 1);  
  27.     // 显示  
  28.     for (size_t i = 0; i < regions.size(); i++)  
  29.     {  
  30.         rectangle(image, regions[i], Scalar(0,0,255), 2);  
  31.     }  
  32.     imshow("HOG行人检测", image);  
  33.     waitKey();  
  34.   
  35.     return 0;  
  36. }  

结果:



从图中可以看出,依然是有漏检的情况。

源码分析:

1、opencv源码解析之(6):hog源码分析

2、目标检测学习_1(用opencv自带hog实现行人检测)

3、HOG:从理论到OpenCV实践

4、opencv之HOG源代码注释

5、opencv之HOG源代码分析

参考资料:

1、维基百科:Histogram of oriented gradients

2、原论文:Histograms of Oriented Gradients for Human Detection

3、基于多特征的粒子滤波行人跟踪算法研究[M],张广西,2013.

4、基于HOG特征的人脸识别系统研究[M],穆春雷,2013.

5、基于HOG特征的目标识别算法研究[M],尚俊,2012.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值