How to detect region of large # of white pixels using OpenCV?

chostDevil picture chostDevil · Apr 21, 2012 · Viewed 47k times · Source

I want to detect a logo inside an image in order to remove it. I have an idea which is to look for objects which have the big number of pixels then remove. Another idea is to loop through all the white pixels (I have inverted my image) and look for pixels which forms a large region and then remove this region. Is there any algorithm better that this one. Also which methods in OpenCV will help me to detect object of large pixels number.

Answer

Abid Rahman K picture Abid Rahman K · Apr 22, 2012

I have a method to do this. I don't know whether this method applicable to all, but it works good here.

Below is code ( in Python ):

First convert image to grayscale, resize image, apply threshold, and make a mask image of same size and type of that of resized grayscale image. (Mask image is just a black image)

import cv2
import numpy as np

img = cv2.imread('bus.png')
img = cv2.resize(img,(400,500))
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,gray = cv2.threshold(gray,127,255,0)
gray2 = gray.copy()
mask = np.zeros(gray.shape,np.uint8)

Now find contours in the threshold image. Filter the contour for area between 500 to 5000. It will be most probably a large white blob, obviously not letters. (Remember, this area is particular for this image. I dont know about your other images. You will have to find it yourself). Now draw this contour on the mask image filled with white color.

contours, hier = cv2.findContours(gray,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
    if 200<cv2.contourArea(cnt)<5000:
        cv2.drawContours(img,[cnt],0,(0,255,0),2)
        cv2.drawContours(mask,[cnt],0,255,-1)

Below is the detected contour image:

detected contour drawn on the input image

Next is the mask image:

New mask image

Now you invert image using cv2.bitwise_not function. There you have option for giving mask where we give our mask image so that function operates only on the area in input image where there is white in mask image.

cv2.bitwise_not(gray2,gray2,mask)

And finally show the image :

cv2.imshow('IMG',gray2)
cv2.waitKey(0)
cv2.destroyAllWindows()

And here is the result:

enter image description here


NOTE:

Above method is done to preserve "ORANGE" in white square. That is why some artifacts are there. If you don't want that orange also, it can be more accurate.

Just find the bounding rectangle for area-filtered contours and draw rectangle filled with black color.

Code :

import cv2
import numpy as np

img = cv2.imread('bus.png')
img = cv2.resize(img,(400,500))
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,gray = cv2.threshold(gray,127,255,0)
gray2 = gray.copy()

contours, hier = cv2.findContours(gray,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
    if 200<cv2.contourArea(cnt)<5000:
        (x,y,w,h) = cv2.boundingRect(cnt)
        cv2.rectangle(gray2,(x,y),(x+w,y+h),0,-1)

cv2.imshow('IMG',gray2)
cv2.waitKey(0)
cv2.destroyAllWindows()

Result :

detected bounding rects:

enter image description here

Then fillout those rectangles with black:

enter image description here

It is better than previous , of course if you don't want "ORANGE")