要做一些行人檢測方面的工作,環境爲vs2010+OpenCV2.4.4
參考博客:http://blog.csdn.net/masibuaa/article/details/16105073
http://blog.csdn.net/masibuaa/article/details/16113373
收集樣本訓練了自己的SVM分類器,接下來在用HOG的多尺度檢測函數detectMultiScale()進行檢測時遇到了一些問題,經過查閱大量的資料及反覆閱讀源代碼,終於搞清楚了原因,現在進行一下簡單的整理。
整個過程可以分爲訓練分類器和HOG檢測兩部分
OpenCV的SVM訓練函數中提供了4種核函數:Linear、poly、RBF、sigmoid,依次找出各核函數對應的效果最好的分類器,主要用到兩個函數SVM::train()和SVM::predict()。
SVM::train()訓練分類器,該函數中可以指定包括核函數在內的其他參數。SVM::predict()用於預測。過程簡單表述爲:先確定某一具體核函數(如Linear),其他參數(如Cvalue)取默認值,輸入訓練樣本訓練分類器,統計測試樣本預測的準確率,不斷調整參數,找到預測準確率最高的分類器。
在確定分類器後,則開始對整幅圖像利用HOG:: detectMultiScale()進行多尺度檢測,也正是在這個過程中遇到了問題。對線性核的情況,一切正常。但是在對其他核(如RBF)分類器的情況,出現了問題。OpenCV自帶的源代碼中,判斷是不是目標的閾值爲0,在檢測的過程中將HOG:: detectMultiScale()中對應的參數設置爲0即可,但在非線性核(如RBF)分類器的情況,其閾值則出現了一些不可預料的結果。
針對出現的這種情況,反覆閱讀源代碼並查找了相關的資料,最終確定了原因:HOG的多尺度檢測函數(HOG:: detectMultiScale())或者更準確一點其檢測函數(HOG::detect ())只針對SVM線性核進行檢測!!這在設置HOG檢測子(HOG::setSVMDetector)的時候就已經確定了!!
另外也可以由源代碼中看出,下面附上部分的源代碼片段進行說明,code1爲SVM線性核的計算方法,code2爲HOG檢測函數(HOG:: detect ())的計算方法。
code1:
for( j = 0; j < vcount; j++ )
{
const float* sample = vecs[j];
double s = 0;
for( k = 0; k <= var_count - 4; k += 4 )
s += sample[k]*another[k] + sample[k+1]*another[k+1] +
sample[k+2]*another[k+2] + sample[k+3]*another[k+3];
for( ; k < var_count; k++ )
s += sample[k]*another[k];
results[j] = (Qfloat)(s*alpha + beta);
}
code2: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]);
#ifdef HAVE_IPP
Ipp32f partSum;
ippsDotProd_32f(vec,svmVec,blockHistogramSize,&partSum);
s += (double)partSum;
#else
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];
#endif
}
除了源代碼以外,在OpenCV的官網上也進行了相關的說明:
可惜,在這個問題上糾結這麼久,答案其實早就已經給出來了,但一直都沒找到!