I want to automatically remove the background from images using OpenCV. The code I use generally works well, but for some images with similar background color to the foreground (e.g. white images with gray shadows on gray background), the code also removes that section of the image. For example, for this image:
I get the following result:
This is the code I use (source):
img = cv2.imread(imgpath)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3,3), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
thresh = 255 - thresh
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, borderType=cv2.BORDER_CONSTANT, borderValue=0)
contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
sorted_contour = sorted(contours, key=cv2.contourArea, reverse=True)
contour = np.zeros_like(gray)
cv2.drawContours(contour, [sorted_contour[0]], 0, 255, -1)
if len(sorted_contour) > 1:
cv2.drawContours(contour, [sorted_contour[1]], 0, 255, -1)
blur = cv2.GaussianBlur(contour, (5,5), sigmaX=0, sigmaY=0, borderType = cv2.BORDER_DEFAULT)
mask = skimage.exposure.rescale_intensity(blur, in_range=(127.5,255), out_range=(0,255))
result = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
result[:,:,3] = mask
Any idea on how to modify the code so that it includes the "holes" in the dress, or to "patch up" the mask automatically? Thanks in advance.