3

所以我一直在玩opencv最新的LBP级联训练器,我一直在无限循环。我相信原因可能是由于我有限的负(背景)图像集造成的。但是程序不应该陷入无限循环......我设法确定了无限循环的位置并对源代码进行了一些修改,不仅避免了无限循环,而且提高了生成的级联文件的检测性能。但是,我仍然希望了解代码的人告诉我这是否是一个正确的修复以及它为什么起作用(或其他原因):

样本准备:所以我有一个正图像,并使用“createsamples”生成 100 个扭曲/旋转的正样本:

opencv_createsamples -img positive1.png -num 100 -bg neg.txt -vec samples.vec -maxidev 50 -w 100 -h 62 -maxxangle 0 -maxyangle 0.6 -maxzangle 0.4 -show 1

我在“负”目录中只有 5 个负样本。然后我的训练命令:

opencv_traincascade -data cascade_result -vec samples.vec -bg neg.txt -numStages 10 -numPos 100 -numNeg 200 -featureType LBP -w 100 -h 62 -bt DAB -minHitRate 0.99 -maxFalseAlarmRate 0.2 -weightTrimRate 0.95 -maxDepth 1

请注意,即使“neg.txt”中只有 5 张负片图像,我也设置了 -numNeg 200。后来我发现 numNeg 不需要匹配负图像的数量,因为程序会反复从负图像中“裁剪”出图像片段,以针对正图像进行训练。

在第 4 阶段,我遇到了无限循环,它位于(参见“// !!!!!”):

int CvCascadeClassifier::fillPassedSamples( int first, int count, bool isPositive, int64& consumed )
{
    int getcount = 0;
    Mat img(cascadeParams.winSize, CV_8UC1);
cout << "isPos: "<< isPositive << "; first: "<< first << "; count: "<< count << endl;
    for( int i = first; i < first + count; i++ )
    {
  int inner_count = 0;
  // !!!!! Here is the start of infinite loop
        for( ; ; )
        {
            // !!!!! This is my code to fix the infinite loop:
        /*
        inner_count++;
        if (inner_count > numNeg * 200) // there should be less than 200 crops of negative images per negative image
        {
            cout << "force exit the loop: inner count: "<< inner_count << "; consumed: " << consumed << endl;
            break;
        }
    */
            bool isGetImg = isPositive ? imgReader.getPos( img ) :
                                       imgReader.getNeg( img );
            if( !isGetImg )
                return getcount;
            consumed++;

            featureEvaluator->setImage( img, isPositive ? 1 : 0, i );
            if( predict( i ) == 1 )
            {
                getcount++;
                break;
            }
        }
    }
    return getcount;
}

我认为问题是 imgReader.getNeg(img) 不断从负集裁剪,直到满足“preduct(i) == 1”条件以退出无限循环。我不明白“预测(i)”的作用,但我猜如果负集很小且有限,它将用完“预测(i)”的“各种”图像以返回1......所以循环永远不会结束。一种解决方案是创建负集,这是我接下来要尝试的。另一个更快的解决方案是我在 // !!!!!! 中添加的代码 将尝试次数限制为平均每个负图像 200 次,然后如果没有找到好的候选者,则强制退出循环。

通过此修复,我的训练课程进入第 5 阶段,然后停在那里。我将级联 xml 放在我的应用程序中,它的性能相当不错,比我在第 4 阶段设置停止以避免无限循环要好。

我希望更了解代码的人能进一步启发我们......

谢谢你

4

1 回答 1

2

你可能会遇到和我一样的问题。

问题是因为opencv_traincascade.exe没有正确获取图像宽高或者原始图像宽高小于训练窗口大小。

您可以将以下代码中箭头指向的两行添加到 opencv/appa/traincascade/imagestorage.cpp 以解决问题。

bool CvCascadeImageReader::NegReader::nextImg()
{
    Point _offset = Point(0,0);
    size_t count = imgFilenames.size();
    for( size_t i = 0; i < count; i++ )
    {
        src = imread( imgFilenames[last++], 0 );
        if(src.rows<winSize.height || src.cols < winSize.width)   <-----------
            continue;                                             <-----------
        if( src.empty() )
            continue;
....

希望此解决方案对您有所帮助。

于 2013-03-19T09:17:35.977 回答