2

I using OpenCV for foreground detection, but I have a question if someone can help. The question is in these two parameters:

  • Learn Rate in: bst.apply(currentFame, foregroungMask, learnRate); // -1 for auto, and the range is 0~1
  • Ratio bst.setBackgroundRatio(double ratio) // default is 0.8xxx

The question is are these two parameters are the same, if the answer is the NO then what is the second parameter can do?

The question has come when I saw that setBackgroundRatio(double ratio) method is not present in BackgroundSubtractorKNN class, but it is only in BackgroundSubtractorMOG2 class. But they both have the learn rate parameter in apply() method.

Note: I am using OpenCV in Java

Bahramdun Adil
  • 5,907
  • 7
  • 35
  • 68

1 Answers1

5

No both are not same.

Learning Rate:

The value between 0 and 1 that indicates how fast the background model is learnt. Negative parameter value makes the algorithm to use some automatically chosen learning rate. 0 means that the background model is not updated at all, 1 means that the background model is completely reinitialized from the last frame.

Ratio:

BackgroundSubtractorMOG2 and BackgroundSubtractorKNN are two different implementation of two different background subtraction algorithms. So, the setBackgroundRatio is not required for BackgroundSubtractorKNN algorithm. Did not found much about this parameter, after seeing the code of this algorithm it seems it is a total weight capping parameter. Not allows total weight more than this threshold. See this code from c++ impelentation:

   void BackgroundSubtractorMOG2Impl::getBackgroundImage(OutputArray backgroundImage) const
{
    if (opencl_ON)
    {
        CV_OCL_RUN(opencl_ON, ocl_getBackgroundImage(backgroundImage))

        opencl_ON = false;
        return;
    }

    int nchannels = CV_MAT_CN(frameType);
    CV_Assert(nchannels == 1 || nchannels == 3);
    Mat meanBackground(frameSize, CV_MAKETYPE(CV_8U, nchannels), Scalar::all(0));
    int firstGaussianIdx = 0;
    const GMM* gmm = bgmodel.ptr<GMM>();
    const float* mean = reinterpret_cast<const float*>(gmm + frameSize.width*frameSize.height*nmixtures);
    std::vector<float> meanVal(nchannels, 0.f);
    for(int row=0; row<meanBackground.rows; row++)
    {
        for(int col=0; col<meanBackground.cols; col++)
        {
            int nmodes = bgmodelUsedModes.at<uchar>(row, col);
            float totalWeight = 0.f;
            for(int gaussianIdx = firstGaussianIdx; gaussianIdx < firstGaussianIdx + nmodes; gaussianIdx++)
            {
                GMM gaussian = gmm[gaussianIdx];
                size_t meanPosition = gaussianIdx*nchannels;
                for(int chn = 0; chn < nchannels; chn++)
                {
                    meanVal[chn] += gaussian.weight * mean[meanPosition + chn];
                }
                totalWeight += gaussian.weight;

               if(totalWeight > backgroundRatio)
                    break;
            }
            float invWeight = 1.f/totalWeight;
            switch(nchannels)
            {
            case 1:
                meanBackground.at<uchar>(row, col) = (uchar)(meanVal[0] * invWeight);
                meanVal[0] = 0.f;
                break;
            case 3:
                Vec3f& meanVec = *reinterpret_cast<Vec3f*>(&meanVal[0]);
                meanBackground.at<Vec3b>(row, col) = Vec3b(meanVec * invWeight);
                meanVec = 0.f;
                break;
            }
            firstGaussianIdx += nmixtures;
        }
    }
    meanBackground.copyTo(backgroundImage);
}

In c++ implementation backgroundRatio is used to cap weights under it. Default 0.8. I think with this default you will get the expected results

Interesting comment found in opencv background_segm.hpp file which seems it is less significant and standard practice is to go with the default:

/////////////////////////
    // less important parameters - things you might change but be carefull
    ////////////////////////
    float backgroundRatio;
MD. Nazmul Kibria
  • 1,080
  • 10
  • 21
  • Thanks Sir for you reply! You mean that for KNN it is not allowed to change the ratio? And also for MOG2 it although we can change the value, but it is better that leave it as its default? But the learn rate is something different and we can pass the value form 0~1 or -1? Am I right? If yes, then your answer has solved the problem. – Bahramdun Adil Sep 26 '16 at 06:04
  • if you want to learn it auto set it -1 and 1 for update background from last frame and 0 for not updating background. So, it is clear the parameter is -1, 1 or zero ... nothing in between – MD. Nazmul Kibria Sep 26 '16 at 06:12
  • How if param is 0.xx?? – Bahramdun Adil Sep 26 '16 at 06:20
  • 0.xx seems also possible. see this code: learningRate = learningRate >= 0 && nframes > 1 ? learningRate : 1./std::min( 2*nframes, history ); – MD. Nazmul Kibria Sep 26 '16 at 06:25
  • OK Thanks for the answer! – Bahramdun Adil Sep 26 '16 at 06:27