参考博文:http://blog.csdn.net/hujingshuang/article/details/47337707/
1.简介
2.具体实现方法
3.HOG特征算法
1.颜色额空间归一化
#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;
}
2.梯度计算
#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”,例如每个cell为6*6个像素。假设我们采用9个bin的直方图来统计这6*6个像素的梯度信息。也就是将cell的梯度方向360度分成9个方向块,如图所示:例如:如果这个像素的梯度方向是20-40度,直方图第2个bin的计数就加一,这样,对cell内每个像素用梯度方向在直方图中进行加权投影(映射到固定的角度范围),就可以得到这个cell的梯度方向直方图了,就是该cell对应的9维特征向量(因为有9个bin)。
像素梯度方向用到了,那么梯度大小呢?梯度大小就是作为投影的权值的。例如说:这个像素的梯度方向是20-40度,然后它的梯度大小是2(假设啊),那么直方图第2个bin的计数就不是加一了,而是加二(假设啊)。
4.把cell组合成大的block,块内归一化梯度直方图
实际上,在运用的时候,我们通常是选取一幅图像中的一个窗口来进行特征提取,依然以上述220X310大小图像为例,经过缩放处理后为216x304,但并不直接提取整个图像的HOG特征,而是用一个固定大小的窗口在图像上滑动,滑动的间隔为8个像素,opencv中默认的窗口大小为128x64(高128,宽64),即有(128÷8)x(64÷8)=16x8个cell,也即有15x7个block,这样一来一幅图像就可以取到(27-16)x(38-8)=11x30=330个窗口。现在提取每个窗口的HOG特征,则可得到105x36=3780维HOG特征向量。
将这330个3780维的HOG特征当做测试样本,用支持向量机(SVM)分类器来判别出,这些窗口的HOG特征是否有行人,有行人的用矩形框标记起来。HOG行人特征及所对应的SVM分类器的参数,在opencv中已经训练好了,我们只需要得到HOG特征,然后调用SVM即可得到判别结果。