【问题标题】:How to get transparent background from JPEG Image by converting to PNG?如何通过转换为 PNG 从 JPEG 图像中获取透明背景?
【发布时间】:2021-02-15 20:18:41
【问题描述】:

我想将图像 (jpg/jpeg) 的背景设为透明白色。

下面是我的代码,它将绿色背景转换为白色(正确识别人的边缘): Input imageOutput image

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,但我看到一些不透明的白色像素:Result image

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

是否有可能,我们在change_bg 函数中添加透明而不是白色(全部 255)?

【问题讨论】:

    标签: python-3.x opencv python-imaging-library


    【解决方案1】:

    你的方法可能有点不幸。对遮罩进行抗锯齿处理时,您会得到0 ... 255 范围内的值,但您只设置了result[mask == 0] = bg(白色)。您没有考虑所有其他像素,它们(逐渐)也属于原始蒙版。所以,我会重新安排你的代码,并简单地使用最终的掩码作为 alpha 通道。我也使用 OpenCV 做到了这一点;从我的角度来看,使用额外的 Pillow Loop 感觉有点麻烦。

    这将是您代码的修改摘录:

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

    【讨论】:

      猜你喜欢
      • 2019-03-19
      • 2011-04-23
      • 1970-01-01
      • 1970-01-01
      • 2010-12-14
      • 2013-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多