Gustavo Pucci
Gustavo Pucci

Reputation: 33

How to count how many white "balls" there are in an image with Opencv Python?

I have this image and I´m trying to count how many white "balls" there are

Imagem

I´m trying this code below and get this result

Result

import cv2
import numpy as np
img = cv2.imread('MASK.jpg', cv2.IMREAD_GRAYSCALE)
img = cv2.resize(img,(700,700))
img = cv2.subtract(255, img)

detector = cv2.SimpleBlobDetector_create()

 # Detect the blobs in the image
 keypoints = detector.detect(img)
 print(len(keypoints))


 imgKeyPoints = cv2.drawKeypoints(img, keypoints, np.array([]), (0,0,255), 
 cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

 cv2.imshow("Keypoints", imgKeyPoints)
 cv2.waitKey(0)

 cv2.destroyAllWindows()

Upvotes: 2

Views: 3608

Answers (1)

nathancy
nathancy

Reputation: 46580

Some preprocessing to isolate the blobs become counting them can help. Here's an approach:

  • Convert image to grayscale
  • Otsu's threshold
  • Morph open to remove noise
  • Find contours and sum blobs

After converting to grayscale, we Otsu's threshold to get a binary image

Next we morph close with a cv2.MORPH_ELLIPSE kernel to remove noise and separate the blobs better

Next we find contours and sum the blobs. Note the morph close did not "detach" all the connected blobs, so we filter using contour area. If the blob is greater than some minimum threshold, we count the blob as a double instead of a single. Here's the detected blobs

Result

blobs: 325

import cv2
import numpy as np

image = cv2.imread('1.jpg')
mask = np.zeros(image.shape, dtype=np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray,0,255,cv2.THRESH_OTSU + cv2.THRESH_BINARY)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7,7))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=5)

cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

blobs = 0
for c in cnts:
    area = cv2.contourArea(c)
    cv2.drawContours(mask, [c], -1, (36,255,12), -1)
    if area > 13000:
        blobs += 2
    else:
        blobs += 1

print('blobs:', blobs)

cv2.imshow('thresh', thresh)
cv2.imshow('opening', opening)
cv2.imshow('image', image)
cv2.imshow('mask', mask)
cv2.waitKey()

Upvotes: 2

Related Questions