Shalin Shah
Shalin Shah

Reputation: 8183

Detect mishapen blobs in python using OpenCV

I would like to detect two blobs in the following image:

Original:

enter image description here

I want to have the inside detected like this:

enter image description here

I also want the outside circle detected:

enter image description here

But I'm applying OpenCV's simple blob detection right now and it is not giving me the desired results. This is my code:

# Set up the detector with default parameters.
detector = cv2.SimpleBlobDetector()

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

# 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(image, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

# Show keypoints
final = Image.fromarray(im_with_keypoints)
final.show()

But this is what the blob detector detects:

enter image description here

Hugh Circle detection in OpenCV also doesn't correctly identify the two shapes.

Update: I've also tried ellipse fitting, but instead of detecting either of the blobs, it detects some random line in the image. Here is the code I used for ellipse fitting.

ret,thresh = cv2.threshold(image,127,255,0)
contours,hierarchy = cv2.findContours(thresh, 1, 2)

cnt = contours[0]
M = cv2.moments(cnt)
print M

cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])

ellipse = cv2.fitEllipse(cnt)
cv2.ellipse(im2,ellipse,(0,255,0),2)

final = Image.fromarray(image)
final.show()

Any help in detecting these blobs is appreciated.

Upvotes: 1

Views: 806

Answers (1)

dhanushka
dhanushka

Reputation: 10682

For detecting the inner blob, you can also try clustering and MSERs, because the region looks flat. I downsampled a cropped version of your image and applied these techniques.

Downsampled image

downsampled

Here I use kmeans with 10 clusters. The drawback is you have to specify the number of clusters.

clustered

Here I use MSER. It is more robust.

mser

The code is in c++. Note that you have to scale the outputs to see the details.

Mat im = imread("2L6hP.png", 0);
Mat dw;
pyrDown(im, dw);

// kmeans with 10 clusters
int k = 10;
Mat rgb32fc, lbl;
dw.convertTo(rgb32fc, CV_32F);
int imsize[] = {rgb32fc.rows, rgb32fc.cols};
Mat color = rgb32fc.reshape(1, rgb32fc.rows*rgb32fc.cols);
kmeans(color, k, lbl, TermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0), 2, KMEANS_PP_CENTERS);
Mat lbl2d = lbl.reshape(1, 2, imsize);
Mat lbldisp; // clustered result
lbl2d.convertTo(lbldisp, CV_8U, 1);

// MSER
MSER mser;
vector<vector<Point>> regions;

mser(dw, regions);
Mat regionsMat = Mat::zeros(dw.rows, dw.cols, CV_8U); // MSER result

for (size_t i = 0; i < regions.size(); i++)
{
    for (Point pt: regions[i])
    {
        uchar& val = regionsMat.at<uchar>(pt);
        if (val > 0)
        {
            val += 1;
        }
        else
        {
            val = 1;
        }
    }

}

Upvotes: 1

Related Questions