57

Instead of any additional blob detection library, how do I use the cv::SimpleBlobDetector class and its function detectblobs()?

3
  • i have already gone through the description and i am not able to understand still. all the members are not described here and no sample code. i need to know its use to play with its properties!!! Commented Nov 11, 2011 at 7:29
  • We have written a framework in python that wrappers openCV. We have also written our own blob detection library that is included. It is well documented with many examples. Maybe you can give it a try and see if it suits your needs. Code is as simple as: cam = Camera(); img = cam.getImage(); blobs = img.findBlobs(); if blobs: blobs.draw(); img.show(); http://www.simplecv.org Commented Nov 12, 2011 at 17:07
  • learnopencv.com/blob-detection-using-opencv-python-c Commented Jul 29, 2016 at 20:05

4 Answers 4

74
+50

Python: Reads image blob.jpg and performs blob detection with different parameters.

#!/usr/bin/python

# Standard imports
import cv2
import numpy as np;

# Read image
im = cv2.imread("blob.jpg")

# Setup SimpleBlobDetector parameters.
params = cv2.SimpleBlobDetector_Params()

# Change thresholds
params.minThreshold = 10
params.maxThreshold = 200


# Filter by Area.
params.filterByArea = True
params.minArea = 1500

# Filter by Circularity
params.filterByCircularity = True
params.minCircularity = 0.1

# Filter by Convexity
params.filterByConvexity = True
params.minConvexity = 0.87

# Filter by Inertia
params.filterByInertia = True
params.minInertiaRatio = 0.01

# Create a detector with the parameters
# OLD: detector = cv2.SimpleBlobDetector(params)
detector = cv2.SimpleBlobDetector_create(params)


# Detect blobs.
keypoints = detector.detect(im)

# Draw detected blobs as red circles.
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures
# the size of the circle corresponds to the size of blob

im_with_keypoints = cv2.drawKeypoints(im, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

# Show blobs
cv2.imshow("Keypoints", im_with_keypoints)
cv2.waitKey(0)

C++: Reads image blob.jpg and performs blob detection with different parameters.

#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
    // Read image
#if CV_MAJOR_VERSION < 3   // If you are using OpenCV 2
    Mat im = imread("blob.jpg", CV_LOAD_IMAGE_GRAYSCALE);
#else
    Mat im = imread("blob.jpg", IMREAD_GRAYSCALE);
#endif

    // Setup SimpleBlobDetector parameters.
    SimpleBlobDetector::Params params;

    // Change thresholds
    params.minThreshold = 10;
    params.maxThreshold = 200;

    // Filter by Area.
    params.filterByArea = true;
    params.minArea = 1500;

    // Filter by Circularity
    params.filterByCircularity = true;
    params.minCircularity = 0.1;

    // Filter by Convexity
    params.filterByConvexity = true;
    params.minConvexity = 0.87;

    // Filter by Inertia
    params.filterByInertia = true;
    params.minInertiaRatio = 0.01;

    // Storage for blobs
    std::vector<KeyPoint> keypoints;

#if CV_MAJOR_VERSION < 3   // If you are using OpenCV 2

    // Set up detector with params
    SimpleBlobDetector detector(params);

    // Detect blobs
    detector.detect(im, keypoints);
#else 

    // Set up detector with params
    Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params);

    // Detect blobs
    detector->detect(im, keypoints);
#endif 

    // Draw detected blobs as red circles.
    // DrawMatchesFlags::DRAW_RICH_KEYPOINTS flag ensures
    // the size of the circle corresponds to the size of blob

    Mat im_with_keypoints;
    drawKeypoints(im, keypoints, im_with_keypoints, Scalar(0, 0, 255), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);

    // Show blobs
    imshow("keypoints", im_with_keypoints);
    waitKey(0);
}

The answer has been copied from this tutorial I wrote at LearnOpenCV.com explaining various parameters of SimpleBlobDetector. You can find additional details about the parameters in the tutorial.

Sign up to request clarification or add additional context in comments.

6 Comments

I think in your blog you updated your answer to also work in OpenCV 3, can you do the same here?
How fast is this compared to findContours() (RETR_EXTERNAL and CHAIN_APPROX_SIMPLE)?
In my case, detector was throwing an error about the self argument. For that, you can write detector = cv2.SimpleBlobDetector_create(params).
For me python detector = cv2.SimpleBlobDetector(params) caused silent Segmentation fault until I updated it to detector = cv2.SimpleBlobDetector_create(params) in Python 3.6.10; opencv-python==4.4.0.42
It took me an hour to make this example work on a grayscale segmentation mask with three possible values (0, 1 and 2). This is clearly an example of bad default values set inside OpenCV, in my case I had to set to false every filtering criteria except color and area.
|
30

You may store the parameters for the blob detector in a file, but this is not necessary. Example:

// set up the parameters (check the defaults in opencv's code in blobdetector.cpp)
cv::SimpleBlobDetector::Params params;
params.minDistBetweenBlobs = 50.0f;
params.filterByInertia = false;
params.filterByConvexity = false;
params.filterByColor = false;
params.filterByCircularity = false;
params.filterByArea = true;
params.minArea = 20.0f;
params.maxArea = 500.0f;
// ... any other params you don't want default value

// set up and create the detector using the parameters
cv::SimpleBlobDetector blob_detector(params);
// or cv::Ptr<cv::SimpleBlobDetector> detector = cv::SimpleBlobDetector::create(params)

// detect!
vector<cv::KeyPoint> keypoints;
blob_detector.detect(image, keypoints);

// extract the x y coordinates of the keypoints: 

for (int i=0; i<keypoints.size(); i++){
    float X = keypoints[i].pt.x; 
    float Y = keypoints[i].pt.y;
}

7 Comments

I'm assuming the blob data is stored in keypoints. How do you access something like x and y centroid position from a given Keypoint ?
I don't agree with this example, you don't capture the FeatureDetector ptr from the create call... What is the purpose of the create call?
+1 thanks for params usage example (there are probably some better ones, but I first saw yours and it helped me). However, I agree with Constantin. cv::SimpleBlobDetector detector(params); would also do.
Under OpenCV 3 the static construction doesn't seem to work anymore. I had to use cv::Ptr<cv::SimpleBlobDetector> detector = cv::SimpleBlobDetector::create(params) instead, but otherwise this was very helpful.
Then, after cv::Ptr<cv::SimpleBlobDetector> detector = cv::SimpleBlobDetector::create(params) , you use: detector -> detect(image, keypoints)
|
6

Note: all the examples here are using the OpenCV 2.X API.

In OpenCV 3.X, you need to use:

Ptr<SimpleBlobDetector> d = SimpleBlobDetector::create(params);

See also: the transition guide: http://docs.opencv.org/master/db/dfa/tutorial_transition_guide.html#tutorial_transition_hints_headers

Comments

2
// creation 
            cv::SimpleBlobDetector * blob_detector; 
            blob_detector = new SimpleBlobDetector(); 
            blob_detector->create("SimpleBlobDetector"); 
// change params - first move it to public!! 
            blob_detector->params.filterByArea = true; 
            blob_detector->params.minArea = 1; 
            blob_detector->params.maxArea = 32000; 
// or read / write them with file 
            FileStorage fs("test_fs.yml", FileStorage::WRITE); 
            FileNode fn = fs["features"]; 

            //blob_detector->read(fn); 
// detect 
            vector<KeyPoint> keypoints; 
            blob_detector->detect(img_text, keypoints); 
            fs.release(); 

I do know why, but params are protected. So I moved it in file features2d.hpp to be public:

  virtual void read( const FileNode& fn ); 
  virtual void write( FileStorage& fs ) const; 

public: 
Params params; 




protected: 
struct CV_EXPORTS Center 
  { 
      Point2d loc 

If you will not do this, the only way to change params is to create file (FileStorage fs("test_fs.yml", FileStorage::WRITE);), than open it in notepad, and edit. Or maybe there is another way, but I`m not aware of it.

1 Comment

You have to create the variable of class SimpleBlobDetector::Params and pass it in the constructor of the class.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.