来自数组的图像显示为灰色图像

Image fromarray is showing a greyed out image

我正在从相机中获取一个数组,对值进行阈值处理并想保存新图像。我正在使用 PIL.Image.fromarry() 将数组转换为图像,但我只看到灰色图像。图像在那里,因为当我导入另一个程序时,我可以看到我想要的东西。当我用 plt.show(data) 显示图像时,这就是我希望看到的图像。如何更改颜色值?

from flirpy.camera.lepton import Lepton
import matplotlib.pyplot as plt
import numpy as np
import cv2
from PIL import Image as im

camera = Lepton()

for i in range(5):
    image = camera.grab()
    cimage = np.around(image/100 - 273.15, 2)
    cimage = np.where(cimage < 20, 20, cimage)
    cimage = np.where(cimage > 30, 30, cimage)
    
    data = im.fromarray(cimage.astype(np.uint8),'L')
    data.save(f'test_{i:04}.png')
    plt.imshow(data)
    plt.show()

camera.close()

Matplotlib:

PIL:

Matplotlib 将颜色图应用于您的图像,并且在某些情况下还会将值缩放到完整的颜色范围。 PIL 不会那样做,所以如果你给它一个灰度图像(单通道),所有值都在 20..30 范围内,它会变成黑色,因为它真的期望值在 0..255 范围内,它也不会为您着色灰色。

以下是如何将 Matplotlib cmap 转换为调色板并将其推入 PIL Image:

#!/usr/bin/env python3

import matplotlib.pyplot as plt
from PIL import Image, ImageMath

def cmap2palette(cmapName='viridis'):
    """Convert a Matplotlib colormap to a PIL Palette"""
    cmap = plt.get_cmap(cmapName)
    palette = [int(x*255) for entry in cmap.colors for x in entry]
    return palette

# Generate a linear ramp
im = Image.linear_gradient('L')
im.save('DEBUG-ramp.png')            # just debug, not required

# Generate the viridis Matplotlib colourmap push into our PIL Image
pal = cmap2palette('viridis')
im.putpalette(pal)
im.save('DEBUG-viridis.png')

# Just for fun...

# Generate the inferno Matplotlib colourmap push into our PIL Image
pal = cmap2palette('inferno')
im.putpalette(pal)
im.save('DEBUG-inferno.png')


# Now with your image
im = Image.open('w9jUR.png')

# Contrast-stretch to full range
gMin, gMax = im.getextrema()
print(F'Greyscale min: {gMin}, greyscale max: {gMax}')
im = ImageMath.eval('int(255*(g-gMin)/(gMax-gMin))', g=im, gMin=gMin, gMax=gMax).convert('L')

# Generate the viridis Matplotlib colourmap push into our PIL Image
pal = cmap2palette('viridis')
im.putpalette(pal)
im.save('DEBUG-result.png')

将此作为输入灰度图像:

这是 viridisinferno 颜色图的结果:

另请注意,您不需要像这样将图像裁剪到 20..30 范围内 2 遍:

cimage = np.where(cimage < 20, 20, cimage)
cimage = np.where(cimage > 30, 30, cimage)

您应该可以使用 np.clip():

np.clip(cimage, 20, 30, out=cimage)

如果我们将上面的代码应用到您的图片: