Home > front end >  How to replace a checked pattern in a PNG image with transparent in Python?
How to replace a checked pattern in a PNG image with transparent in Python?

Time:10-21

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

Source Image

Pattern Template: pattern.png

Pattern Template

Output: result.png (the gray area is actually transparent; enlarge a bit for viewing easier)

Output Image

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:

  • enter image description here

    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()
    

    enter image description here

    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

  • Related