OpenCV - Getting All Blob Pixels

opencv blob detection
opencv blob tracking
opencv blob detection keypoints
blob detection c++
opencv keypoint
opencv findcontours
opencv find color blob
opencv detect dots

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.

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()

blob draw and number of pixels, Hi, i detected the blobs with the SimpleBlobDetector class . how can i draw these blobs or extract to matrix? How do I calculate the number of� 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 think for your use case, you might benefit more from findContours. You'll even see that the SimpleBlobDetector uses this function. It is mentioned in step 2 of the link you provided, but know that the contour only lists the outer pixels. If all you are doing is simply drawing each blob, then when using drawContours, you just need to set the thickness parameter to -1.

If you need to know each pixel value, then I would say the solution is to draw each contour and then record the pixel values into your own list. It's not totally clear what you're trying to use this for so it's hard to give you a straight answer, but I hope this helps.

Blob Detection Using OpenCV ( Python, C++ ), A Blob is a group of connected pixels in an image that share some E.g. setting minArea = 100 will filter out all the blobs that have less then 100 pixels. If you liked this article and would like to get more OpenCV tips, tricks,� In the context of image processing and computer vision, each shape is made of pixels, and the centroid is simply the weighted average of all the pixels constituting the shape. Image Moments. We can find the center of the blob using moments in OpenCV. But first of all, we should know what exactly Image moment is all about. Image Moment is a

Might be a tad late by I encountered the same problem. I wanted to filter out smaller blobs. So I ended up writing this:

def filter_blobs(bin_img, min_size):
    label_ix = 1
    labels = np.zeros(shape=bin_img.shape)
    for j, row in enumerate(bin_img):
        for i, pix in enumerate(row):
            if pix > 0:
                above = labels[j-1][i] if j > 0 else None
                left = labels[j][i-1] if i > 0 else None
                if above and above > 0:
                    labels[j][i] = above
                    if left and left > 0:
                        labels[labels==left] = above
                elif left and left > 0:
                    labels[j][i] = left
                else:
                    labels[j][i] = label_ix
                    label_ix += 1
    for label in range(1, label_ix+1):
        filt = labels == label
        size = np.sum(filt)
        if size < min_size:
            bin_img[filt] = 0
    return label_ix, labels/np.max(labels)*255, bin_img

bin_img = np.round(np.random.rand(50,50))*255
fig = plt.figure(figsize=(9.5,4))
ax = fig.add_subplot(1,3,1)
ax.imshow(bin_img, cmap='gray', vmin=0, vmax=255)
num_blobs, blob_img, filtered_img = filter_blobs(bin_img, 20)
ax = fig.add_subplot(1,3,2)
ax.imshow(blob_img, cmap='gray', vmin=0, vmax=255)
ax.set_title('# blobs: {}'.format(num_blobs))
ax = fig.add_subplot(1,3,3)
ax.imshow(filtered_img, cmap='gray', vmin=0, vmax=255)
plt.tight_layout()

Here's an example of the output:

Oddly satisfying to play with. If anyone can make this more efficient please comment!

Find Center of a Blob (Centroid) Using OpenCV (C++/Python , A blob is a group of connected pixels in an image that shares some The centroid of a shape is the arithmetic mean (i.e. the average) of all the python code for multiple blobs in an Image, you may get <strong>cX = int� The convention used in OpenCV for their methods is to maintain that the x coordinates are horizontal while the y coordinates are vertical. That's why the notation is flipped in my code above. It's more for compatibility into OpenCV rather than accessing the actual pixels themselves. – rayryeng Mar 13 '17 at 16:14

OpenCV Blob Detection, OpenCV Blob Detection with What is OpenCV, History, Installation, Reading Images, Writing Images, Resize Blob stands for Binary Large Object and refers to the connected pixel in the binary image. After doing this, we get the core part of the background of the subtraction where we calculate the All rights reserved. In OpenCV, all pixels in a row are stored in one continuous block of memory. If the Mat object is created using the create , ALL pixels are stored in one contiguous block of memory. Since we are reading the image from disk and imread uses the create method, we can simply loop over all pixels using simple pointer arithmetic that does not require

OpenCV::blobs() \ language (API), OpenCV opencv; void setup() { size( 640, 480 ); // open video stream opencv When searching for blobs, you must define the minimum and maximum size in pixels. Blob objects contain all the relevant information about each contour ( area,� OpenCV’s blobFromImage and blobFromImages function. Let’s start off by referring to the official OpenCV documentation for cv2.dnn.blobFromImage: [blobFromImage] creates 4-dimensional blob from image. Optionally resizes and crops image from center, subtract mean values, scales values by scalefactor, swap Blue and Red channels.

Blob detection processing library, For complex image processing such as face/object detection OpenCV library From Jun 28, 2018 � Getting Technical: How to build an Object Detection model using The blob detection algorithm is applied to all the white pixels (threshold� Best of all, such algorithm has been implemented in an open-source (GPL) library called CMVision. The algorithm and the inner workings of the library are well-described in a thesis by its author, J. Bruce. It is a worthy reading, if you ever plan on using the library or implementing a similar method. Blob detection

Comments
  • You can use moments to compute the centroids and then draw white filled circles to cover them up. See learnopencv.com/… for moments to centroids computation
  • @fmw42 I appreciate that suggestion but I need to be more precise in my painting since I don’t want to paint out all of the blobs, only ones of a certain size. I need this method to be able to identify and eliminate blobs that are very close together but I don’t want to accidentally obscure any that should not be painted out.
  • Use nathancy's solution below.
  • I really appreciate your response, but - and I updated the OP to reflect this - I'm not looking to paint all of the blobs out, only blobs of a certain size. That's why I was hoping there would be a way to get the blob pixels from SimpleBlobDetector rather than grabbing all the white pixels.
  • @Antillies oh I see, check the update. You can use cv2.findContours() + cv2.contourArea() to filter the blobs based on some threshold area. If the blob passes this filter then we can paint the blob with cv2.drawContours()
  • That did it. The only change I made to your code was to modify threshold_area to min_threshold_area and add a max_threshold_area comparator, altering the if statement to read if area > min_threshold_area and area < max_threshold_area. Thank you for all of your help and insight. As a parting final question, can I ask about this line: cnts = cnts[0] if len(cnts) == 2 else cnts[1]. What's the reasoning to grab the return 'image' if the counters equal two rather than the contours themselves?
  • That line is to obtain the contours regardless of the OpenCV version. See this answer for full explanation