I am trying to remove the checkered background (which represents transparent background in Adobe Illustrator and Photoshop) with transparent color (alpha channel) in some PNGs with Python script.
First, I use template matching:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img_rgb = cv2.imread('testimages/fake1.png', cv2.IMREAD_UNCHANGED)
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('pattern.png', 0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where( res >= threshold)
for pt in zip(*loc[::-1]):
if len(img_rgb[0][0]) == 3:
# add alpha channel
rgba = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2RGBA)
rgba[:, :, 3] = 255 # default not transparent
img_rgb = rgba
# replace the area with a transparent rectangle
cv2.rectangle(img_rgb, pt, (pt[0] w, pt[1] h), (255, 255, 255, 0), -1)
cv2.imwrite('result.png', img_rgb)
Source Image: fake1.png
Pattern Template: pattern.png
Output: result.png (the gray area is actually transparent; enlarge a bit for viewing easier)
I know this approach has problems, as the in some cases, the template cannot be identified fully, as part of the pattern is hidden by the graphics in the PNG image.
My question is: How can I match such a pattern perfectly using OpenCV? via FFT Filtering?
References:
-
import cv2 import numpy as np # read input img = cv2.imread("fake.png") # threshold on checks low = (230,230,230) high = (255,255,255) mask = cv2.inRange(img, low, high) # invert alpha alpha = 255 - mask # convert img to BGRA result = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA) result[:,:,3] = alpha # save output cv2.imwrite('fake_transparent.png', result) cv2.imshow('img', img) cv2.imshow('mask', mask) cv2.imshow('result', result) cv2.waitKey(0) cv2.destroyAllWindows()
Download the resulting image to see that it is actually transparent.
CodePudding user response:
since you're working on PNG's with transparent backgrounds, it would probably be equally viable to instead of trying to detect the checkered background, you try to extract the stuff that isn't checkered. This could probably be achieved using a color check on all pixels. You could use opencv's
inRange()
function. I'll link a StackOverflow link below that tries to detect dark spots on a image. Inrange example