Итак, я играл с новейшим каскадным тренером 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, чтобы избежать бесконечного цикла.
Я надеюсь, что кто-то, кто лучше понимает код, просветит нас дальше...
Спасибо