Skip to content
Advertisement

cv2.boundingRect creating issue

I am working on preprocessing images of digits. Each image contains a single number and some unwanted contours sample_1 sample_2.

This noise or contours can be in the form of lines or small dots. My task is to remove these contours. So I decided to use the following algorithm

  1. Find all contours

  2. Sort the contours according to the area in descending order

  3. Iterate through contours from index 2 to last

  4. create a boundingRect and fill that part of the image with 255

     cv2.findContours(image,  cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
     contours = sorted(contours, key = cv2.contourArea, reverse = True)
     for c in contours[2:]:
         (x, y, w, h) = cv2.boundingRect(c)
         image[y:y + h, x:x + w] = 255
    

Now the problem is that in case of first image boundingRect is returning (14,14,150,150) which covers the digit too. Now my question is that is there any better alternative to boundingRect so that only contour area can be replaced.

Output images were following:

Output_1 Output_2

Original image files are following

original 1 original 2

Advertisement

Answer

I’m able to achieve the desired output by these steps:

  1. Inverse the color of the image (Or change the retrieving method to RETR_INTERNAL while finding contours). White pixels have value of 1 and blacks have the value of 0, thus black contours can not be detected by RETR_EXTERNAL operation.

  2. Sort te contours according to area as you did

  3. Fill the contours starting from the second largest contour with white.

Code:

# Images I copied from here were not single channel, so convert to single channel to be able to find contours.
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Copy the original image to draw on it later on
img_copy = img.copy()

# Invert the color if using RETR_EXTERNAL
img = cv2.bitwise_not(img)

# Note that findContours function returns hierarchy as well as the contours in OpenCV4.x, in OpenCV3.x it used to return 3 values.
contours, hierarchy = cv2.findContours(img,  cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Sort the contours descending according to their area
contours = sorted(contours, key =lambda x: cv2.contourArea(x), reverse = True)

# Fill the detected contours starting from second largest
for c in contours[1:]:
    print(c)
    img_copy = cv2.fillPoly(img_copy, [c], color=(255,255,255))

Output: (Black bar between windows is my background)

enter image description here

Advertisement