在白色背景上保存透明PNG为JPEG

3

假设我有一张 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。

2个回答

3

我认为你更需要的是渐变透明融合而不是Fred的回答中展示的简单阈值透明。

我制作了一个带有透明度渐变的样本图像进行测试。这是一个正常的图像,并在一个像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)

在黑色背景上的效果如下:

enter image description here

在白色背景上的效果如下:

enter image description here

关键词: 图像处理,Python,OpenCV,alpha通道,alpha混合,alpha合成,叠加。


我该如何为你在我的另一个问题上提供的优秀答案授予赏金?https://dev59.com/mFIG5IYBdhLWcg3wggA2 - Pono
1
@Pono 没关系,我不太担心分数 - 我只是喜欢帮助人们。很高兴它对你有用。 - Mark Setchell

1
在Python的OpenCV和Numpy中,你可以将图像的alpha通道分离出来。所以如果imgA是带有alpha通道的图片。那么可以将rgb图像(img)和alpha通道(alpha)分开。
img = imgA[:,:,0:3]
alpha = imgA[:,:,3]

然后将alpha为黑色的图像颜色设置为白色。
img[alpha == 0] = (255,255,255)


谢谢您的回答,但不幸的是,这并没有按预期工作。它只会用白色替换完全透明的像素。那么像半透明值127怎么办?我正在寻找一种解决方案,可以将半透明PNG完美地混合到白色画布上。 - Pono
你的问题不是很清楚。你想让半透明像素完全变成白色吗?如果不是,它们应该是什么颜色 -- 比例上是灰色的吗? - fmw42

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接