如何在opencv-python中创建透明遮罩
How to create a transparent mask in opencv-python
我有白色背景的标志(任意形状的标志)图像,我想获得透明背景的标志图像。
我已经设法创建了一个蒙版并将其应用到图像上,我认为使蒙版透明是可行的。我在这里和其他地方进行了很多搜索,但没有任何帮助。
import cv2
import numpy as np
file_name = "/path/to/input/img/Unbenannt.jpg" # can be also .png
img = 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)
输入:
当前输出:
如前所述,我想让背景透明。
非常感谢您的帮助。
我发现我必须将图像转换为 BGRA 才能获得透明背景。我还添加了一种将图像剪切到其边界矩形的方法。正如承诺的那样,工作代码:
import cv2
import numpy as np
file_name = "/path/to/img.png"
def cut(img):
# crop image
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)
_, 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_image
def fourChannels(img):
height, width, channels = img.shape
if channels < 4:
new_img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
return new_img
return img
s_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)
输入是:
输出的是透明背景的图片:
对于较新的 OpenCV 版本
import cv2
import numpy as np
file_name = "/path/to/img.png"
def cut(img):
# crop image
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)
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_image
def fourChannels(img):
height, width, channels = img.shape
if channels < 4:
new_img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
return new_img
return img
s_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)
我有白色背景的标志(任意形状的标志)图像,我想获得透明背景的标志图像。
我已经设法创建了一个蒙版并将其应用到图像上,我认为使蒙版透明是可行的。我在这里和其他地方进行了很多搜索,但没有任何帮助。
import cv2
import numpy as np
file_name = "/path/to/input/img/Unbenannt.jpg" # can be also .png
img = 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)
输入:
当前输出:
如前所述,我想让背景透明。
非常感谢您的帮助。
我发现我必须将图像转换为 BGRA 才能获得透明背景。我还添加了一种将图像剪切到其边界矩形的方法。正如承诺的那样,工作代码:
import cv2
import numpy as np
file_name = "/path/to/img.png"
def cut(img):
# crop image
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)
_, 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_image
def fourChannels(img):
height, width, channels = img.shape
if channels < 4:
new_img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
return new_img
return img
s_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)
输入是:
输出的是透明背景的图片:
对于较新的 OpenCV 版本
import cv2
import numpy as np
file_name = "/path/to/img.png"
def cut(img):
# crop image
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)
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_image
def fourChannels(img):
height, width, channels = img.shape
if channels < 4:
new_img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
return new_img
return img
s_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)