【问题标题】:Saving transparent PNG as JPEG on white background在白色背景上将透明 PNG 保存为 JPEG
【发布时间】:2020-11-26 21:58:27
【问题描述】:

假设我有一个 BGRA 图像 numpy 数组,看起来很像这样:

[[[233 228 230   128]
  [233 228 230   128]
  [233 228 230   0]
  ...
  [164 160 159   65]
  [199 197 196   65]
  [255 255 254   120]]

这看起来很简单 - 三个颜色通道 + 一个控制像素透明度的 alpha。将该 numpy 数组保存为 PNG 格式会导致图像应该是半透明的。

但是,当将其保存为 JPEG 时,Alpha 通道会被完全丢弃,并且所有像素都是完全不透明的。

由于 JPEG 不支持 alpha 透明度,我希望将我的半透明图像(上面的 numpy 数组)保存在白色背景上。这样一来,像素看起来仍然是半透明的。

如何将半透明的 numpy 数组覆盖在全白背景上?我主要使用 numpy 和 OpenCV。

【问题讨论】:

    标签: python numpy opencv


    【解决方案1】:

    我认为您正在寻找渐变 alpha 混合,而不是 Fred 的回答很好地展示的更简单的 alpha 阈值。

    出于测试目的,我制作了一个中间带有 alpha 渐变的示例图像。在这里,它是一张普通图像,并合成在棋盘上以显示透明度,就像 Photoshop 一样:

    要进行 alpha 混合,请使用以下公式:

    result = alpha * Foreground + (1-alpha)*Background
    

    其中的值都是在 0..1 范围内缩放的浮点数


    混合黑白背景的代码如下:

    #!/usr/bin/env python3
    
    import cv2
    import numpy as np
    
    # Load image, including gradient alpha layer
    im = cv2.imread('GradientAlpha.png', cv2.IMREAD_UNCHANGED)
    
    # Separate BGR channels from A, make everything float in range 0..1
    BGR = im[...,0:3].astype(np.float)/255
    A   = im[...,3].astype(np.float)/255
    
    # First, composite image over black background using:
    # result = alpha * Foreground + (1-alpha)*Background
    bg  = np.zeros_like(BGR).astype(np.float)     # black background
    fg  = A[...,np.newaxis]*BGR                   # new alpha-scaled foreground
    bg = (1-A[...,np.newaxis])*bg                 # new alpha-scaled background
    res = cv2.add(fg, bg)                         # sum of the parts
    res = (res*255).astype(np.uint8)              # scaled back up
    cv2.imwrite('OverBlack.png', res)
    
    # Now, composite image over white background
    bg  = np.zeros_like(BGR).astype(np.float)+1   # white background
    fg  = A[...,np.newaxis]*BGR                   # new alpha-scaled foreground
    bg = (1-A[...,np.newaxis])*bg                 # new alpha-scaled background
    res = cv2.add(fg, bg)                         # sum of the parts
    res = (res*255).astype(np.uint8)              # scaled back up
    cv2.imwrite('OverWhite.png', res)
    

    这给了这个黑色:

    而且这个是白色的:

    关键词:图像处理、Python、OpenCV、alpha、alpha blending、alpha compositing、overlay。

    【讨论】:

    • 我怎样才能赏金你对我的另一个问题的出色回答? stackoverflow.com/questions/64874129/…
    • @Pono 没关系,我并不太担心分数 - 我只是喜欢帮助人们。很高兴它对你有用。
    【解决方案2】:

    在 Python OpenCV Numpy 中,您可以将 alpha 通道与图像分离。因此,如果 imgA 是具有 alpha 通道的图像。然后分离rgb图像(img)和alpha通道(alpha)

    img = imgA[:,:,0:3]
    alpha = imgA[:,:,3]
    

    然后将img的颜色设置为白色,其中alpha为黑色

    img[alpha == 0] = (255,255,255)
    

    【讨论】:

    • 感谢您的回答,但不幸的是,这不能按预期工作。它只用白色替换 完全透明 像素。像 127(半透明)这样的 alpha 值呢?我正在寻找一种可以将完全半透明的 PNG 混合到白色画布上的解决方案。
    • 你的问题不是很清楚。你想让半透明像素全白吗?如果不是,它们应该是什么颜色——成比例的灰色?
    猜你喜欢
    • 2015-06-22
    • 2017-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    • 2014-10-05
    • 2013-07-26
    相关资源
    最近更新 更多