非线性缩放色图以增强对比度
以下这段Python代码可以创建一个热图,热图中包含的是正态分布的数值。
import numpy as np
from matplotlib import pylab as plt
np.random.seed(123) #make sure we all have same data
m = np.random.randn(200).reshape(10, 20)
plt.imshow(m, cmap='RdYlGn', interpolation='nearest')
plt.colorbar()
这是运行这段代码后得到的结果。
我想通过“淡化”接近零的数值来增强这个图像的对比度。 我可以通过对原始数据进行双曲正切缩放来轻松实现这一点,代码如下:
def disigmoidScaling(values, steepnessFactor=1, ref=None):
''' Sigmoid scaling in which values around a reference point are flattened
arround a reference point
Scaled value y is calculated as
y = sign(v - d)(1 - exp(-((x - d)/s)**2)))
where v is the original value, d is the referenc point and s is the
steepness factor
'''
if ref is None:
mn = np.min(values)
mx = np.max(values)
ref = mn + (mx - mn) / 2.0
sgn = np.sign(values - ref)
term1 = ((values - ref)/steepnessFactor) ** 2
term2 = np.exp(- term1)
term3 = 1.0 - term2
return sgn * term3
plt.imshow(disigmoidScaling(m, 4), cmap='RdYlGn', interpolation='nearest')
plt.colorbar()
这是新的输出结果。
我对这个结果很满意,但有一点让我不太高兴,就是在这个版本中,原始的数值被缩放后的数值替代了。
有没有办法可以对数值进行非线性映射,以便更好地应用到颜色图上呢?
1 个回答
4
一个颜色映射表就像一个字典,里面存储了红色、绿色和蓝色的值,这些值的范围在0到1之间。线性分段颜色映射的文档中给出了一个例子。
cdict = {'red': [(0.0, 0.0, 0.0),
(0.5, 1.0, 1.0),
(1.0, 1.0, 1.0)],
'green': [(0.0, 0.0, 0.0),
(0.25, 0.0, 0.0),
(0.75, 1.0, 1.0),
(1.0, 1.0, 1.0)],
'blue': [(0.0, 0.0, 0.0),
(0.5, 0.0, 0.0),
(1.0, 1.0, 1.0)]}
在这个例子中,表格中每种颜色的每一行都是一组(x, y0, y1)的元组。在每组中,x的值必须从0到1逐渐增加。对于任何在x[i]和x[i+1]之间的输入值z,输出的颜色值会在y1[i]和y0[i+1]之间线性插值,也就是说会根据这两个值之间的比例来计算。
比如,RdYlGn
这个颜色映射表有11个x值,从0到1.0,每隔0.1一个值。你可以通过调用
plt.cm.RdYlGn._segmentdata
来获取cdict
的值。然后你可以把x值改成你想要的任何步长(只要它们是逐渐增加的,并且在0到1之间),再通过调用matplotlib.colors.LinearSegmentedColormap
来生成一个新的颜色映射表。关于这方面有很多很好的例子,可以在Matplotlib Cookbook中找到。