【原文:http://hi.baidu.com/windey1988/item/c239139f9efbacc3b62531fd】
opencv中带有计算HOG的代码,同时还包含了一个peopledetect的例程。
在例程中,声明一个HOGDescriptor的对象hog,构造函数为系统默认的构造函数,
检测窗大小为64*128,block大小为16*16,cell大小为8*8,每个cell包含的方向bin
为9个。对于hog对象的一个成员SVMDetector,采用如下的方式进行初始化:
hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());
输入一张图片时,对于这张图片进行多尺度检测。原理很简单:对于检测窗中
的图像计算HOG描述子,然后和SVMDetector求内积,加上一个rho,若大于等于
一个阈值,表示检测窗中对应的是行人。
其源代码中检测部分核心实现如下:
double s = rho;
const float* svmVec = &svmDetector[0];
int j, k;
for( j = 0; j < nblocks; j++, svmVec += blockHistogramSize )
{
const HOGCache::BlockData& bj = blockData[j];
Point pt = pt0 + bj.imgOffset;
const float* vec = cache.getBlock(pt, &blockHist[0]);
for( k = 0; k <= blockHistogramSize - 4; k += 4 )
s += vec[k]*svmVec[k] + vec[k+1]*svmVec[k+1] +
vec[k+2]*svmVec[k+2] + vec[k+3]*svmVec[k+3];
for( ; k < blockHistogramSize; k++ )
s += vec[k]*svmVec[k];
}
if( s >= hitThreshold )
hits.push_back(pt0);
这里默认的Detector其实就是一个3780维的浮点数组。它到底是怎么来的呢?
这里我纠结了好久好久。网上有人说,它其实是支持向量的加权,也就是求和
(支持向量sv_i * alpha_i)。
其实很简单,根据SVM的原理,构建一个最大间隔的超平面,有效地将样本
分为两类。分类超平面对应的方程为:wx+b=0.
因此,我们很容易的可以知道,这个Detector其实就是方程中的w。
因此,由支持向量和对应的alpha加权可以得到。由于opencv中cvSVM类将支持向量
和权值alpha都设置为了保护成员,我们可以引入一个派生类继承于cvSVM,通过操作
cvSVM的支持向量和alpha可以得到检测子。
关于如何得到SVMDetector的讨论可以看:
http://tech.groups.yahoo.com/group/OpenCV/message/80890
http://comments.gmane.org/gmane.comp.lib.opencv/46508