Python OpenCV - 给RGB图像添加alpha通道

40

使用OpenCV在Python中将RGB图像转换为RGBA的最佳方法是什么?

假设我有一个形状为

(185, 198, 3) - it is RGB

如何将它们合并并保存到文件中?其中一个是形状为(185, 198)的阿尔法掩码。

6个回答

73

使用opencv3,这应该可以工作:

Python

# First create the image with alpha channel
rgba = cv2.cvtColor(rgb_data, cv2.COLOR_RGB2RGBA)

# Then assign the mask to the last channel of the image
rgba[:, :, 3] = alpha_data

C++

# First create the image with alpha channel
cv::cvtColor(rgb_data, rgba , cv::COLOR_RGB2RGBA);

# Split the image for access to alpha channel
std::vector<cv::Mat>channels(4);
cv::split(rgba, channels);

# Assign the mask to the last channel of the image
channels[3] = alpha_data;

# Finally concat channels for rgba image
cv::merge(channels, 4, rgba);

3
这个东西效果很棒。这个答案必须被采纳。 - Trect
@kaanoner python:有人能解释一下这是怎么工作的吗?我得到了意外的结果-3什么也没做,0-2产生了各种颜色,我不明白它应该如何工作。 - Ddefin Orsstt
cvtcolor函数在你的三通道RGB数据上创建了一个额外的通道用于Alpha层。然后,你可以通过选择这个新通道(使用 [:,:,3])来分配你的Alpha数据,Alpha数据只有一个通道。最终,你将得到一个四通道的RGBA图像,其中包含你的RGB和Alpha通道的组合。 - kaanoner
这是最简单的方法。 - Lewis Morris

44
你可以使用 cv2.merge() 将 alpha 通道添加到给定的 RGB 图像中,但首先您需要根据 文档 将 RGB 图像拆分为 R、G 和 B 通道:

Python: cv2.merge(mv[, dst])

  • mv – 要合并的输入数组或矩阵向量; mv 中的所有矩阵必须具有相同的大小和深度。
这可以通过以下方式完成:
b_channel, g_channel, r_channel = cv2.split(img)

alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 50 #creating a dummy alpha channel image.

img_BGRA = cv2.merge((b_channel, g_channel, r_channel, alpha_channel))

1
有时候我们可能需要执行 alpha_channel = alpha_channel.astype(np.uint8),即确保所有通道具有相同的数据类型。 - Minh Triet
4
这段代码意为:将RGB数据转换为RGBA数据,可使用cv2.cvtColor()函数,并选择转换方式为COLOR_RGB2RGBA。 - Trect

8

由于OpenCV图像只是Numpy数组,因此您可以使用一行代码完成此操作,使用Numpy快速高效。因此,这里是设置代码:

import numpy as np

# We'll synthesise a random image and a separate alpha channel full of 128 - semitransparent
im    = np.random.randint(0,256,(480,640,3), dtype=np.uint8)
alpha = np.full((480,640), 128, dtype=np.uint8)

这里的解决方案是将alpha通道堆叠到图像的"depth"轴上,使用dstack()函数实现:

result = np.dstack((im, alpha))

5

这是另一个使用Grabcut的简单示例,它有助于在将图像保存到磁盘与pyplot时获取正确的通道顺序。

from matplotlib import pyplot as plt
import numpy as np
import cv2

img = cv2.imread('image.jpg')

mask = np.zeros(img.shape[:2], np.uint8)
bgdModel = np.zeros((1,65), np.float64)
fgdModel = np.zeros((1,65), np.float64)
rect = (50, 50, 450, 290)

# Grabcut 
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)

r_channel, g_channel, b_channel = cv2.split(img) 
a_channel = np.where((mask==2)|(mask==0), 0, 255).astype('uint8')  

img_RGBA = cv2.merge((r_channel, g_channel, b_channel, a_channel))
cv2.imwrite("test.png", img_RGBA)

# Now for plot correct colors : 
img_BGRA = cv2.merge((b_channel, g_channel, r_channel, a_channel))

plt.imshow(img_BGRA), plt.colorbar(),plt.show()

4
import cv2
import numpy as np
import skimage.exposure



path_input_image="./input_image.png"


input_image = cv2.imread(path_input_image2, cv2.IMREAD_UNCHANGED)


input_image_alphachann = np.full((input_image.shape[0],input_image.shape[1]), 128, dtype=np.uint8)

output_image = np.dstack((input_image, input_image_alphachann))


print(input_image.shape)
print(output_image.shape)
#(400, 200, 3); 3 channell rgb
#(400, 200, 4); 4c channel rgba



print(input_image.dtype)
print(output_image.dtype)
# uint8




path_output_image=path_input_image+'.alpha.png'
cv2.imwrite(path_output_image, output_image)


4

我将在此发布我的C++答案,因为它可能对其他人有所帮助(已经有足够的Python答案):

  std::vector<cv::Mat> matChannels;
  cv::split(mat, matChannels);
  
  // create alpha channel
  cv::Mat alpha(...);
  matChannels.push_back(alpha);

  cv::merge(matChannels, dst);

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