所以我一直在玩opencv最新的LBP级联训练器,我一直在无限循环中运行。我相信原因可能是由我有限的负面(背景)图像集引起的。然而程序不应该进入无限循环...我设法识别无限循环的位置并对源代码进行一些修改,不仅避免了无限循环,而且还提高了生成的级联文件中的检测性能。但是,我仍然希望有人了解代码,告诉我这是否是一个正确的解决方案及其工作原理(或其他方式):
样品制备: 所以我有一个正面图像,并使用“创建样本”来生成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阶段,然后在那里停止。我把cascade xml放在我的应用程序中,它表现得相当好,比我在第4阶段设置停止以避免无限循环更好。
我希望更能理解代码的人能够进一步启发我们......
谢谢
答案 0 :(得分: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;
....
希望此解决方案能为您提供帮助。