I'm newbie in OpenCV. I want to remove the small triangles from the image blow. I have tried to use close morphology with a custom kernel, but it doesn't work.
Here is my kernel to recognize a pair of triangles. Because I want to keep the text unchanged, so I create kernel of the pair of triangles:
kernel = np.array([
[1,1,0,0,0,0],
[1,1,1,1,0,0],
[1,1,1,1,1,1],
[0,0,0,0,0,0],
[0,0,0,0,0,0],
[1,1,1,1,1,1],
[1,1,1,1,0,0],
[1,1,0,0,0,0]
], dtype=np.uint8)
src_img = cv2.imread("triangle_and_text.png")
gray = cv2.cvtColor(src_img, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV cv2.THRESH_OTSU)[1]
removed_triangles = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=1)
cv2.imwrite("removed_triangles.png", 255 - removed_triangles)
Where I'm wrong?
CodePudding user response:
import cv2
import sys
import numpy as np
pth = sys.path[0]
def removeTri():
# Load image
im = cv2.imread("%s/im.png" % pth)
# Make a gray version
im_thresh = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
# Make a black and white version
im_thresh = cv2.adaptiveThreshold(
im_thresh, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2
)
# Merge channels
im_thresh = cv2.merge((im_thresh, im_thresh, im_thresh))
# Remove small noise
im_thick = cv2.medianBlur(im_thresh, 9)
# Connect components
im_thick = cv2.erode(im_thick, np.ones((31, 31)))
# Draw a white border around shape to avoid errors in blob finding
cv2.rectangle(im_thick, (0, 0), im.shape[:2], (255, 255, 255), 10)
# To find each blob and size of each
im_out = im.copy()
im_thick = ~cv2.split(im_thick)[0]
cnts, _ = cv2.findContours(im_thick, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnts = list(cnts)
cnts.sort(
key=lambda p: max(cv2.boundingRect(p)[2], cv2.boundingRect(p)[3]), reverse=True
)
for cnt in cnts:
peri = cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, 0.02 * peri, True)
x, y, w, h = cv2.boundingRect(approx)
cv2.rectangle(im_out, (x, y), (x w, y h), (0, 255, 0), 2)
# Draw biggest blob in blue color
x, y, w, h = cv2.boundingRect(cnts[0])
cv2.rectangle(im_out, (x, y), (x w, y h), (255, 0, 0), 2)
# Make a mask of text area
mask = im_thick.copy()
mask[:] = 0
cv2.rectangle(mask, (x, y), (x w, y h), (255, 255, 255), -1)
# Extract the final text using mask
im_res=im.copy()
im_res[np.where(mask==0)]=(255,255,255)
# Save output image
im_thick = cv2.merge((im_thick, im_thick, im_thick))
mask = cv2.merge((mask, mask, mask))
top = np.hstack((im, im_thresh, im_thick))
btm = np.hstack((im_out, mask, im_res))
cv2.imwrite("%s/im_out.png" % pth, np.vstack((top, btm)))
if __name__ == "__main__":
removeTri()