我想将图像(jpg / jpeg)的背景设为透明白色。
下面是将绿色背景转换为白色(正确识别人的边缘)的代码:输入图像至输出图像
def change_bg(img, bg=(255, 255, 255)):
# convert to hsv
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# threshold using inRange
range1 = (20, 80, 80)
range2 = (90, 255, 255)
mask = cv2.inRange(hsv, range1, range2)
mask = 255 - mask
# apply morphology opening to mask
kernel = np.ones((3, 3), np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_ERODE, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
# antialias mask
mask = cv2.GaussianBlur(mask, (0, 0), sigmaX=3, sigmaY=3, borderType=cv2.BORDER_DEFAULT)
mask = skimage.exposure.rescale_intensity(mask, in_range=(127.5, 255), out_range=(0, 255))
result = img.copy()
result[mask == 0] = bg
return result
使用下面的代码,我将jpeg图像转换为png,但是我看到一些不透明的白色像素:结果图像
def white_to_transe(image):
"""
@input: PIL image
@return:
"""
image = image.convert('RGBA')
# Transparency
newImage = []
for item in image.getdata():
if item[:3] == (255, 255, 255):
newImage.append((255, 255, 255, 0))
else:
newImage.append(item)
image.putdata(newImage)
print(image.mode, image.size)
return newImage
那么,如何获得干净的白色透明背景呢?
在white_to_transe
使用以下内容进行更新后,它可以工作,但是会影响白色像素,例如说白衬衫:
for item in image.getdata():
if item[0] > 240 and item[1] > 240 and item[2] > 240:
newImage.append((255, 255, 255, 0))
是否有可能我们不添加白色(全部为255),而是在change_bg
功能上添加了透明性?
您的方法可能有点不幸。在对遮罩进行抗锯齿时,您会得到范围内的值0 ... 255
,但只能进行设置result[mask == 0] = bg
(白色)。您无需考虑所有其他像素(逐渐地)也属于原始蒙版。因此,我将重新安排您的代码,并简单地将最终蒙版用作Alpha通道。我也是使用OpenCV做到的;从我的角度来看,使用附加的Pillow循环感觉有些麻烦。
那将是您的代码的修改摘录:
import cv2
import numpy as np
import skimage.exposure
img = cv2.imread('rmQRJIS.jpg')
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower = (40, 80, 80)
upper = (90, 255, 255)
mask = cv2.inRange(img_hsv, lower, upper)
mask = 255 - mask
kernel = np.ones((3, 3), np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_ERODE, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
# Use initial, binary mask to set background to white
result = img.copy()
result[mask == 0] = (255, 255, 255)
# Save image just for intermediate output
cv2.imwrite('output_no_trans.png', result)
# Use antialiased mask as final alpha channel for transparency
mask = cv2.GaussianBlur(mask, (0, 0), sigmaX=3, sigmaY=3, borderType=cv2.BORDER_DEFAULT)
mask = skimage.exposure.rescale_intensity(mask, in_range=(127.5, 255), out_range=(0, 255))
result = cv2.cvtColor(result, cv2.COLOR_BGR2BGRA)
result[:, :, 3] = mask
# Save final image
cv2.imwrite('output.png', result)
作为中间输出,我将背景设置为白色后保存了图像:
包括alpha通道的最终输出如下所示:
老实说,在这里几乎看不到差异,因为我必须在上传之前缩小输出图像的尺寸以保持PNG
兼容性。如果结果对您有利,请您自己查看完整图像!
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.16299-SP0
Python: 3.9.1
NumPy: 1.20.1
OpenCV: 4.5.1
scikit-image: 0.18.1
----------------------------------------
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句