Facing problem while removing checkerboard pattern. I'm using cv2.Threshold but it selected unexpected pixels too (red marked) .
import cv2
import numpy as np
input = cv2.imread('image.png')
ret, logo_mask = cv2.threshold(input[:,:,0], 0, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
cv2.imshow(logo_mask)
Anyone can help?
CodePudding user response:
Getting perfect results that covers all cases is challenging.
The following solution assumes that the white checkerboard color is (255, 255, 255), and gray is (230, 230, 230).
Another assumptions is that the clusters with that specific colors in the other parts of the image are very small.
We may use the following stages:
- Find "white mask" and "gray mask" where color is (255, 255, 255) and (230, 230, 230).
- Create unified mask using bitwise or.
- Find contours, and remove small contours from the mask (assumed to be "noise").
Code sample:
import cv2
import numpy as np
input = cv2.imread('image.png')
white_mask = np.all(input == 255, 2).astype(np.uint8)*255 # cv2.inRange(input, (255, 255, 255), (255, 255, 255))
gray_mask = np.all(input == 230, 2).astype(np.uint8)*255 # gray_mask = cv2.inRange(input, (230, 230, 230), (230, 230, 230))
mask = cv2.bitwise_or(white_mask, gray_mask) # Create unified mask
ctns = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2] # Find contours
# Remove small contours from mask
for c in ctns:
area = cv2.contourArea(c) # Find the area of each contours
if (area < 10): # Ignore small contours (assume noise).
cv2.drawContours(mask, [c], 0, 0, -1)
mask = cv2.dilate(mask, np.ones((3, 3), np.uint8)) # Dilate the mask - "cosmetics"
output = cv2.copyTo(input, 255-mask) # Put black color in the masked part.
# Show images for testing
cv2.imshow('input', input)
cv2.imshow('mask', mask)
cv2.imshow('output', output)
cv2.waitKey()
cv2.destroyAllWindows()
In case there are large white areas or gray areas in the foreground part, the above solution may not work.
I thought of a process for finding only the areas that overlaps a boundary between white and gray rectangle.
It's not working, because there are small parts between the tree branches that are excluded.
The following code may give you inspirations:
import cv2
import numpy as np
input = cv2.imread('image.png')
#ret, logo_mask = cv2.threshold(input[:,:,0], 0, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
white_mask = np.all(input == 255, 2).astype(np.uint8)*255 # cv2.inRange(input, (255, 255, 255), (255, 255, 255))
gray_mask = np.all(input == 230, 2).astype(np.uint8)*255 # gray_mask = cv2.inRange(input, (230, 230, 230), (230, 230, 230))
cv2.imwrite('white_mask.png', white_mask)
cv2.imwrite('gray_mask.png', gray_mask)
# Apply opening for removing small clusters
opened_white_mask = cv2.morphologyEx(white_mask, cv2.MORPH_OPEN, np.ones((3, 3), np.uint8))
opened_gray_mask = cv2.morphologyEx(gray_mask, cv2.MORPH_OPEN, np.ones((3, 3), np.uint8))
cv2.imwrite('opened_white_mask.png', opened_white_mask)
cv2.imwrite('opened_gray_mask.png', opened_gray_mask)
white_mask_shell = cv2.dilate(opened_white_mask, np.ones((3, 3), np.uint8)) - opened_white_mask # Dilate white_mask and keep only the "shell"
gray_mask_shell = cv2.dilate(opened_gray_mask, np.ones((3, 3), np.uint8)) - opened_gray_mask # Dilate gray_mask and keep only the "shell"
white_mask_shell = cv2.dilate(white_mask_shell, np.ones((3, 3), np.uint8)) # Dilate the "shell"
gray_mask_shell = cv2.dilate(gray_mask_shell, np.ones((3, 3), np.uint8)) # Dilate the "shell"
cv2.imwrite('white_mask_shell.png', white_mask_shell)
cv2.imwrite('gray_mask_shell.png', gray_mask_shell)
overlap_shell = cv2.bitwise_and(white_mask_shell, gray_mask_shell)
cv2.imwrite('overlap_shell.png', overlap_shell)
dilated_overlap_shell = cv2.dilate(overlap_shell, np.ones((17, 17), np.uint8))
mask = cv2.bitwise_or(cv2.bitwise_and(white_mask, dilated_overlap_shell), cv2.bitwise_and(gray_mask, dilated_overlap_shell))
cv2.imshow('input', input)
cv2.imshow('white_mask', white_mask)
cv2.imshow('gray_mask', gray_mask)
cv2.imshow('white_mask', white_mask)
cv2.imshow('gray_mask', gray_mask)
cv2.imshow('opened_white_mask', opened_white_mask)
cv2.imshow('opened_gray_mask', opened_gray_mask)
cv2.imshow('overlap_shell', overlap_shell)
cv2.imshow('dilated_overlap_shell', dilated_overlap_shell)
cv2.imshow('mask', mask)
cv2.waitKey()
cv2.destroyAllWindows()