其定义在 object.hpp中找到的:
struct CV_EXPORTS_W HOGDescriptor { public: enum { L2Hys=0 }; enum { DEFAULT_NLEVELS=64 }; CV_WRAP HOGDescriptor() : winSize(64,128), blockSize(16,16), blockStride(8,8), cellSize(8,8), nbins(9), derivAperture(1), winSigma(-1), histogramNormType(HOGDescriptor::L2Hys), L2HysThreshold(0.2), gammaCorrection(true), nlevels(HOGDescriptor::DEFAULT_NLEVELS) {} CV_WRAP HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride, Size _cellSize, int _nbins, int _derivAperture=1, double _winSigma=-1, int _histogramNormType=HOGDescriptor::L2Hys, double _L2HysThreshold=0.2, bool _gammaCorrection=false, int _nlevels=HOGDescriptor::DEFAULT_NLEVELS) : winSize(_winSize), blockSize(_blockSize), blockStride(_blockStride), cellSize(_cellSize), nbins(_nbins), derivAperture(_derivAperture), winSigma(_winSigma), histogramNormType(_histogramNormType), L2HysThreshold(_L2HysThreshold), gammaCorrection(_gammaCorrection), nlevels(_nlevels) {} CV_WRAP HOGDescriptor(const String& filename) { load(filename); } HOGDescriptor(const HOGDescriptor& d) { d.copyTo(*this); } virtual ~HOGDescriptor() {} CV_WRAP size_t getDescriptorSize() const; CV_WRAP bool checkDetectorSize() const; CV_WRAP double getWinSigma() const; CV_WRAP virtual void setSVMDetector(InputArray _svmdetector); virtual bool read(FileNode& fn); virtual void write(FileStorage& fs, const String& objname) const; CV_WRAP virtual bool load(const String& filename, const String& objname=String()); CV_WRAP virtual void save(const String& filename, const String& objname=String()) const; virtual void copyTo(HOGDescriptor& c) const; CV_WRAP virtual void compute(const Mat& img, CV_OUT vector<float>& descriptors, Size winStride=Size(), Size padding=Size(), const vector<Point>& locations=vector<Point>()) const; //with found weights output CV_WRAP virtual void detect(const Mat& img, CV_OUT vector<Point>& foundLocations, CV_OUT vector<double>& weights, double hitThreshold=0, Size winStride=Size(), Size padding=Size(), const vector<Point>& searchLocations=vector<Point>()) const; //without found weights output virtual void detect(const Mat& img, CV_OUT vector<Point>& foundLocations, double hitThreshold=0, Size winStride=Size(), Size padding=Size(), const vector<Point>& searchLocations=vector<Point>()) const; //with result weights output CV_WRAP virtual void detectMultiScale(const Mat& img, CV_OUT vector<Rect>& foundLocations, CV_OUT vector<double>& foundWeights, double hitThreshold=0, Size winStride=Size(), Size padding=Size(), double scale=1.05, double finalThreshold=2.0,bool useMeanshiftGrouping = false) const; //without found weights output virtual void detectMultiScale(const Mat& img, CV_OUT vector<Rect>& foundLocations, double hitThreshold=0, Size winStride=Size(), Size padding=Size(), double scale=1.05, double finalThreshold=2.0, bool useMeanshiftGrouping = false) const; CV_WRAP virtual void computeGradient(const Mat& img, CV_OUT Mat& grad, CV_OUT Mat& angleOfs, Size paddingTL=Size(), Size paddingBR=Size()) const; CV_WRAP static vector<float> getDefaultPeopleDetector(); CV_WRAP static vector<float> getDaimlerPeopleDetector(); CV_PROP Size winSize; CV_PROP Size blockSize; CV_PROP Size blockStride; CV_PROP Size cellSize; CV_PROP int nbins; CV_PROP int derivAperture; CV_PROP double winSigma; CV_PROP int histogramNormType; CV_PROP double L2HysThreshold; CV_PROP bool gammaCorrection; CV_PROP vector<float> svmDetector; CV_PROP int nlevels; // evaluate specified ROI and return confidence value for each location void detectROI(const cv::Mat& img, const vector<cv::Point> &locations, CV_OUT std::vector<cv::Point>& foundLocations, CV_OUT std::vector<double>& confidences, double hitThreshold = 0, cv::Size winStride = Size(), cv::Size padding = Size()) const; // evaluate specified ROI and return confidence value for each location in multiple scales void detectMultiScaleROI(const cv::Mat& img, CV_OUT std::vector<cv::Rect>& foundLocations, std::vector<DetectionROI>& locations, double hitThreshold = 0, int groupThreshold = 0) const; // read/parse Dalal's alt model file void readALTModel(std::string modelfile); };
默认构造函数的几个参数:
winSize(64,128), blockSize(16,16), blockStride(8,8), cellSize(8,8), nbins(9), derivAperture(1), winSigma(-1), histogramNormType(HOGDescriptor::L2Hys), L2HysThreshold(0.2), gammaCorrection(true), nlevels(HOGDescriptor::DEFAULT_NLEVELS)
winSize : 窗口的大小
blockSize :块的大小
cellSize: 胞元的大小
nbins: 方向bin的个数 nBins表示在一个胞元(cell)中统计梯度的方向数目,例如nBins=9时,在一个胞元内统计9个方向的梯度直方图,每个方向为360/9=40度。
更详细请移步: http://blog.csdn.net/raocong2010/article/details/6239431
=++++++++++++++++++++++提取 HOG 特征+++++++++++++++++++++++++=
//样本矩阵,nImgNum:横坐标是样本数量。 列数是该 样本对应的 特征维数。ex: 样本是学生,其样本特征可以由 身高,体重,年龄 组成,那么 第二个参数就是 3 啦。
CvMat *data_mat = cvCreateMat( nImgNum, 1764, CV_32FC1 );
//类型矩阵,存储每个样本的类型标志 , 一维,只需要存储该样本属于哪一类即可(只有两类)
CvMat * res_mat = cvCreateMat( nImgNum, 1, CV_32FC1 );
HOGDescriptor *hog=new HOGDescriptor(cvSize(64,64),cvSize(16,16),cvSize(8,8),cvSize(8,8),9);
// 计算hog特征
// trainImg是读入的需要计算特征的图像,IplImage* trainImg=cvCreateImage(cvSize(64,64),8,3);
//descriptors 是结果数组 vector<float> descriptors; HOG特征的维数就是 = descriptors.size 啦,上例中,就是 那个3 啦。
hog->compute(trainImg, descriptors,Size(1,1), Size(0,0));
//计算完成后,把hog特征存储到 上面声明的那个 样本 矩阵中
// i 是当前处理的第 i 张 图片, n 从 0 开始 ++ ,从第 0 列 开始存储。 *iter 是 (vector<float>::iterator iter=descriptors.begin();iter!=descriptors.end();iter++)
cvmSet(data_mat, i, n,*iter);
// 训练读入的图片是有 标签 的( 知道已知属于哪一类), 将标签存入 标签 矩阵 。i 是当前处理的 图片 的 编号。 img_catg[i] 是 读入 的已知的 数据。
cvmSet( res_mat, i, 0, img_catg[i] );
++++++++++++++++++++++++++++++++++开始训练+++++++++++++++++++++++++++
首先要/新建一个SVM
CvSVM svm = CvSVM();
// 开始训练~
svm.train( data_mat, res_mat, NULL, NULL, param ); //data_mat 是 上面提取 到的 HOG特征,存储 m 个样本的 n 个特征, res_mat 是标签矩阵,m个样本属于哪一类,已 // 知的。 param 的定义如下:
CvSVMParams param = CvSVMParams( CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.09, 1.0, 10.0, 0.5, 1.0, NULL, criteria );
CvTermCriteria criteria = cvTermCriteria( CV_TERMCRIT_EPS, 1000, FLT_EPSILON );
// 将训练结果保存在 xml文件中
svm.save( "SVM_DATA.xml" );
此阶段生成文件:
SVM_DATA.xml
训练完成之后,就开始 对 你所需要 的 数据 进行 预测。 这里预测 当前 图片 属于 那一类别。
++++++++++++++++++++++++++++++++++检测样本+++++++++++++++++++++++++++
读入当前要预测的图片 testImg
将testImg 缩放 至 与 训练图片 一样大小 ,直接存放到 trainImg中
计算读入的图片的Hog特征,
hog->compute(trainImg, descriptors,Size(1,1), Size(0,0)); //调用计算函数开始计算
仍用 vector<float> descriptors; 存放结果
创建一个 一行 n 列 的向量。 n 是 特征的个数 。 就是上面的 3 啊, descriptors.size() 啊。 用来存放 当前要预测的图片的 特征
CvMat* SVMtrainMat=cvCreateMat(1,descriptors.size(),CV_32FC1);
// 开始预测
int ret = svm.predict(SVMtrainMat);
ret 返回的是 当前 预测 的 图片 的 类别。 就是 一开始 读到 标签 矩阵 中的 数据。 一般 用 0 or 1 来标示 两大类别。
可将结果文件保存在:
SVM_PREDICT.txt
+++++++++++++++++=OPENCV HOG特征向量个数计算方法+++++++++++++++++++++++
下面参照 网上 方法 说下 怎么计算 的 每个向量 的 特征 维数, 就是一开始就声明 的
样本矩阵 CvMat *data_mat = cvCreateMat( nImgNum, 1764, CV_32FC1 );
中这个 1764 是如何计算出来的。
1. 先确定 你 要训练 以及 检测 的图片 的 大小 IplImage* trainImg=cvCreateImage(cvSize(64,64),8,3);
ok 这里是 64 x 64
2. 确定 HOGDescriptor *hog=new HOGDescriptor(cvSize(64,64),cvSize(16,16),cvSize(8,8),cvSize(8,8),9);
第一个 窗口 大小 设置 为 上面的图片大小 64 x 64 。
第二个 块大小 是 16 x 16 的话 [ 额 这个肿么确定?与前面的 窗口大小有关系 么? 这是opencv中默认的大小]
第三个 块block的步进 stride 8 x 8
第四个是 胞元cell大小 8 x 8
第五个是 cell的直方图的 bin = 9 [ 不懂 +_+]
每个 cell 有 9 个向量
每个block 有 (16 / 8 ) * (16 / 8) = 2 * 2 = 4 个 cell, 那么现在就有 4 * 9 = 36 个向量啦
每个 窗口 有多少个 block 呢?
利用公式 (window_size - block_size)/block_stride + 1 对两个方向进行计算:
( 64 - 16) / 8 + 1 = 7
两个方向 7 * 7 = 49
so 共有 49* 36 = 1764