2

我对来自 12 位相机的多帧 TIFF 图像进行了一些图像处理,并希望保存输出。但是,PIL 文档没有列出fromarray(). PIL 如何处理位深度以及如何确保保存的 TIFF 图像与原始图像具有相同的动态范围?

示例代码:

import os

import numpy as np
import matplotlib.pyplot as plt

from PIL import Image


# Read image file names
pathname = '/home/user/images/'
filenameList = [filename for filename in os.listdir(pathname)
                if filename.endswith(('.tif', '.TIF', '.tiff', '.TIFF'))]

# Open image files, average over all frames, save averaged image files
for filename in filenameList:
    img = Image.open(pathname + filename)
    X, Y = img.size
    NFrames = img.n_frames

    imgArray = np.zeros((Y, X))
    for i in range(NFrames):
        img.seek(i)
        imgArray += np.array(img)
        i += 1
    imgArrayAverage = imgArray/NFrames

    imgAverage = Image.fromarray(imgArrayAverage)    # <=== THIS!!!
    imgAverage.save(pathname + filename.rsplit('.')[0] + '.tif')

    img.close()
4

1 回答 1

0

以我的经验,12 位图像以 16 位图像打开,前四个 MSB 全为零。我的解决方案是使用将图像转换为 numpy 数组

arr = np.array(img).astype(np.uint16)

astype() 指令可能不是绝对必要的,但它似乎是个好主意。然后转换为 16 位,将二进制数字左移四位:

arr = np.multiply(arr,2**4)

如果您想改用 8 位,

arr = np.floor(np.divide(arr,2**4)).astype(np.uint8)

这里 astype() 是强制转换为 8 位整数所必需的。我认为 8 位截断隐式执行 floor() 函数,但我将其保留以防万一。

最后,转换回 PIL Image 对象,一切顺利:

img = Image.fromarray(arr)

对于您的特定用例,这将具有相同的效果:

imgAverage = Image.fromarray(imgarrayAverage.astype(np.uint16) * 2**4)

再次进行类型转换可能不是必需的,但它可能会节省您的时间,因为将 imgArray 除以 NFrame 应该会隐式地产生浮点数组。如果您担心精度,可以省略它。

于 2021-01-09T15:44:43.630 回答