title: Infinite loop in opencv_traincascade CvCascadeClassifier::fillPassedSamples
body: <p>So I have been playing around with opencv's newest LBP cascade trainer, and I keep running into infinite loop. I believe the reason may be caused by my limited negative (background) image set. However the program should not run into infinite loop... I managed to identify the location of infinite loop and made some modification to the source code not only to avoid the infinite loop, but also improved the detection performance in the resulting cascade file. However, I would still like someone who understands the code to tell me if this is a proper fix and why it works (or otherwise):</p>
  
  <p>Sample preparation:
  So I have one positive image, and used "createsamples" to generate 100 distorted / rotated positive samples: </p>
  
  <pre><code>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
  </code></pre>
  
  <p>I have only 5 negative samples in the "negative" directory. Then my training command:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Note that I set -numNeg 200 even though I only have 5 negative images in  "neg.txt". Later I found out numNeg does not need to match the number of negative images, as the program "crops" out pieces of images from your negative images repeatedly to use against positive images for training.</p>
  
  <p>At stage 4 is where I run into the infinite loop, and it is in (see "// !!!!!" ):</p>
  
  <pre><code>int CvCascadeClassifier::fillPassedSamples( int first, int count, bool isPositive, int64&amp; consumed )
  {
      int getcount = 0;
      Mat img(cascadeParams.winSize, CV_8UC1);
  cout &lt;&lt; "isPos: "&lt;&lt; isPositive &lt;&lt; "; first: "&lt;&lt; first &lt;&lt; "; count: "&lt;&lt; count &lt;&lt; endl;
      for( int i = first; i &lt; 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 &gt; numNeg * 200) // there should be less than 200 crops of negative images per negative image
          {
              cout &lt;&lt; "force exit the loop: inner count: "&lt;&lt; inner_count &lt;&lt; "; consumed: " &lt;&lt; consumed &lt;&lt; endl;
              break;
          }
      */
              bool isGetImg = isPositive ? imgReader.getPos( img ) :
                                         imgReader.getNeg( img );
              if( !isGetImg )
                  return getcount;
              consumed++;
  
              featureEvaluator-&gt;setImage( img, isPositive ? 1 : 0, i );
              if( predict( i ) == 1 )
              {
                  getcount++;
                  break;
              }
          }
      }
      return getcount;
  }
  </code></pre>
  
  <p>I think the problem is imgReader.getNeg(img) keeps cropping from the negative set until "preduct(i) == 1" condition is satisfied to exit the infinite loop. I do not understand what "predict(i)" does, but I do guess that if negative set is small and limited, it will run out of "variety" of images for "predict(i)" to return 1... so loop never finishes. One solution is to increate negative set which is what I am going to try next. The other quicker solution is the code I added in // !!!!!  to limite the number of try's to 200 per negative images on average, then force exit the loop if no good candidate is found.</p>
  
  <p>With this fix, my training session went on to stage 5, then stopped there. I put the cascade xml in my app, and it performed reasonably well, better than if I set stop at stage 4 to avoid infinite loop.</p>
  
  <p>I hope someone who understands the code more would enlighten us further...</p>
  
  <p>thank you</p>