'Opencv : How to remove rectangle black box without removing any other characters

I would like to remove a rectangle black box from the below image.

enter image description here

I do some preprocessing operation to keep the upper top of the image only. My problem with the rectangle in the middle of the image

This is the preprocessing operation I do on this image

gray = cv2.cvtColor(cropped_top, cv2.COLOR_BGR2GRAY)




binary = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 15, 2)


binary = cv2.fastNlMeansDenoising(binary, None, 65, 5, 21)


ret, thresh1 = cv2.threshold(binary, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

k = np.ones((4,4))
binary = cv2.morphologyEx(thresh1, cv2.MORPH_CLOSE, k)

This is the output till now

enter image description here

Here it appears 3 lines connected together. I have used cv2.findContours. But till now I failed to remove this rectangle. I know I am doing something wrong regarding contours.

Here is the code I used for detecting contours

_,binary = cv2.threshold(image, 150, 255, cv2.THRESH_BINARY)


# find external contours of all shapes
_,contours,_ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# create a mask for floodfill function, see documentation
h,w= image.shape
mask = np.zeros((h+2,w+2), np.uint8)

# determine which contour belongs to a square or rectangle
for cnt in contours:
    poly = cv2.approxPolyDP(cnt, 0.05*cv2.arcLength(cnt,True),True)
    if len(poly) == 4:
        # if the contour has 4 vertices then floodfill that contour with black color
        cnt = np.vstack(cnt).squeeze()
        _,binary,_,_ = cv2.floodFill(binary, mask, tuple(cnt[0]), 0)

how I can successfully remove this black rectangle without distorting letter Q



Solution 1:[1]

I used cv2.fillConvexPoly() rather than cv2.floodFill(). Why?

I first found the contour having the highest perimeter and stored its points in a variable. I then used cv2.fillConvexPoly() to fill the contour of having highest perimeter with any color (in this case black (0, 0, 0) ).

Code:

_, binary = cv2.threshold(im, 150, 255, cv2.THRESH_BINARY_INV)
cv2.imshow('binary', binary)

enter image description here

#--- taking a copy of the image above ---
b = binary.copy()

#--- finding contours ---
i, contours, hierarchy = cv2.findContours(binary.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

im2 = img.copy()
max_peri = 0         #--- variable to store the maximum perimeter
max_contour = 0      #--- variable to store the contour with maximum perimeter

# determine which contour belongs to a square or rectangle
for cnt in contours:
    peri = cv2.arcLength(cnt, True)
    print(peri)
    if peri > max_peri:
        max_peri = peri
        max_contour = cnt

#---- filling the particular contour with black ---
res = cv2.fillConvexPoly(b, max_contour, 0) 

cv2.imshow('res.jpg', res)

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jeru Luke