下面的示例演示了一种简单的方法来撤消色图的“值 -> RGB”映射。
def unmap_nearest(img, rgb):
""" img is an image of shape [n, m, 3], and rgb is a colormap of shape [k, 3]. """
d = np.sum(np.abs(img[np.newaxis, ...] - rgb[:, np.newaxis, np.newaxis, :]), axis=-1)
i = np.argmin(d, axis=0)
return i / (rgb.shape[0] - 1)
此函数通过获取每个像素的RGB值,并在颜色映射中查找最佳匹配颜色的索引来工作。使用索引和广播技巧可以进行有效的向量化(以临时数组的内存消耗为代价):
img[np.newaxis, ...]
将图像从形状 [n, m, 3] 转换为 [1, n, m, 3]
rgb[:, np.newaxis, np.newaxis, :]
将色彩映射从形状 [k, 3] 转换为 [k, 1, 1, 3]。
- 减去结果数组会得到一个形状为 [k, n, m, 3] 的数组,其中包含每个颜色分量的每个色彩映射索引
k
和像素 n, m
之间的差异。
sum(abs(..), axis=-1)
取差值的绝对值,并对所有颜色分量(最后一维)求和,以获得所有像素和色彩映射条目之间的总差异(形状为 [k, n, m] 的数组)。
i = np.argmin(d, axis=0)
沿第一维找到最小元素的索引。结果是每个像素 [n, m] 的最佳匹配色彩映射条目的索引。
return i / (rgb.shape[0] - 1)
最后返回通过色彩映射大小归一化的索引,使结果在0-1范围内。
![enter image description here](https://istack.dev59.com/bKTQx.webp)
这种方法有一些注意事项:
- 它无法重建原始值范围。
- 它将所有像素视为颜色映射的一部分(即大陆轮廓也会被映射)。
- 如果使用错误的颜色映射,它将出现严重错误。
.
import numpy as np
import matplotlib.pyplot as plt
from skimage.color import rgb2gray
def unmap_nearest(img, rgb):
""" img is an image of shape [n, m, 3], and rgb is a colormap of shape [k, 3]. """
d = np.sum(np.abs(img[np.newaxis, ...] - rgb[:, np.newaxis, np.newaxis, :]), axis=-1)
i = np.argmin(d, axis=0)
return i / (rgb.shape[0] - 1)
cmap = plt.cm.jet
rgb = cmap(np.linspace(0, 1, cmap.N))[:, :3]
original = (np.arange(10)[:, None] + np.arange(10)[None, :])
plt.subplot(2, 2, 1)
plt.imshow(original, cmap='gray')
plt.colorbar()
plt.title('original')
plt.subplot(2, 2, 2)
rgb_img = cmap(original / 18)[..., :-1]
plt.imshow(rgb_img)
plt.title('color-mapped')
plt.subplot(2, 2, 3)
wrong = rgb2gray(rgb_img)
plt.imshow(wrong, cmap='gray')
plt.title('rgb2gray')
plt.subplot(2, 2, 4)
reconstructed = unmap_nearest(rgb_img, rgb)
plt.imshow(reconstructed, cmap='gray')
plt.colorbar()
plt.title('reconstructed')
plt.show()
jet
),那么可能可以创建一个从RGB到cmap值的反向查找表。 - MB-F