Skip to content

A SimpleBlobDetector parameter is not used unless other parameter is set #6667

@Efreeto

Description

@Efreeto

SimpleBlobDetector has many parameters, and the two are minDistBetweenBlobs and threshold (set by minThreshold, maxThreshold, thresholdStep)
A developer is forced to use more than one threshold values to use minDistBetweenBlobs parameter, which could degrade processing speed. It also confuses beginners without knowledge in the interworkings of the code because one would normally use just one threshold for blob detection.

Please state the information for your system

  • OpenCV version: 3.1
  • Host OS: Windows 10

In which part of the OpenCV library you got the issue?

  • features2d
  • SimpleBlobDetector

Expected behaviour

  • SimpleBlobDetector parameter minDistBetweenBlobs to work if there is only one threshold.

Actual behaviour

  • minDistBetweenBlobs only works with more than one threshold because the code that uses them can never be reached.

Steps to reproduce the issue

  1. Provide a greyscale image of range 0-255.
  2. Set threshold as min: 250, max: 260, step: 10, so that only one threshold is used at 250.
  3. Change minDistBetweenBlobs

Code example to reproduce the issue

Following is as it is currently in opencv/modules/features2d/src/blobdetector.cpp. I inserted my comment inside /* ... */ blocks.

std::vector < std::vector<Center> > centers;    /* 1. 'centers' is initialized here*/
for (double thresh = params.minThreshold; thresh < params.maxThreshold; thresh += params.thresholdStep)
{
    Mat binarizedImage;
    threshold(grayscaleImage, binarizedImage, thresh, 255, THRESH_BINARY);

    std::vector < Center > curCenters;
    findBlobs(grayscaleImage, binarizedImage, curCenters);
    std::vector < std::vector<Center> > newCenters;
    for (size_t i = 0; i < curCenters.size(); i++)
    {
        bool isNew = true;
        for (size_t j = 0; j < centers.size(); j++)    /* 2. 'centers' has size of 0, so this loop is skipped */
        {
            double dist = norm(centers[j][ centers[j].size() / 2 ].location - curCenters[i].location);
            isNew = dist >= params.minDistBetweenBlobs && dist >= centers[j][ centers[j].size() / 2 ].radius && dist >= curCenters[i].radius;    /* 3. So the code surrounding params.minDistBetweenBlobs is skipped */
            if (!isNew)
            {
                centers[j].push_back(curCenters[i]);

                size_t k = centers[j].size() - 1;
                while( k > 0 && centers[j][k].radius < centers[j][k-1].radius )
                {
                    centers[j][k] = centers[j][k-1];
                    k--;
                }
                centers[j][k] = curCenters[i];

                break;
            }
        }
        if (isNew)
            newCenters.push_back(std::vector<Center> (1, curCenters[i]));
    }
    std::copy(newCenters.begin(), newCenters.end(), std::back_inserter(centers));    /* 4. 'centers' is updated here, but it's not useful for blob detectors with one threshold.
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions