用于人像的识别,动物识别。需要提前录入训练数据,才能进行对比识别,OpenCV中已经录入了行人的训练数据
HOG(Histogram of Oriented Gradient)特征描述子提取:
- 灰度图像转换—gray = R*0.3 + 0.59*G + 0.11*B
- 梯度计算—sobel算子计算梯度,像素点的两个特征:方向(角度)与梯度
- 分网格的梯度方向直方图
- 块描述子—方块的:R-HOG 圆形的:C-HOG
- 块描述子归一化 —至此得到了 HOG特征的数据了
特征数据与检测窗口
最终获得HOG描述算子(特征数据) 需要正向训练200个左右的特征样本 反向训练600~800个左右的特征样本 初步测试、开窗检测 举例: 对于64x128的像素块,可以分为8x16个Cell分为7x15个块(R-HOG) 总计的直方图向量数为: 7x15x2x2x9 = 3780个向量数组
匹配方法
cv::HOGDescriptor HOGDescriptor( // HOG特征描述子提取 Size _winSize, // 窗口大小,对应上面举例的 64x128 Size _blockSize, // 2x2个_cellSize,也就是 16x16 Size _blockStride, // 每次移动步长,也就是 _cellSize的尺寸 8x8 Size _cellSize, // 8x8 int _nbins, // 对梯度方向直方图中的bins 9 int _derivAperture=1, // 求梯度的参数 double _winSigma=-1, int _histogramNormType=HOGDescriptor::L2Hys, // 求直方图的参数 double _L2HysThreshold=0.2, // 归一化阈值参数 bool _gammaCorrection=false, // 对于灰度的输入图像是否要做伽马校正 int _nlevels=HOGDescriptor::DEFAULT_NLEVELS, bool _signedGradient=false
)
代码
#include "../common/common.hpp"
void main(int argc, char** argv)
{
Mat src = imread(getCVImagesPath("images/hogman.png"));
imshow("src-13", src);
// HOG特征描述子
Mat dst, dst_gray;
resize(src, dst, Size(64, 128)); // 将原始图像变成 64x128 尺寸
imshow("resize2-13", dst);
cvtColor(dst, dst_gray, COLOR_BGR2GRAY);
HOGDescriptor detector(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9); // HOG特征描述子提取类
vector<float> descriptors; // 保存举例中的计算出来的3780个向量数组
vector<Point> locations; // 作用?
detector.compute(dst_gray, descriptors, Size(0, 0), Size(0, 0), locations); // 计算HOG特征描述子
// descriptors.size=3780, locations.size=0
cout << "descriptors.size=" << descriptors.size() << ", locations.size=" << locations.size() << endl;
// HOG+SVM 实现行人检测
Mat walkers = imread(getCVImagesPath("images/HOGV.png"));
imshow("walkers", walkers);
HOGDescriptor hog = HOGDescriptor();
hog.setSVMDetector(hog.getDefaultPeopleDetector()); // opencv自带的封装好了行人数据的Detector
vector<Rect> foundLocations; // 保存检测到的行人的 Rect
hog.detectMultiScale(walkers, foundLocations, 0, Size(8, 8), Size(32, 32), 1.05, 2); // 在多个尺寸上寻找,detect 同一尺度
cout << "foundLocations.size=" << foundLocations.size() << endl; // foundLocations.size=3
Mat result = walkers.clone();
for (size_t t = 0; t < foundLocations.size(); t++) {
rectangle(result, foundLocations[t], Scalar(0, 0, 255), 2, 8, 0); // 绘制行人的方框
}
imshow("HOG SVM Detector", result);
waitKey(0);
}