图像处理基础-hog算法

参考博文:http://blog.csdn.net/hujingshuang/article/details/47337707/

                 http://blog.csdn.net/liulina603/article/details/8291093


1.简介

HOG( histogram of oriented gradient ,方向梯度直方图 )算法是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子(卷积核)。HOG是一种解决人体目标检测的图像描述子, 是一种用于表征图像局部梯度方向和梯度强度分布特性的描述符。 Hog特征结合SVM分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功。

其主要思想是:在边缘具体位置未知的情况下,局部目标的表象和形状(appearance and shape)
能够被梯度或边缘的方向密度分布很好地描述。(本质:梯度的统计信息,而梯度主要存在于边缘的地方)

2.具体实现方法

 首先将图像分成小的连通区域,我们把它叫细胞单元。 然后采集细胞单元中各像素点的梯度或边缘的方向直方图。最后把这些直方图组合起来就可以构成特征描述器。

3.HOG特征算法


HOG特征算法的几个步骤: 1.颜色空间归一化
                                          2.梯度计算(梯度方向,梯度膜)
                                          3.梯度方向直方图
                                          4.重叠块直方图归一化
                                          5.HOG特征。

1.颜色额空间归一化

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

①图像灰度化:对于彩色图像,将RGB分量转化成灰度图像,公式如下(在matlab中有专门的处理函数)
                    
②Gamma矫正:在图像照度不均的情况下,可以通过Gamma矫正,将图像整体亮度提高或降低。在实际中采用两种不同的方式进行Gamma标准化,平方根、对数法。平方根方法公式如下( γ=0.5
                                  
http://blog.csdn.net/lichengyu/article/details/20840135
// 一段简单的测试代码
#include <opencv2\opencv.hpp>
using namespace cv;
int main() 
{
Mat picture = imread("D:\\HOG算法测试\\原图.jpg");//灰度
Mat img = imread("D:\\HOG算法测试\\原图.jpg",0);//灰度
Mat img1 = img;
img1.convertTo(img1, CV_32F);//转换成浮点
sqrt(img1, img1);   //gamma矫正
normalize(img1, img1, 0, 255, NORM_MINMAX, CV_8UC1); //归一化像素值
imshow("原图", picture);
imshow("灰度", img);
imshow("矫正", img1);
waitKey();
return 0;
}


其中函数normalize()进行像素归一化,使像素的灰度值分布在0~255之间,避免图像对比度不足(图像像素分布不平衡),若不进行归一化,原图由于对比度的问题进 γ=0.5的矫正时会使整张图片的对比度很低,必须使用归一化提高对比度.


2.梯度计算

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



G(X,Y):梯度模值
θ(X,Y):梯度方向


// 一段简单的测试代码
#include <opencv2\opencv.hpp>
using namespace cv;
int main() 
{
Mat picture = imread("D:\\HOG算法测试\\原图.jpg");//灰度
Mat img = imread("D:\\HOG算法测试\\原图.jpg",0);//灰度
Mat img1 = img;
Mat img2;
img1.convertTo(img1, CV_32F);//转换成浮点
sqrt(img1, img1);   //gamma矫正
img2=img1;
normalize(img2, img2, 0, 255, NORM_MINMAX, CV_32F); //归一化像素值
imshow("原图", picture);
imshow("灰度", img);
imshow("矫正以后未归一化", img1);


imwrite("D:\\HOG算法测试\\灰度.jpg", img);
imwrite("D:\\HOG算法测试\\矫正以后未归一化.jpg", img1);
imwrite("D:\\HOG算法测试\\矫正以后归一化.jpg", img2);
Mat gradient = Mat::zeros(img2.rows, img2.cols, CV_32F);//梯度  两个全0矩阵
Mat theta = Mat::zeros(img2.rows, img2.cols, CV_32F);//角度 CV_32F 对应float对应32位
//接下来对图像矩阵做卷积
for(int i=1;i<img2.rows-1;i++)
for (int j = 1; j < img2.cols - 1; j++)
{
float Gx, Gy;
Gx = img2.at<float>(i, j+1 ) - img2.at<float>(i, j-1);
Gy = img2.at<float>(i +1, j) - img2.at<float>(i-1 , j);
gradient.at<float>(i,j) = sqrt((Gx*Gx )+ (Gy*Gy));
theta.at<float>(i, j) = float(atan2(Gy, Gx) * 180 / CV_PI);//梯度方向为【-180,180】
}
normalize(gradient, gradient, 0, 255, NORM_MINMAX, CV_8UC1);
normalize(img2, img2, 0, 255, NORM_MINMAX, CV_8UC1);//CV_8UC1,CV_8UC2,CV_8UC3  1.2.3表示通道数
imshow("梯度图", gradient);
imwrite("D:\\HOG算法测试\\梯度图.jpg", gradient); 
imshow("矫正以后归一化", img2);

waitKey();
return 0;




}






3.梯度方向直方图(重点)


 

 第三步的目的是为局部图像区域提供一个编码,同时能够保持对图像中人体对象的姿势和外观的弱敏感性。

我们将图像分成若干个“单元格cell”,例如每个cell6*6个像素。假设我们采用9bin的直方图来统计这6*6个像素的梯度信息。也就是将cell的梯度方向360度分成9个方向块,如图所示:例如:如果这个像素的梯度方向是20-40度,直方图第2bin的计数就加一,这样,对cell内每个像素用梯度方向在直方图中进行加权投影(映射到固定的角度范围),就可以得到这个cell的梯度方向直方图了,就是该cell对应的9维特征向量(因为有9bin)。

        像素梯度方向用到了,那么梯度大小呢?梯度大小就是作为投影的权值的。例如说:这个像素的梯度方向是20-40度,然后它的梯度大小是2(假设啊),那么直方图第2bin的计数就不是加一了,而是加二(假设啊)。


细胞单元可以是矩形的( rectangular ),也可以是星形的( radial )。

P.S 







4.把cell组合成大的block,块内归一化梯度直方图

由于局部光照的变化以及前景 - 背景对比度的变化,使得梯度强度的变化范围非常大。这就需要对梯度强度做归一化。归一化能够进一步地对光照、阴影和边缘进行压缩。
作者采取的办法是:把各个细胞单元组合成大的、空间上连通的区间( blocks )。这样,一个 block 内所有 cell 的特征向量串联起来便得到该 block HOG 特征。这些区间是互有重叠的,这就意味着:每一个单元格的特征会以不同的结果多次出现在最后的特征向量中。我们将归一化之后的块描述符(向量)就称之为 HOG 描述符。
假设有一幅图像大小为220x310,将其划分成若干个8x8cells,显然220÷8=27.5、310÷8=38.75不是整数,也就是说划分之后依然还有多余像素不能构成cell。处理办法是将图像缩放成能被8整除的长宽(如216x304),再划分。216÷8=27304÷8=38,因此,216x304的图像可以得到27x38cells,没有重叠。
 以上述缩放后的图像为例,共得到 27x38 cell ,也就是将图像划分成了 27x38 个单元;将上下左右相邻的 2x2 cells 当做一个 block 整体,如下所示( 为方便观察,每个颜色框故意错开了一点 ), 黑色 8x8 像素为一个 cell 粉红 绿 框都是一个 block ,即每个框内 2x2 cell 组成一个 block 。故 27x38 cell 可划分成 26x37 block ,每个 block 16x16 像素。相邻 block 之间是有重叠的,这样有效的利用了相邻像素信息,对检测结果有很大的帮助。



接下分别对每个 block 进行标准化,一个 block 内有 4 cell ,每个 cell 9 维特征向量,故每个 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即可得到判别结果。



  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值