55

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

approxiblue
  • 6,982
  • 16
  • 51
  • 59
user1036908
  • 831
  • 1
  • 12
  • 16
  • 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!!! – user1036908 Nov 11 '11 at 07: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](http://www.simplecv.org) – xamox Nov 12 '11 at 17:07
  • https://www.learnopencv.com/blob-detection-using-opencv-python-c/ – shim Jul 29 '16 at 20:05

4 Answers4

71

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.

Satya Mallick
  • 2,807
  • 1
  • 20
  • 14
  • I think in your blog you updated your answer to also work in OpenCV 3, can you do the same here? – Antonio May 18 '16 at 09:30
  • 1
    How fast is this compared to `findContours()` (`RETR_EXTERNAL` and `CHAIN_APPROX_SIMPLE`)? – étale-cohomology Nov 21 '16 at 06:54
  • 5
    In my case, detector was throwing an error about the self argument. For that, you can write detector = cv2.SimpleBlobDetector_create(params). – Jack Daniels Jul 27 '18 at 11:14
  • 6
    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 – AI Mechanic Sep 04 '20 at 15:18
  • 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. – Avio Mar 28 '22 at 14:01
  • This worked for me, your blog does not. I am thinking it was @AIMechanic's comment – Daniel Lord Dec 03 '22 at 04:03
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;
}
chappjc
  • 30,359
  • 6
  • 75
  • 132
airfang
  • 1,238
  • 3
  • 14
  • 22
  • 1
    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 ? – user391339 Oct 03 '12 at 15:42
  • 5
    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? – Constantin Feb 15 '13 at 16:31
  • +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. – Valentin H Dec 22 '13 at 23:53
  • @airfang How do you extract the biggest blob in the image? The keypoints provide the radiuses and location of the blob centers according to the docs. But, how do you extract the biggest blob? – Eagle Apr 09 '14 at 00:27
  • @Eagle `keypoints[i].size` will give you the size of the blob. just look for the largest and save the index – EdgeCaseBerg Sep 11 '14 at 17:20
  • 4
    Under OpenCV 3 the static construction doesn't seem to work anymore. I had to use cv::Ptr detector = cv::SimpleBlobDetector::create(params) instead, but otherwise this was very helpful. – John Stephen Jan 24 '15 at 19:41
  • 2
    Then, after cv::Ptr detector = cv::SimpleBlobDetector::create(params) , you use: detector -> detect(image, keypoints) – Doombot Mar 20 '15 at 14:52
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

David Wolever
  • 148,955
  • 89
  • 346
  • 502
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.

Yan Foto
  • 10,850
  • 6
  • 57
  • 88
grzes
  • 29
  • 2
  • You have to create the variable of class `SimpleBlobDetector::Params` and pass it in the constructor of the class. – api55 May 17 '16 at 11:48