将灰度二维 numpy 数组转换为 RGB 图像

Convert grayscale 2D numpy array to RGB image

我有一个灰度 'TIF' 图像,我将其读取为二维的 numpy 数组

我的二维阵列中的像素强度范围为 17 到 317。

我有两个挑战

  1. 将此二维数组转换为 RGB 图像

  2. 将像素强度(17 到 317 之间)缩放为 RGB 值并将灰度图像显示为 RGB 彩色图像

很遗憾,我无法使用 Opencv 和 Matplotlib,因为我工作的最终产品不支持这些

在我看来,您的问题有 3 个方面:

  • 正在创建颜色图或 LUT “查找 Table”
  • 将像素缩放到标准范围
  • 在没有 matplotlib 的情况下将颜色映射应用于图像。

因此,要创建颜色图,我们需要一个包含 256 个 RGB 值的列表,其中 我们可以查找任何灰度值并找到我们想要显示的颜色。我知道您不能在生产中使用 matplotlib,但您可以从其他机器上获取一两个颜色图并将其复制到您的生产机器上。那么,让我们这样做吧。我们将采用 viridis 颜色图:

#!/usr/bin/env python3

import numpy as np
from matplotlib import cm

# Get 256 entries from "viridis" or any other Matplotlib colormap
colmap = cm.get_cmap('viridis', 256)

# Make a Numpy array of the 256 RGB values
# Each line corresponds to an RGB colour for a greyscale level
np.savetxt('cmap.csv', (colmap.colors[...,0:3]*255).astype(np.uint8), fmt='%d', delimiter=',')

如果我们查看那个文件 "cmap.csv",它有 256 行并且开始是这样的:

68,1,84
68,2,85
68,3,87
69,5,88
69,6,90
69,8,91
70,9,92
...
...

这意味着我们在灰度图像中看到 0 的任何地方,实际上我们为像素 rgb(68,1,86) 着色。我们在灰度中看到 1 的任何地方都映射到 rgb(68,2,85)。大概你可以将该文件复制到你的生产机器上,你可以选择 Matplotlibs colormaps.

中的任何一个

关于缩放,您发布的是范围为 0..117 的 8 位 PNG 图像,而不是范围为 17..317 的 16 位 TIFF 图像,因此这不是最有帮助的。另外,你还没有说你打算如何在没有 OpenCVmatplotlib 的系统上读取 TIFF,所以我不知道知道您是否有 PIL/Pillow 或计划使用 tifffile.

然后,我将创建一个范围为 17..317 的虚拟 32x32 图像,如下所示:

grey = np.random.randint(17,318, (32,32))

看起来像这样:

array([[244,  75, 237, ..., 154, 190,  70],
       [286, 247, 158, ..., 150, 267, 124],
       [170, 305, 237, ..., 126, 111, 236],
       ...,
       [163, 292, 184, ...,  24, 253, 177],
       [314,  34,  36, ...,  87, 316, 182],
       [258, 153, 278, ..., 189,  57, 196]])

如果我们现在想将其从 17..317 范围缩放到 0..255 范围内,我们可以使用:

rescaled = ((grey.astype(float) - grey.min())*255/(grey.max() - grey.min())).astype(np.uint8)

这给了我们这个:

array([[192,  49, 187, ..., 116, 147,  45],
       [228, 195, 119, ..., 113, 212,  90],
       [130, 244, 187, ...,  92,  79, 186],
       ...,
       [124, 233, 141, ...,   5, 200, 136],
       [252,  14,  16, ...,  59, 254, 140],
       [204, 115, 221, ..., 146,  34, 152]], dtype=uint8) 

可以通过加载包含我们的颜色图的 CSV 文件并从颜色图中获取相应的元素来完成查找,这些元素由 0...255 范围内的灰度值索引:

#!/usr/bin/env python3

import numpy as np
from PIL import Image

# Load image as greyscale and make into Numpy array
grey = np.array(Image.open('TdoGc.png').convert('L'))

# Load RGB LUT from CSV file
lut = np.loadtxt('cmap.csv', dtype=np.uint8, delimiter=',')

# Make output image, same height and width as grey image, but 3-channel RGB
result = np.zeros((*grey.shape,3), dtype=np.uint8)

# Take entries from RGB LUT according to greyscale values in image
np.take(lut, grey, axis=0, out=result)

# Save result
Image.fromarray(result).save('result.png')

如果您在阅读后将灰度图像缩放到完整范围,请使用此行:

grey = ((grey.astype(float) - grey.min())*255/(grey.max() - grey.min())).astype(np.uint8)

你会得到这个:


如果您想可视化您的颜色图,请将上面的行更改为如下所示:

grey = np.array(Image.open('TdoGc.png').convert('L'))

进入这个以便它生成渐变(斜坡)图像:

grey = np.repeat(np.arange(256,dtype=np.uint8).reshape(1,-1), 100, axis=0)

然后你可以看到你的颜色图:


快速处理没有 class 枚举颜色的变量的分段线性颜色图。因此,您可以像这样从 autumn 颜色图中制作 cmap.csv 文件:

import numpy as np
from matplotlib import cm

# Get "autumn" colourmap
colmap = cm.get_cmap('autumn')

# Save 256 RGB entries as CSV - one for each of grey levels 0..255
np.savetxt('cmap.csv', np.array([colmap(i/255)[:3] for i in range(256)]) * 255, fmt="%d", delimiter=',')