1.计算Hog的特征得维度:
#include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/objdetect/objdetect.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace std; using namespace cv; #define Posnum 2 //正样本个数 #define Negnum 2 //负样本个数 int main() { char adpos[128], adneg[128]; HOGDescriptor hog(Size(64, 64), Size(16, 16), Size(8, 8), Size(8, 8), 3);//利用构造函数,给对象赋值。 int DescriptorDim;//HOG描述子的维数 Mat samFeatureMat, samLabelMat; //依次读取正样本图片,生成HOG描述子 for (int i = 1; i <= Posnum; i++) { sprintf_s(adpos, "E:\VS2015Opencv\vs2015\project\picture\pos\%d.png", i); Mat src = imread(adpos);//读取图片 resize(src, src, Size(64, 64)); vector<float> descriptors;//HOG描述子向量 hog.compute(src, descriptors); if (i == 1) { DescriptorDim = descriptors.size(); samFeatureMat = Mat::zeros(Posnum + Negnum, DescriptorDim, CV_32FC1); samLabelMat = Mat::zeros(Posnum + Negnum, 1, CV_32FC1); } for (int j = 0; j<DescriptorDim; j++) { samFeatureMat.at<float>(i - 1, j) = descriptors[j]; samLabelMat.at<float>(i - 1, 0) = 1; } } //依次读取负样本图片,生成HOG描述子 for (int k = 1; k <= Negnum; k++) { sprintf_s(adneg, "E:\VS2015Opencv\vs2015\project\picture\neg\%d.png", k); Mat src = imread(adneg);//读取图片 resize(src, src, Size(64, 64)); vector<float> descriptors;//HOG描述子向量 hog.compute(src, descriptors); for (int l = 0; l<DescriptorDim; l++) { samFeatureMat.at<float>(k + Posnum - 1, l) = descriptors[l]; samLabelMat.at<float>(k + Posnum - 1, 0) = -1; } } cout << "特征个数:" << samFeatureMat.rows << endl; cout << "特征维度:" << samFeatureMat.cols << endl; system("pause"); return 0; }
这是一个很简单的代码;
HOGDescriptor(Size _winSize, ---:窗口大小,即检测的范围大小,前面的64*128 Size _blockSize,--- 前面的2*2的cell,即cell的数量,这里要填像素值Size(16,16) Size _blockStride,---每次block移动的步长,以像素计,为一个cell像素块大小 Size _cellSize, ---cell的大小,前面的8*8 int _nbins, ----直方图的组数 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)
相关函数可参考:HOG:从理论到OpenCV实践
setSVMDetector 函数
(1)作用:设置线性SVM分类器的系数
(2)函数原型:C++: void gpu::HOGDescriptor::setSVMDetector(const vector<float>& detector)
detect 函数
(1)作用:用没有多尺度的窗口进行物体检测
(2)函数原型:
vector<Point>& found_locations,
double hit_threshold=0,
Size win_stride=Size(),
Size padding=Size()
)
(3)参数注释
<1>img:源图像。只支持CV_8UC1和CV_8UC4数据类型。
<2>found_locations:检测出的物体的边缘。
<3>hit_threshold:特征向量和SVM划分超平面的阀值距离。通常它为0,并应由检测器系数决定。但是,当系数被省略时,可以手动指定它。
<4>win_stride:窗口步长,必须是块步长的整数倍。
<5>padding:模拟参数,使得CUP能兼容。目前必须是(0,0)。
下面是简单调用api进行行人检测:
#include <opencv2/opencv.hpp> #include <opencv2/objdetect.hpp> using namespace std; using namespace cv; int main() { Mat src, dst; src = imread("E:\VS2015Opencv\vs2015\project\picture\x1.png", 1); if (src.empty()) { printf("can not load the image... "); return -1; } dst = src.clone(); vector<Rect> findrects, findrect; HOGDescriptor HOG; //SVM分类器 HOG.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector()); //多尺度检测 HOG.detectMultiScale(src, findrects, 0, Size(4, 4), Size(0, 0), 1.05, 2); //若rects有嵌套,则取最外面的矩形存入rect for (int i = 0; i < findrects.size(); i++) { Rect rect = findrects[i]; int j = 0; for (; j < findrects.size(); j++) if (j != i && (rect & findrects[j]) == rect) break; if (j == findrects.size()) findrect.push_back(rect); } //框选出检测结果 for (int i = 0; i<findrect.size(); i++) { RNG rng(i); Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)); rectangle(dst, findrect[i].tl(), findrect[i].br(), color, 2); } imshow("src", src); imshow("dst", dst); waitKey(); return 0; }