matplotlib imshow使用colormap或RGB数组显示不同

17 投票
2 回答
18288 浏览
提问于 2025-04-18 13:15

我遇到了一个问题:我正在用显微镜保存16位的tiff图像,现在需要对这些图像进行分析。我想用numpy和matplotlib来处理这些图像,但当我想简单地把图像显示成绿色时(之后我还需要叠加其他图像),却失败了。

下面是我尝试将图像作为RGB数组或使用默认的jet颜色映射时的一个例子。

import numpy as np
import matplotlib.pyplot as plt
import cv2

imageName = 'image.tif'

# image as luminance 
img1 = cv2.imread(imageName,-1)

# image as RGB array
shape = (img1.shape[0], img1.shape[1], 3)
img2 = np.zeros(shape,dtype='uint16')
img2[...,1] += img1

fig = plt.figure(figsize=(20,8))
ax1 = fig.add_subplot(1,2,1)
ax2 = fig.add_subplot(1,2,2)

im1 = ax1.imshow(img1,interpolation='none')
im2 = ax2.imshow(img2,interpolation='none')
fig.show()

这让我得到了如下的图像:enter image description here

如果这个问题太基础,我很抱歉,但我真的不知道为什么右边的图像会出现这些问题。我希望能用绿色的色调得到类似于左边图像的效果(imageJ也能得到类似左边的图像)。

非常感谢你的帮助。

2 个回答

0

我处理这个问题的方法是将图像进行归一化,也就是把它的值调整到一个标准范围内。根据DrV的说法,对于uint16这种数据类型,最大值是65535。这个辅助函数大概长这样:

def normalise_bits(img):
    bits = 1.0  # catch all
    try:
        # Test integer value, e.g. np.uint16
        bits = np.iinfo(img.dtype).max
    except ValueError:
        # Try float maximum, e.g. np.float32
        bits = np.finfo(img.dtype).max
    return (img / bits).astype(float)

这样处理后,图像就可以被matplotlib当作浮点数来使用,范围是[0.0, 1.0]。

40

我觉得正确的图像看起来更有艺术感...

matplotlib 在处理图像时有点复杂。大致流程如下:

  • 如果图像是一个 NxM 的数组,不管是什么类型,它会通过颜色映射来解释(如果没有特别说明,会自动缩放)。原则上,如果这个数组是一个 float 类型的数组,范围在 0 到 1 之间,它应该被解释为灰度图像。文档是这么说的,但实际上并不总是这样。

  • 如果图像是一个 NxMx3 的 float 数组,RGB 组件会被解释为 0 到 1 之间的 RGB 颜色。如果值超出了这个范围,会用正数取模 1,也就是说 1.2 会变成 0.2,-1.7 会变成 0.3,等等。

  • 如果图像是一个 NxMx3 的 uint8 数组,它会被解释为标准图像(0 到 255 的组件)。

  • 如果图像是 NxMx4 的数组,解释方式和上面一样,但第四个组件是透明度(alpha)。

所以,如果你给 matplotlib 一个包含其他整数类型的 NxMx3 数组(不是 uint8float),结果就不确定了。不过,通过查看源代码,可以理解这种奇怪的行为:

if A.dtype != np.uint8:
    A = (255*A).astype(np.uint8)

这里的 A 是图像数组。所以,如果你给它 uint16 值 0, 1, 2, 3, 4...,你会得到 0, 255, 254, 253, ... 是的,这看起来会很奇怪。(在我看来,解释可以更直观一些,但就是这样处理的。)


在这种情况下,最简单的解决办法是把数组除以 65535,这样图像就应该符合预期了。另外,如果你的原始图像确实是线性的,那么你还需要进行反伽马校正:

img1_corr = (img1 / 65535.)**(1/2.2)

否则你的中间色调会显得太暗。

撰写回答