方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子。它通过计算和统计图像局部区域的梯度方向直方图来构成特征。Hog特征结合SVM分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功
主要思想:在一副图像中,局部目标的表象和形状(appearance and shape)能够被梯度或边缘的方向密度分布很好地描述。(本质:梯度的统计信息,而梯度主要存在于边缘的地方)
首先将图像分成小的连通区域,我们把它叫细胞单元。然后采集细胞单元中各像素点的梯度的或边缘的方向直方图。最后把这些直方图组合起来就可以构成特征描述器
把这些局部直方图在图像的更大的范围内(我们把它叫区间或block)进行对比度归一化(contrast-normalized),所采用的方法是:先计算各直方图在这个区间(block)中的密度,然后根据这个密度对区间中的各个细胞单元做归一化。通过这个归一化后,能对光照变化和阴影获得更好的效果.
与其他的特征描述方法相比,HOG有很多优点。首先,由于HOG是在图像的局部方格单元上操作,所以它对图像几何的和光学的形变都能保持很好的不变性,这两种形变只会出现在更大的空间领域上。其次,在粗的空域抽样、精细的方向抽样以及较强的局部光学归一化等条件下,只要行人大体上能够保持直立的姿势,可以容许行人有一些细微的肢体动作,这些细微的动作可以被忽略而不影响检测效果。因此HOG特征是特别适合于做图像中的人体检测的.
什么是方向梯度?
方向很简单,指的就是图像梯度的方向或朝向。Hog就是一张有关图像梯度方向的直方图。首先HOG会接受一张图像,然后计算每个像素的梯度幅度和方向
void detectMultiScale(
const Mat& image,
CV_OUT vector& objects,
double scaleFactor = 1.1,
int minNeighbors = 3,
int flags = 0,
Size minSize = Size(),
Size maxSize = Size()
);
#include
#include
#include
#include
using namespace cv;
using namespace std;
using namespace cv::xfeatures2d;
Mat src,dst, gray_src;
const char* output_title = "output_win";
int corners = 20;
int max_corners = 50;
void Tomasi_Demo(int, void*);
void SubPixel_Demo(int, void*);
int main(int argc, char** argv) {
src = imread("wuhu.jpg");
if (src.empty()) {
printf("could not load image");
return -1;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input_img", src);
//计算检测算子
//将目标图像转化为窗口大小
//resize(src, dst, Size(64, 128));
//cvtColot(dst, dst_gray, COLOR_BGR2GRAY);
//定义HOG检测器
//HOGDescriptor detector(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9);
//定义容器装特征描述子以及对应描述子的位置
//vector descriptors;
//vector locations;
//根据窗口大小自动计算窗口移动步长,并返回算子数据
//detector.compute(dst_gray,descriptors,Size(0,0),Size(0,0),locations);
//printf("number of HOG descriptors:%d", descriptors.size());//3780
//行人检测案例
//新建一个HOGDescriptor对象
HOGDescriptor hog = HOGDescriptor();
//使用open CV定义好的模型
//新建一个SVM分类检测器
//getDefaultPeopleDetector()--人像检测库
hog.setSVMDetector(hog.getDefaultPeopleDetector());
vector foundLocation;//定义容器装检测结果的矩形
//detectMultiScale对图像进行多尺度检测
hog.detectMultiScale(src, foundLocations, 0, Size(8, 8), Size(32, 32), 1.05, 2);
//将结果在另一张图片中画出
Mat result = src.clone();
for (size_t i = 0; i < foundLocations.size(); i++)
{
rectangle(result, foundLocation[i], Scalar(0, 0, 255), 2, 8, 0);
}
imshow("HOG SVM Detector Demo", result);
waitKey(0);
return 0;
}
部分内容注释的原因是,这里直接用了OpenCV已经学习好的函数。
但是当图片比较复杂的时候,会勾选一些莫名其妙的位置,甚至会忽略掉一部分人
自己测试的效果图很不好