具有多个比例的 Matlab 曲面图颜色图
Matlab surface plot colormap with multiple scales
我有以下跨越 [x,y]
域的示例数据集:
test=[2.58,2.2, 0.00023, 0.000163, 0.000123, 0.000164, 0.00022, 2.18, 2.56,2.56;
2.46,2.17, 0.00021, 0.000150, 0.000119, 0.000141, 0.00020, 2.16, 2.43, 2.56;
2.35,2.14, 0.00019, 0.000143, 0.000101, 0.000136, 0.00018, 2.14, 2.36,2.56;
2.23,2.12, 0.000184, 0.000138, 0.000095, 0.000124, 0.000166, 2.12, 2.24,2.56;
2.2,2.11, 0.000177, 0.000141, 0.00009, 0.000101, 0.000156, 2.09, 2.18, 2.56;
2.25,2.1, 0.000176, 0.000168, 0.00008, 0.000095, 0.000164, 2.08, 2.26, 2.56;
2.32,2.13, 0.000183, 0.000178, 0.000086, 0.000104, 0.000177, 2.11, 2.35,2.56;
2.44, 2.15, 0.00019, 0.000191, 0.000099, 0.000112, 0.000189, 2.13, 2.44,2.56;
2.56, 2.17,0.00021, 0.000199, 0.000101, 0.000132, 0.000199, 2.15, 2.52,2.56;
2.59, 2.19, 0.00022, 0.000209, 0.000118, 0.000144, 0.00021, 2.19,2.55, 2.56]
可以看到,边缘的数据比中间的数据高很多,即有两种不同的尺度。使用 Matlab 曲面图 (surf(test)
) 我可以选择关注边缘,通过在 2.6
上设置颜色图最大值,我得到:
Focus on the edges。
这很好地显示了边缘的局部差异,但看不到中间部分的差异。
或者,我可以通过将最大值设置为 0.00025
来关注中间,我得到:
Focus on the middle,
它显示了中间的局部差异,而不是边缘的差异。
我真的很想把两者结合起来。我经常使用 colormapeditor,但还没有找到令人满意的解决方案。
理想情况下,我会将颜色条分成两个区域,一个蓝色区域范围从 0
到 0.00023
(中间区域的最大值),第二个黄色区域范围从 0.00023
到2.59
(边缘区域的最大值)。
或者,可以将两张图片进行一些叠加(在 2D 中相当容易,但我也想在 3D 中这样做),但我更喜欢使用自定义颜色条来解决它。
有人知道怎么做吗?
您可以改为绘制数据日志,例如
surf(log(test))
caxis(log([min(test(:)) max(test(:))]));
colorbar_array = linspace(log(min(test(:))), log(max(test(:))), 5);
colorbar('FontSize',11,'YTick',colorbar_array,'YTickLabel',exp(colorbar_array));
编辑:您仍然需要 fiddle 使用颜色图编辑器,以解决数据范围上限的差异(黄色区域)。
您遇到的问题是高动态范围数据。这个一般没办法解决。
从高动态范围(HDR)摄影的角度来看,你要做的事情有一个名字:Tonemapping。关于如何解决这个问题没有简单的答案。按照 Amos 的建议对数据取对数,这是很好的第一步。这通常在查看高动态范围的信号频谱(例如图像的功率谱)时完成,由于功率谱和自然图像之间的统计联系,它更普遍地起作用。
第二种方法(很简单)是对图像应用 gamma-correction。这为您提供了一个可以调整的简单参数,对于一些二维数据就足够了。
正如您自己指出的那样,对数(或伽玛校正)通常不会根据需要重新缩放数据。这是色调映射仍然是一个开放研究领域的原因之一。
话虽如此,有全自动的方法,有一些是在 Matlab 中实现的。这是 I have never tried myself, but supported by mathworks.
我有以下跨越 [x,y]
域的示例数据集:
test=[2.58,2.2, 0.00023, 0.000163, 0.000123, 0.000164, 0.00022, 2.18, 2.56,2.56;
2.46,2.17, 0.00021, 0.000150, 0.000119, 0.000141, 0.00020, 2.16, 2.43, 2.56;
2.35,2.14, 0.00019, 0.000143, 0.000101, 0.000136, 0.00018, 2.14, 2.36,2.56;
2.23,2.12, 0.000184, 0.000138, 0.000095, 0.000124, 0.000166, 2.12, 2.24,2.56;
2.2,2.11, 0.000177, 0.000141, 0.00009, 0.000101, 0.000156, 2.09, 2.18, 2.56;
2.25,2.1, 0.000176, 0.000168, 0.00008, 0.000095, 0.000164, 2.08, 2.26, 2.56;
2.32,2.13, 0.000183, 0.000178, 0.000086, 0.000104, 0.000177, 2.11, 2.35,2.56;
2.44, 2.15, 0.00019, 0.000191, 0.000099, 0.000112, 0.000189, 2.13, 2.44,2.56;
2.56, 2.17,0.00021, 0.000199, 0.000101, 0.000132, 0.000199, 2.15, 2.52,2.56;
2.59, 2.19, 0.00022, 0.000209, 0.000118, 0.000144, 0.00021, 2.19,2.55, 2.56]
可以看到,边缘的数据比中间的数据高很多,即有两种不同的尺度。使用 Matlab 曲面图 (surf(test)
) 我可以选择关注边缘,通过在 2.6
上设置颜色图最大值,我得到:
Focus on the edges。
这很好地显示了边缘的局部差异,但看不到中间部分的差异。
或者,我可以通过将最大值设置为 0.00025
来关注中间,我得到:
Focus on the middle,
它显示了中间的局部差异,而不是边缘的差异。
我真的很想把两者结合起来。我经常使用 colormapeditor,但还没有找到令人满意的解决方案。
理想情况下,我会将颜色条分成两个区域,一个蓝色区域范围从 0
到 0.00023
(中间区域的最大值),第二个黄色区域范围从 0.00023
到2.59
(边缘区域的最大值)。
或者,可以将两张图片进行一些叠加(在 2D 中相当容易,但我也想在 3D 中这样做),但我更喜欢使用自定义颜色条来解决它。
有人知道怎么做吗?
您可以改为绘制数据日志,例如
surf(log(test))
caxis(log([min(test(:)) max(test(:))]));
colorbar_array = linspace(log(min(test(:))), log(max(test(:))), 5);
colorbar('FontSize',11,'YTick',colorbar_array,'YTickLabel',exp(colorbar_array));
编辑:您仍然需要 fiddle 使用颜色图编辑器,以解决数据范围上限的差异(黄色区域)。
您遇到的问题是高动态范围数据。这个一般没办法解决。
从高动态范围(HDR)摄影的角度来看,你要做的事情有一个名字:Tonemapping。关于如何解决这个问题没有简单的答案。按照 Amos 的建议对数据取对数,这是很好的第一步。这通常在查看高动态范围的信号频谱(例如图像的功率谱)时完成,由于功率谱和自然图像之间的统计联系,它更普遍地起作用。
第二种方法(很简单)是对图像应用 gamma-correction。这为您提供了一个可以调整的简单参数,对于一些二维数据就足够了。
正如您自己指出的那样,对数(或伽玛校正)通常不会根据需要重新缩放数据。这是色调映射仍然是一个开放研究领域的原因之一。
话虽如此,有全自动的方法,有一些是在 Matlab 中实现的。这是 I have never tried myself, but supported by mathworks.