SimpleBlobDetector example

asked 2015-05-08 14:53:25 -0500

LBerger gravatar image

Hi,

My program is a small example how to use SimpleBlobDetector and how to use SimpleBlobDetector::Params with this specific image As I am new to opencv I want to know if everything are goods.

Thanks you for time consumming to test it and give your opinion.

My program is

#include <opencv2/opencv.hpp>
#include <vector>
#include <map>
#include <iostream>

using namespace std;
using namespace cv;


static void help()
{
    cout << "\n This program demonstrates how to use BLOB and MSER to detect region \n"
        "Usage: \n"
        "  ./BLOB_MSER <image1(../data/forme2.jpg as default)>\n"
        "Press a key when image window is active to change descriptor";
}
struct MSERParams
    {
    MSERParams(int _delta = 5, int _min_area = 60, int _max_area = 14400,
    double _max_variation = 0.25, double _min_diversity = .2,
    int _max_evolution = 200, double _area_threshold = 1.01,
    double _min_margin = 0.003, int _edge_blur_size = 5)
        {
        delta = _delta;
        minArea = _min_area;
        maxArea = _max_area;
        maxVariation = _max_variation;
        minDiversity = _min_diversity;
        maxEvolution = _max_evolution;
        areaThreshold = _area_threshold;
        minMargin = _min_margin;
        edgeBlurSize = _edge_blur_size;
        pass2Only = false;
        }

    int delta;
    int minArea;
    int maxArea;
    double maxVariation;
    double minDiversity;
    bool pass2Only;

    int maxEvolution;
    double areaThreshold;
    double minMargin;
    int edgeBlurSize;
    };

String Legende(SimpleBlobDetector::Params &pAct)
{
    String s="";
    if (pAct.filterByArea)
        {
        String inf = static_cast<ostringstream*>(&(ostringstream() << pAct.minArea))->str();
        String sup = static_cast<ostringstream*>(&(ostringstream() << pAct.maxArea))->str();
        s = " Area range [" + inf + " to  " + sup + "]";
        }
    if (pAct.filterByCircularity)
        {
        String inf = static_cast<ostringstream*>(&(ostringstream() << pAct.minCircularity))->str();
        String sup = static_cast<ostringstream*>(&(ostringstream() << pAct.maxCircularity))->str();
        if (s.length()==0)
            s = " Circularity range [" + inf + " to  " + sup + "]";
        else
            s += " AND Circularity range [" + inf + " to  " + sup + "]";
        }
    if (pAct.filterByColor)
        {
        String inf = static_cast<ostringstream*>(&(ostringstream() << (int)pAct.blobColor))->str();
        if (s.length() == 0)
            s = " Blob color " + inf;
        else
            s += " AND Blob color " + inf;
        }
    if (pAct.filterByConvexity)
        {
        String inf = static_cast<ostringstream*>(&(ostringstream() << pAct.minConvexity))->str();
        String sup = static_cast<ostringstream*>(&(ostringstream() << pAct.maxConvexity))->str();
        if (s.length() == 0)
            s = " Convexity range[" + inf + " to  " + sup + "]";
        else
            s += " AND  Convexity range[" + inf + " to  " + sup + "]";
        }
    if (pAct.filterByInertia)
        {
        String inf = static_cast<ostringstream*>(&(ostringstream() << pAct.minInertiaRatio))->str();
        String sup = static_cast<ostringstream*>(&(ostringstream() << pAct.maxInertiaRatio))->str();
        if (s.length() == 0)
            s = " Inertia ratio range [" + inf + " to  " + sup + "]";
        else
            s += " AND  Inertia ratio range [" + inf + " to  " + sup + "]";
        }
    return s;
}

int main(int argc, char *argv[])
{
    vector<String> fileName;
    Mat img(600,800,CV_8UC1);
    if (argc == 1)
    {
        fileName.push_back("../data/BLOB_MSER.bmp");
    }
    else if (argc == 2)
        {
        fileName.push_back(argv[1]);
        }
    else
        {
        help();
        return(0);
        }
    img = imread(fileName[0], IMREAD_UNCHANGED);
    if (img.rows*img.cols <= 0)
        {
        cout << "Image " << fileName[0] << " is empty or cannot be found\n";
        return(0);
        }

    SimpleBlobDetector::Params pDefaultBLOB;
    // This is default parameters for SimpleBlobDetector
    pDefaultBLOB.thresholdStep = 10;
    pDefaultBLOB.minThreshold = 10;
    pDefaultBLOB.maxThreshold = 220;
    pDefaultBLOB.minRepeatability = 2;
    pDefaultBLOB.minDistBetweenBlobs = 10;
    pDefaultBLOB.filterByColor = false;
    pDefaultBLOB.blobColor = 0;
    pDefaultBLOB.filterByArea = false;
    pDefaultBLOB.minArea = 25;
    pDefaultBLOB.maxArea = 5000;
    pDefaultBLOB.filterByCircularity = false;
    pDefaultBLOB.minCircularity = 0.9f;
    pDefaultBLOB.maxCircularity = std::numeric_limits<float>::max();
    pDefaultBLOB.filterByInertia = false;
    pDefaultBLOB.minInertiaRatio = 0.1f;
    pDefaultBLOB.maxInertiaRatio = std::numeric_limits<float>::max();
    pDefaultBLOB.filterByConvexity = false;
    pDefaultBLOB.minConvexity = 0.95f;
    pDefaultBLOB.maxConvexity = std::numeric_limits<float>::max();
    // Descriptor array (BLOB or MSER)
    vector<String> typeDesc;
    // Param array for BLOB
    vector ...
(more)
edit retag flag offensive close merge delete

Comments

I think your code it's too articulated. MSER code isn't used neither explained. When draw the circle you should remember you are using radius not diameter. Finally it gains an exception when use filterby color (image should be in grayscale). I think this is much clear for novice.

pklab gravatar imagepklab ( 2015-07-30 11:35:39 -0500 )edit

This post is 3 months old. So some lines have changed in code. You can find two samples now here and here. About your link my sample doesn't want to explain MSER method and Blob detector but only how to use it. Your link is good but my post is only line code it's not a web page with good explanation.

About your remark about radius I cannot find problem in my code :

circle(result, k->pt, (int)k->size, palette[i % 65536]);

parameter in circle is radius so what do you mean by diameter?

LBerger gravatar imageLBerger ( 2015-08-01 08:53:05 -0500 )edit

@pklab thanks for the link. @LBerger thanks for your contribution.

sturkmen gravatar imagesturkmen ( 2015-08-02 16:42:53 -0500 )edit
1

About circle I mean that you are using the size of the blob as radius for the circle while I think you should use k->size/2 . Age of a post it's not so relevant if it can be useful in special case of an "HowTo" post updating and descriptions are welcomes ...you are asking for comment and I'm trying to give my contributions :)

pklab gravatar imagepklab ( 2015-08-03 02:01:53 -0500 )edit

@pklab I'm sorry if you feel hurt with my remark.

About radius I understand now that I haven't read doc and I will have to make a pull request. Thanks

LBerger gravatar imageLBerger ( 2015-08-03 02:19:11 -0500 )edit