I have this image:
I've been using the opencv feature SimpleBlobDetector
to identify the blobs of white pixels on the black background. Code is below.
blobDetectorParameters = cv2.SimpleBlobDetector_Params()
blobDetectorParameters.filterByArea = True
blobDetectorParameters.minArea = 1
blobDetectorParameters.maxArea = 100
blobDetectorParameters.minDistBetweenBlobs = 1
blobDetectorParameters.filterByCircularity = False
blobDetectorParameters.filterByColor = False
blobDetectorParameters.filterByConvexity = False
blobDetectorParameters.filterByInertia = False
detector = cv2.SimpleBlobDetector_create(blobDetectorParameters)
keypoints = detector.detect(image)
imageWithKeypoints = cv2.drawKeypoints(image, keypoints, numpy.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow("Keypoints", imageWithKeypoints)
cv2.waitKey(0)
Which correctly identifies the blobs as shown in the image below:
The question: I want to be able to have a list of all the blob pixels in order to paint them out. I can't seem to find a way, using the SimpleBlobDetector
, to return the pixels of all blobs. I can get the keypoints (returned via detect
), but I believe those correspond to the blob centers.
I should also add that I only want to paint blobs of a certain size out, which is why a blanket method of grabbing all the white pixels is not ideal.
Is there any function related to the SimpleBlobDetector
(or elsewhere within OpenCV) to return all pixels related to all blobs?
Thank you in advance for your help.
Blob stands for Binary Large Object and refers to the connected pixel in the binary image. The term "Large" focuses on the object of a specific size, and that other "small" binary objects are usually noise. There are three processes regarding BLOB analysis.
To identify circles, ellipses, or in general, any shape in which the pixels are connected we use the SimpleBlobDetector() function of OpenCV.
You can use np.column_stack
+ np.where
on the binary image to obtain the coordinates of all points. For this example I colored each point green onto a new mask. Here's the result
Here's the (x,y)
coordinates of each pixel
[[ 28 32]
[ 28 33]
[ 29 33]
[ 31 25]
[ 31 26]
[ 37 43]
[ 37 44]
[ 37 45]
[ 38 43]
[ 38 44]
[ 38 45]
[ 85 96]
[118 116]
[118 118]
[119 116]
[119 117]
[120 116]
[121 87]
[121 115]
[122 87]
[122 115]
[123 87]
[123 97]
[123 115]
[124 87]
[124 97]
[124 115]
[125 93]
[125 95]
[125 96]
[125 114]
[125 115]
[126 94]
[126 95]
[126 96]
[126 113]
[126 114]
[127 90]
[127 94]
[127 95]
[127 96]
[127 112]
[127 113]
[128 90]
[128 91]
[128 95]
[128 102]
[128 103]
[128 104]
[128 111]
[128 112]
[129 101]
[129 102]
[129 103]
[129 104]
[130 84]
[130 85]
[130 101]
[130 102]]
Code
import numpy as np
import cv2
image = cv2.imread('1.png')
mask = np.zeros(image.shape, dtype=np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
coords = np.column_stack(np.where(thresh > 0))
for coord in coords:
mask[coord[0], coord[1]] = (36,255,12)
print(coords)
cv2.imshow('mask', mask)
cv2.waitKey()
Update: You can use contour area filtering to achieve your desired result. Specifically, we can use cv2.findContours()
to grab the contours of all the blobs then filter using contour area with cv2.contourArea()
. If the contour passes some minimum threshold area, then we draw it otherwise we ignore the contour. We can draw the blob with cv2.drawContours()
, by passing in -1
for the last parameter, we fill in the contour, otherwise any positive value will draw the outline of the blob. Here's an example:
import numpy as np
import cv2
image = cv2.imread('1.png')
mask = np.zeros(image.shape, dtype=np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
threshold_area = 0.5
for c in cnts:
area = cv2.contourArea(c)
if area > threshold_area:
cv2.drawContours(mask, [c], -1, (36,255,12), -1)
cv2.imshow('mask', mask)
cv2.waitKey()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With