如何使用 python 将 3 张 TIFF 图像合并为 1 张 PNG 图片?

How to combine 3 TIFF images into 1 PNG image with python?

每个 RGB 颜色通道有 1 个 tif 图像,我想使用 python 将这 3 个图像组合成一个 RGB 图像,所有 3 个通道均为 png 格式。我已经尝试了几个使用 PIL 库的实验,但我无法得到它。

我上传了 3 张示例图片到 Google 驱动器 here。有人知道怎么做吗?

答案取决于您真正想要实现的目标...

如果您想准确合并 3 个通道,您可能应该使用 tifffile 模块来理解输入文件中的浮点值并在输出文件中准确表示它们。事实上,gdal 可能会更好,因为它理解文件中的 GeoTIFF 标签。 PIL 无法处理 RGB float32 图像。

如果你想要一些模糊地允许某种近似可视化的东西,如 PNG,你需要做一些工作来将你的值缩放到合理的(但不准确),因为 PNG 不能像你的图像包含的那样表示浮点数据.


这是您的频道与 tifffile 更准确的合并:

from tifffile import imread, imwrite
import numpy as np

r = imread('r.tif')
g = imread('g.tif')
b = imread('b.tif')
RGB = np.dstack((r,g,b))
imwrite('result.tif', RGB)

使用 PIL,您将使用 Image.merge(),但您的数据是浮动的,因此您需要先将其转换为 uint8/uint16 才能获得可以存储在 PNG 中的内容:

from PIL import Image
import numpy as np

# Open images
red   = Image.open('red_channel.tif')
green = Image.open('green_channel.tif')
blue  = Image.open('blue_channel.tif')

# Convert PIL Images to Numpy arrays
npRed   = np.array(red)
npGreen = np.array(green)
npBlue  = np.array(blue)

# Get rid of the pesky -3.4e+38 marker for out-of-bounds pixels
npRed[npRed < 0]     = 0
npBlue[npBlue < 0]   = 0
npGreen[npGreen < 0] = 0

# Find maximum across all channels for scaling
max = np.max([npRed,npGreen,npBlue])

# Scale all channels equally to range 0..255 to fit in a PNG (could use 65,535 and np.uint16 instead)
R = (npRed * 255/max).astype(np.uint8)
G = (npGreen * 255/max).astype(np.uint8)
B = (npBlue * 255/max).astype(np.uint8)

# Build a PNG
RGB = np.dstack((R,G,B))
Image.fromarray(RGB).save('result.png')