自动构建以零值为中心的色图

9
我经常想绘制一个范围从某个负数到某个正数的差异图像。问题在于Matlab的色图只能从最小值到最大值进行缩放,但并不关心某些中间值(本例中为零)。例如,我使用单个像素点生成了peaks图像:

enter image description here

其中原始图像如下所示:

enter image description here

因此,顶部图像的零值为蓝色,底部为绿色...(以jet色图为例)

我想建立一个自动将零值表示为相同颜色的色图,无论最小\最大值是什么。该怎么做?


我认为你可以通过将所有内容缩放到绘图之前的固定间隔(例如[-1,1])来实现。 - Marc Claesen
使用色图编辑器:http://www.mathworks.de/de/help/matlab/ref/colormapeditor.html 在那里解释了如何将绿色聚焦于零。 - Enno
Robocob特别要求自动实现,这样他就不需要每次打开色彩地图编辑器了... - bla
你可以使用 caxis 函数来控制颜色映射,通过使用以零为中心的范围,这样 0 就始终在中间(假设你正在使用缩放的颜色映射而不是直接映射)。 - Amro
3个回答

9

使用caxis函数(可设置当前坐标轴对象的CLim属性)可以控制颜色映射。前提是使用了缩放的颜色映射,而不是直接颜色映射(请查看CDataMapping属性)。通过使用以零为中心的范围作为输入,您可以确保始终将零放在中间。

这里是一个例子:

load penny
P = 4*(P./255) - 1;        %# not centered around zero
imagesc(P), axis image off
colormap(lbmap(64,'BrownBlue')), colorbar

现在我们调整颜色映射,使其围绕零点对称:

skewed_range

c = max(abs([min(P(:)),max(P(:))]));
caxis([-c c])

对称范围

请注意,我使用的是Light Bartlein颜色方案,这是一种设计为突出两个极端之间差异的发散调色板。

如果原始范围非常倾斜,您可能希望重新采样颜色映射,在过度拉伸的子范围内给它更多值。


谢谢Amro,但如果我理解正确,使用这个假设我需要将我的色图中心设置为零,而大多数情况下,上限和下限不对称。所以处理它的方法是在绝对值较大的限制上设置限制,我猜。 - user2212608
是的,我假设这对你适用...毕竟有很多应用程序中零值具有重要意义(例如显示海平面为零的地形图)。最简单的方法是使用以零为中心的颜色范围,配合适当的对称色图,并让MATLAB进行缩放。另一种方法是逐段构建它,每个部分都是两个端点之间的线性映射,这样您可以拥有尽可能多的“节点”(类似于上面提到的colormapeditor)。 - Amro
c = max(abs((P(:)))); 就足够了。 - wsdzbm

4
您可以使用FEX中的此工具,它生成了蓝色-白色-红色的色图,其中零始终对应于白色。如果您想要包含两种以上的颜色,请深入研究代码并根据需求进行调整。
在FEX中还有一些类似的选项(这是一个,以及另一个)。图片如下: enter image description here

3

我喜欢其他答案,特别是@Amro的答案。但它看起来很复杂 :) 而且你的参数不需要依赖于你的输入,你可以直接从轴上获取它们。所有这些都可以成为一个一行代码:

a = gca; % or whatever you use to access your axis handle
a.CLim = max(abs(a.CLim)) * [-1 1];

就是这样。这适用于MATLAB R2014b及以上版本,该版本具有新的图形句柄系统(详见此处)。在早期版本中(以及您喜欢的新版本中),您将使用以下方法:

a = gca; % or whatever you use to access your axis handle
set(a, 'CLim', max(abs(get(a, 'CLim'))) * [-1 1]);

或者使用caxis。
a = gca; % or whatever you use to access your axis handle
caxis(a, max(abs(caxis(a))) * [-1 1]);

自动化这个过程也相当容易:
a = gca; % or whatever you use to access your axis handle
addlistener(a, 'CLimMode', 'PostSet', @(h, e) caxis(e.AffectedObject, max(abs(caxis(e.AffectedObject))) * [-1 1]));

这使您可以这样做。

for ii = -5 : 5
    imagesc([-1 0 10^ii]);
    pause(0.2);
end

中间的条纹(代表0)始终是彩条的中间颜色。


2
感谢addlistener。我不知道它的存在,但它似乎非常有用。 - Scz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接