Search code examples
python-3.xmachine-learningdeep-learningcomputer-visioncomputer-science

How to count instances of a blob in a binary image, (white blobs and black as background color)


I have a binary image with white multiple white blobs and background is black. I want to count number of blobs in this image in python

I tried python function cv.findContours from cv and skimage.measure.find_contours() but it didn't give me required result

img = cv2.imread('test.png', 0)
con = measure.find_contours(img, 0.8)

fig, ax = plt.subplots()
ax.imshow(img, interpolation='nearest', cmap=plt.cm.gray)

for n, contour in enumerate(con):
    ax.plot(contour[:, 1], contour[:, 0], linewidth=2)

ax.axis('image')
ax.set_xticks([])
ax.set_yticks([])
plt.show()

# Trying to save image with contours but failed.

cv2.imwrite('contour.png', con)

# No idea how to count instances of a blob in a binary image

Solution

  • You can use a function that counts the number of connected components. There are implemented options and you can easily write one your own. here is a sample code:

    def connected_components(image):
        # list of tags we have used 
        tags = []
        # current  tag (remember 1 and 0 are already in image so start from 2)
        tag = 2
        # counter
        cntr = 0
        for i in range(image.shape[0]):
            for j in range(image.shape[1]):
                if image[i, j] != 0:
                    if i != 0 and j != 0 and image[i, j-1] != 0 and image[i-1, j] != 0 and image[i-1, j] != image[i, j-1]:
                        image[i, j] = image[i, j - 1]
                        tags.remove(image[i - 1, j])
                        cntr -= 1
                        image[image == image[i - 1, j]] = image[i, j]
                    elif i != 0 and image[i-1, j] != 0:
                        image[i, j] = image[i-1, j]
                    elif j != 0 and image[i, j-1] != 0:
                        image[i, j] = image[i, j-1]
                    else:
                        image[i, j] = tag
                        tags.append(tag)
                        tag += 1
                        cntr += 1
        return image, tags, cntr
    

    what this code is doing: we move on each pixel and if it's a new pixel with 1 value:

    • if no pixel on its left or right are also 1, we give it a new tag.
    • if the pixels to its left or up are also 1, we give it the same tag as they are in
    • if the pixels to its left and up are also 1:
      • we give it the same tag as they are, if they have the same tag already
      • we give it the same tag as one of them, and turn all the pixels with the second tag to the first tag, so these to components are now one (since they are connected by this pixel)

    you can also use predefined methods like this example.