本文提供了一个Python脚本,用于将波长光谱映射到颜色的表示形式。
没有独特的方法来做到这一点,但这里使用的公式是基于色彩匹配函数(CIE, colour matching functions), $x(\lambda), y(\lambda)$ 和 $z(\lambda)$。 这些模型通过映射波长的能量光谱 $P(\lambda)$ 映射为三原色 $X, Y, Z$ 来模拟 “standard observer” 的 chromatic response, 类似于人眼中三种视锥细胞的实际响应。
\(X = \int P(\lambda) x(\lambda)d\lambda\) \(Y = \int P(\lambda) y(\lambda)d\lambda\) \(Z = \int P(\lambda)z(\lambda)d\lambda\)
X、Y 和 Z 可以通过除以它们的总和来归一化(以失去有关光亮度的信息为代价):
\[x = \frac{X}{X+Y+Z}, \quad y = \frac{Y}{X + Y + Z}, \quad z = \frac{Z}{X + Y + Z} = 1 - x - y\]这样,只需要两个参数,x 和 y 来描述光的颜色(更准确地说,色度)。CIE标准色度图如下所示。
通过显示设备将(x,y)进一步转换为 RGB 值以输出,需要通过适当的色度矩阵进行转换。从几何上讲,这将上述颜色“舌头”中的点映射到 RGB “色域”内的点子集,即所示的三角形区域。颜色系统可以由三个原色色度(三角形的顶点)和一个白点组成的矩阵来定义:一组色度坐标为某种目的定义了“颜色”白色。
因此,将(x,y,z)值的向量乘以该矩阵的倒数,给出描述所用系统中相应颜色的 RGB 值。
将波长映射为 XYZ 色彩空间, 再将 XYZ 色彩空间映射为 sRGB 色彩空间
将波长映射为 XYZ 色彩空间, 再将 XYZ 色彩空间映射为 sRGB 色彩空间, 最后将 sRGB 色彩空间对应到灰度图上, 生成 colormap。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import numpy as np
from PIL import ImageCms, Image
from scipy.interpolate import interp1d
from colormath.color_objects import sRGBColor, XYZColor
from colormath.color_conversions import convert_color
class ColorMatchFunc:
def __init__(self):
self.cmf = np.loadtxt("cmf.txt", usecols=(0, 1, 2, 3))
lams, Xs, Ys, Zs = self.cmf[:, 0], self.cmf[:, 1], self.cmf[:, 2], self.cmf[:, 3]
self.f = interp1d(lams, np.column_stack((Xs, Ys, Zs)), kind='linear', fill_value=(0,0,0), bounds_error=False, axis=0)
def spec2srgb(self, lam):
XYZ = self.f(lam)
xyz = XYZColor(*XYZ)
sRGB = convert_color(xyz, sRGBColor).get_value_tuple()
return sRGB
def __call__(self, lam):
srgb = self.spec2srgb(lam)
srgb = np.kron(np.ones((3, 1)), srgb)
gray = np.arange(0., 1., 1/256.)[:, None].repeat(3, axis=1)
cmM = np.dot(gray, srgb)
cmM = cmM / np.max(cmM)
return cmM
应用 colormap (matplotlib)
1
2
3
4
5
6
7
8
9
10
from scipy import io as sio
import matplotlib.colors as mcolors
hsi = sio.loadmat("./TSA_simu_data/Truth/scene01.mat")['img']
cmap_name = 'CustomColormap'
cm = mcolors.LinearSegmentedColormap.from_list(cmap_name, list(cmap), N=len(cmap))
mapped_img = cm(hsi[:, :, 0])
plt.imshow(mapped_img)
Reference
-
Previous
【深度学习】注册机制不能很好地扩展 -
Next
【Research & Writing】CVPR 2023 Presenter and Virtual Platform Upload REMINDER