0

I'm trying to do blob detection on peanut shaped distributions - for a typical example see the image below:

enter image description here

I would like to do find the centroids of the two blobs, but I'm not sure which computer vision methods or algorithms are best to apply to the problem. Ideally the solution should be lightweight, since I need to process many such blobs. So far I've tried using skimage.feature.blob_doh to get the blob center and radius and the finding the weighted mean pixel of that blob, but that hasn't worked very well since blob_doh struggles with the joined nature of the blobs (ie only returns the one blob):

enter image description here

The blobbing code is as follows:

def get_blobs(image, num_blobs):
    img = image
    img = cv.normalize(img, None, 0.0, 1.0, cv.NORM_MINMAX)
    img = img.astype(float)
    blobs = blob_doh(img)
    ys = np.array([x[0] for x in blobs])
    xs = np.array([x[1] for x in blobs])
    rs = np.array([x[2] for x in blobs])
    sort_args = np.argsort(rs)
    xs, ys, rs = xs[sort_args], ys[sort_args], rs[sort_args]
    if len(ys) < num_glints:
        diff = num_blobs - len(ys)
        ys = np.concatenate((ys, np.zeros((diff)))).astype(float)
        xs = np.concatenate((xs, np.zeros((diff)))).astype(float)
        rs = np.concatenate((rs, np.zeros((diff)))).astype(float)
        num_blobs = len(ys)
    xs, ys, rs = xs[0:num_blobs], ys[0:num_blobs], rs[0:num_blobs]

    return xs, ys, rs

I also don't want to binarize the image, since I am finding the centroid with something like this:

def find_centroid(xs, ys, weights):
    sum_w = np.sum(weights)
    sum_x = np.sum(np.multiply(xs, weights))
    sum_y = np.sum(np.multiply(ys, weights))
    cx = sum_x / sum_w
    cy = sum_y / sum_w
    return [cx, cy]

(in other words, all pixels in the blob contribute to the centroid). Many thanks!

1
  • not sure if you've tried this, but you might find that simply applying some morphology operations to the imagery as a preprocessing step (Erosion or Opening) might help split these blobs up. Commented Mar 21, 2021 at 16:34

1 Answer 1

1

Following is one way to do it using OpenCV. This will however binarize the image, but should not have any performance drawbacks. You can adjust thresholding parameter as per your needs and also add filtering on blob size if need be.

import numpy as np
import cv2
import matplotlib.pyplot as plt

rgb = cv2.imread('/your/image/path/blobs_0001.png')
gray = cv2.cvtColor(rgb, cv2.COLOR_BGR2GRAY)

th = cv2.adaptiveThreshold(gray,255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY_INV,11,2)

contours, _ = cv2.findContours(th,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

for cnt in contours:
    M = cv2.moments(cnt)
    cx = int(M['m10']/M['m00'])
    cy = int(M['m01']/M['m00'])
    cv2.circle(rgb, (cx, cy), 5, (255, 0, 0), cv2.FILLED)
    
plt.imshow(rgb)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.