[捉蟲記錄]關於Cascade Training Error的bug

LinJM-機器視覺發表於2015-08-26

Jeremy 

opencv_traincascade.exe -data data -vec diode\pos.vec -bg nodiode\neg.dat -numPos 600 -numNeg 600 -numStages 15 -w 22 -h 52 -minHitRate 0.995 -maxFalseAlarmRate 0.5 
pause

Note:如果上面的引數名稱寫錯了,程式會自動忽略,並取預設數值.


在應用opencv_traincascade.exe對圖片進行訓練的過程中碰到很多問題,現一一記錄如下:


[bug1]: Train dataset for temp stage can not filled. Branch training terminated.


首先我們來看這個錯誤時從哪裡出來的,從原始碼[cascadeclassifier.cpp]中我們可以看到:

    for( int i = startNumStages; i < numStages; i++ )
    {
        cout << endl << "===== TRAINING " << i << "-stage =====" << endl;
        cout << "<BEGIN" << endl;

        if ( !updateTrainingSet( requiredLeafFARate, tempLeafFARate ) )
        {
            cout << "Train dataset for temp stage can not be filled. "
                "Branch training terminated." << endl;
            break;
        }
        if( tempLeafFARate <= requiredLeafFARate )
        {
            cout << "Required leaf false alarm rate achieved. "
                 "Branch training terminated." << endl;
            break;
        }

        CvCascadeBoost* tempStage = new CvCascadeBoost;
        bool isStageTrained = tempStage->train( (CvFeatureEvaluator*)featureEvaluator,
                                                curNumSamples, _precalcValBufSize, _precalcIdxBufSize,
                                                *((CvCascadeBoostParams*)stageParams) );
        cout << "END>" << endl;

可以知道,是在函式updateTrainingSet()中出了問題,我們接下來進去看看:

bool CvCascadeClassifier::updateTrainingSet( double minimumAcceptanceRatio, double& acceptanceRatio)
{
    int64 posConsumed = 0, negConsumed = 0;
    imgReader.restart();
    int posCount = fillPassedSamples( 0, numPos, true, 0, posConsumed );
    if( !posCount )
        return false;
    cout << "POS count : consumed   " << posCount << " : " << (int)posConsumed << endl;

    int proNumNeg = cvRound( ( ((double)numNeg) * ((double)posCount) ) / numPos ); // apply only a fraction of negative samples. double is required since overflow is possible
    int negCount = fillPassedSamples( posCount, proNumNeg, false, minimumAcceptanceRatio, negConsumed );
    if ( !negCount )
        return false;

    curNumSamples = posCount + negCount;
    acceptanceRatio = negConsumed == 0 ? 0 : ( (double)negCount/(double)(int64)negConsumed );
    cout << "NEG count : acceptanceRatio    " << negCount << " : " << acceptanceRatio << endl;
    return true;
}

我們的錯誤輸出是在"POS count……"之後,“NEG count”之前,這樣……問題就是negCount=false,也即fillPassedSamples()函式出錯了


後來我把numPos變大為1500,numNeg變大為1200。因為每次stage的迭代過程中會只更換“1%”左右的樣本。





相關文章