PIL 的 fromarray() 函数中的动态范围(位深度)?



我对来自12位相机的多帧TIFF图像进行了一些图像处理,并希望保存输出。但是,PIL文档没有列出fromarray()的12位模式。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()

根据我的经验,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图像对象,你就可以开始了:

img = Image.fromarray(arr)

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

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

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

相关内容

  • 没有找到相关文章

最新更新