I have sign (signs with arbitrary shape) images with white background and I want to get an image of the sign with transparent background.
I have managed to create a mask and apply it to the image and thought making the mask transparent would be doable. I searched a lot here and elsewhere, but nothing really helped me.
import cv2
import numpy as npfile_name = "/path/to/input/img/Unbenannt.jpg" # can be also .pngimg = cv2.imread(file_name)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
th, threshed = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
morphed = cv2.morphologyEx(threshed, cv2.MORPH_CLOSE, kernel)_, roi, _ = cv2.findContours(morphed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)mask = np.zeros(img.shape, img.dtype)cv2.fillPoly(mask, roi, (255,)*img.shape[2], )masked_image = cv2.bitwise_and(img, mask)cv2.imwrite("/path/to/output/mask_test.png", masked_image)
Input:
Current Output:
As already mentioned I want to make the background transparent.
Help is highly appreciated.
I found that I have to convert the image to BGRA to get a transparent background. I have also added a method to cut the image to its bounding rectangle. As promised, the working code:
import cv2
import numpy as npfile_name = "/path/to/img.png"def cut(img):# crop imagegray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)th, threshed = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))morphed = cv2.morphologyEx(threshed, cv2.MORPH_CLOSE, kernel)_, cnts, _ = cv2.findContours(morphed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)cnt = sorted(cnts, key=cv2.contourArea)[-1]x,y,w,h = cv2.boundingRect(cnt)new_img = img[y:y+h, x:x+w]return new_img def transBg(img): gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)th, threshed = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))morphed = cv2.morphologyEx(threshed, cv2.MORPH_CLOSE, kernel)_, roi, _ = cv2.findContours(morphed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)mask = np.zeros(img.shape, img.dtype)cv2.fillPoly(mask, roi, (255,)*img.shape[2], )masked_image = cv2.bitwise_and(img, mask)return masked_imagedef fourChannels(img):height, width, channels = img.shapeif channels < 4:new_img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)return new_imgreturn imgs_img = cv2.imread(file_name, -1)# set to 4 channels
s_img = fourChannels(s_img)# remove white background
s_img = cut(s_img)# set background transparent
s_img = transBg(s_img)cv2.imwrite("/path/to/store/img.png", s_img)
input is:
output is an image with transparent background: