0

Objective: Copy the bigger blobs in another mask image

I have a threshold image with blobs as shown:

enter image description here

How could I copy the bigger blobs into a mask image and leave out the one-pixel blobs?

enter image description here

My code (but I am not getting the desired result):

import numpy as np
import cv2

ref_img = cv2.imread('threshold.jpg', 0)
thresh = np.copy(ref_img)
cnts,_ = cv2.findContours(ref_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
mask = np.zeros(ref_img.shape, dtype="uint8")
for c in cnts:
   (x,y),radius = cv2.minEnclosingCircle(c)
   area = cv2.contourArea(c)
   if int(area) < 1:
      cv2.circle(mask, (int(x), int(y)), int(radius), (255, 255, 255), -1)

cv2.imshow('img', mask)
cv2.waitKey(0)

Note: Using OpenCV 2.4.x

Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
Jeremy
  • 189
  • 4
  • 14
  • 1
    you say "bigger blobs"... try if int(area) > 1: instead of "less than". – user1269942 Nov 23 '18 at 16:38
  • In addition to above comment, don't draw circles, if you want to copy the blobs. If what you want to copy is pure white, then just draw the contour, filled with white colour (the function to do that is `cv2.drawContours`). Otherwise, use that filled contour as a mask to copy the matching contents of the original image. – Dan Mašek Nov 23 '18 at 22:45
  • 1
    BTW, even if your original threshold image was originally binary (having only 0s and 255s), having saved it in JPEG format, you've introduced a lot of different values (due to the lossy nature and the way JPEG works). As such, you should at least re-do the thresholding operation in the script, or better, use a lossless format such as PNG to store the data. – Dan Mašek Nov 23 '18 at 22:50
  • What do you consider the area of a contour/blob to be? The number of pixels that are white? If so, then `cv2.contourArea` is not the function to use (and the [documentation](https://docs.opencv.org/2.4/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html#double%20contourArea(InputArray%20contour,%20bool%20oriented)) mentions this). For blobs this small, you will definitely get odd results. – Dan Mašek Nov 23 '18 at 23:02

1 Answers1

1

Here is one of the method you can use to achieve your goal. Explanations are provided in the comments of the code

import numpy as np
import cv2

ref_img = cv2.imread('threshold.jpg', 0)


img, cnts,_ = cv2.findContours(ref_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
mask = np.zeros(ref_img.shape, dtype="uint8")
for c in cnts:
   # Get the bounding rect surrounding your blobs
   x,y,w,h = cv2.boundingRect(c) 

   # Calculating the area of the rect is similar to the area of the blob minus the complexity
   area = w*h

   # For box area bigger than one, copy the information from the source image to the mask. 
   # Since the bounding box contains all the relevant information, just copy the entire box to the mask.
   if int(area) > 1 :
    mask[y:y+h,x:x+w] = ref_img[y:y+h,x:x+w]




cv2.imshow('img', mask)
cv2.waitKey(0)
yapws87
  • 1,809
  • 7
  • 16