首页 > 解决方案 > 如何在python中为uint16图像添加透明度(在opencv中使用connectedcomponents的上下文中)?

问题描述

使用 uint8、3 通道图像和 uint8 二进制掩码,我在 opencv 和 python 中完成了以下操作,以便将黑色背景上的对象更改为透明背景上的对象:

# Separate image into its 3 channels
b, g, r = cv2.split(img)
# Merge channels back with mask (resulting in a 4-channel image)
imgBGRA = cv2.merge((b, g, r, mask))

但是,当我尝试使用 uint16、3 通道图像和 uint16 二进制掩码执行此操作时,保存的结果是 4 通道,但背景仍然是黑色。(我将其保存为 .tiff 文件并在 Photoshop 中查看。)

如何使背景透明,保持输出图像 uint16?

更新

看到@Shamshirsaz.Navid 和@fmw42 的评论,我试过了 imgBGRA=cv2.cvtColor(imgBGR, cv2.COLOR_BGR2BGRA)。然后使用 Numpy 从掩码中添加 alpha 通道:imgBGRA[:,:,3]=mask. (我没有尝试过,因为我认为 cvtColor 操作需要 8 位图像。)尽管如此,我的结果是一样的。

我认为问题是我的面具。当我运行时numpy.amin(mask),我得到 0,而对于numpy.amax(mask),我得到 1。它们应该是什么?在使用拆分/合并技术之前,我尝试将蒙版乘以 255,但背景仍然是黑色。然后我尝试了 mask*65535,但背景又是黑色的。

我曾试图缩小我最初帖子的范围。但似乎我的问题确实存在于我正在做的事情以及如何创建这个 uint16 掩码的更大范围内。

我正在使用connectedComponentsWithStats(CC) 剪切 uint16 图像上的组件。CC 需要一个 8 位掩码,我将其用作 CC 的输入。但是剪切结果需要来自我的 uint16 原件。这需要对我学习在 uint8 图像上使用 CC 的方式进行一些更改。请注意,每个组件的掩码(我最终用来尝试使背景透明)被创建为 uint16。这是精简版:

# img is original image, dtype=uint16
# bin is binary mask, dtype=uint8
cc = cv2.connectedComponentsWithStats(bin, connectivity, cv2.CV_32S)
num_labels = cc[0]
labels = cc[1]
for i in range(1, num_labels):
    maskg = (labels == i).astype(np.uint16)   # with uint8: maskg = (labels == i).astype(np.uint8) * 255
    # NOTE: I don't understand why removing the `* 255` works; but after hours of experimenting, it's the only way I could get the original to appear correctly when saving 'glyph'; for all other methods I tried the colors were off in some significant way -- either grayish blue whereas the object in my original is variations of brown, or else a pixelated rainbow of colors)
    glyph = img * maskg[..., np.newaxis]      # with uint8: glyph = cv2.bitwise_and(img, img, mask=maskg)
    b, g, r = cv2.split(glyph)
    glyphBGRA = cv2.merge((b, g, r, maskg))

示例(我的真实原始图像很大,而且我无法分享它;所以我把这个例子放在一起)

img(原始 uint16 图像)

img(原始 uint16 图像

bin(输入 uint8 掩码)

bin(输入 uint8 掩码)

maskg(在循环中创建的 uint16 组件掩码) (这是截图——直接上传时显示为全黑)

maskg(在循环中创建的 uint16 组件掩码)

字形(应用了 maskg 的 img)

字形(应用了 maskg 的 img)

glyphBGRA(尝试添加透明度的拆分和合并方法的结果) (这也是一个屏幕截图——直接添加时这个屏幕显示为全白/空白)

glyphBGRA(尝试添加透明度的拆分和合并方法的结果)

我希望这个添加的信息为我的问题提供足够的背景。

标签: pythonimageopencvalpha-transparencyuint16

解决方案


我检查了你最后的评论。我认为一个例子可能会更好。您的代码是正确的;问题是,你是如何使用它的?我附上了一张图片和一个面具来测试它们。

import sys,cv2

main = cv2.imread(sys.path[0]+'/main.png')
mask = cv2.imread(sys.path[0]+'/mask.png', cv2.IMREAD_GRAYSCALE)
mask = cv2.threshold(mask, 127, 255, cv2.THRESH_BINARY)[1]

b, g, r = cv2.split(main)
bgra = cv2.merge((b, g, r, mask))
cv2.imwrite(sys.path[0]+'/out_split_merge.png',bgra)

主要的:
在此处输入图像描述

面具:
在此处输入图像描述

输出:
在此处输入图像描述

如果您使用图像编辑软件打开最终输出,您会注意到它的一部分是透明的。
在此处输入图像描述


推荐阅读