Бесконечный цикл в opencv_traincascade CvCascadeClassifier::fillPassedSamples

Итак, я играл с новейшим каскадным тренером 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

Обратите внимание, что я установил -numNeg 200, хотя у меня есть только 5 негативных изображений в «neg.txt». Позже я узнал, что 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, чтобы избежать бесконечного цикла.

Я надеюсь, что кто-то, кто лучше понимает код, просветит нас дальше...

Спасибо


person Joe Qi    schedule 28.01.2013    source источник
comment
см. это: code.opencv.org/issues/3370   -  person tidy    schedule 10.09.2014


Ответы (1)


Джо

вы можете столкнуться с той же проблемой, что и моя.

Проблема возникает из-за того, что 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;
....

Надеюсь, это решение поможет вам.

person herezt    schedule 19.03.2013