6

为向 SO 提出非编程问题提前道歉,但权力已确定所有与 MATLAB 相关的问题都属于这里

我一直在做一些卡尔曼滤波器并绘制状态变量估计值,以查看它们如何随时间收敛。现在,我想直观地表示协方差矩阵,它表示估计中的不确定性。所以我写了一个小函数,在估计值周围涂上颜色。

(编辑说明:以前的版本错误地使用2*cov了每个半带的宽度,当它需要 2 个标准偏差时)

function [ls, regions] = plotuncertain( t, y, cov )
    t = t(:);
    y = y(:);
    stdev = cov(:).^(1/2);
    a = ones(size(t));
    regions(1) = patch('XData', [t; t(end:-1:1)], ...
                       'YData', [y + 2*stdev; y(end:-1:1)], ...
                       'FaceVertexAlphaData', [0*a; a], ...
                       'FaceAlpha', 'interp', 'EdgeColor', 'none');
    regions(2) = patch('XData', [t; t(end:-1:1)], ...
                       'YData', [y - 2*stdev; y(end:-1:1)], ...
                       'FaceVertexAlphaData', [0*a; a], ...
                       'FaceAlpha', 'interp', 'EdgeColor', 'none');
    ls = line('XData', t, 'YData', y);

它看起来很合理:

一锥不确定性

但是我有两个具有相似含义的状态变量,我想在一个轴上同时绘制它们。

两个不确定的锥体

呃,哦,k_1 的初始数据被 k_2 波段的(上半部分)遮蔽了。MATLAB 没有按照我提交的顺序绘制线条和补丁。即使我设法控制了他们绘制的顺序,alpha 混合仍然不如基于概率混合颜色的最佳选择。

任何想法如何同时渲染两者?我可以以某种方式利用我为两个变量使用两个不同的颜色平面这一事实吗?

4

2 回答 2

3

当绘图太复杂时,matlab 开始像这里一样出现异常行为。我经常尝试应用此处描述的解决方案。

对于您的特定(并且非常好的)图,我将通过声明轴来修改函数:

function [ax, ls, regions] = plotuncertain( t, y, cov )

    ax = axes;

    t = t(:);
    y = y(:);
    cov = cov(:);
    a = ones(size(t));
    regions(1) = patch('XData', [t; t(end:-1:1)], ...
                       'YData', [y + 2*cov; y(end:-1:1)], ...
                       'FaceVertexAlphaData', [0*a; a], ...
                       'FaceAlpha', 'interp', 'EdgeColor', 'none');
    regions(2) = patch('XData', [t; t(end:-1:1)], ...
                       'YData', [y - 2*cov; y(end:-1:1)], ...
                       'FaceVertexAlphaData', [0*a; a], ...
                       'FaceAlpha', 'interp', 'EdgeColor', 'none');
    ls = line('XData', t, 'YData', y);

然后调用函数:

[ax1, ls, regions] = plotuncertain( t, y, cov );
[ax2, ls, regions] = plotuncertain( t, y, cov );
set(ax2,'Visible','off');
linkaxes([ax1 ax2],'xy'); %or any (XLim,YLim) settings

这样,一个轴的透明度独立于另一个轴。

编辑

更好地控制颜色混合的一种方法是将专用图形中创建的每个轴转换为图像,然后将它们融合。例如,可以使用imfuse(im1,im2,'blend')(图像处理工具箱)或混合 2 个图像的任何功能。

从图中提取图像的方法是

F = getframe(gcf);
imwrite(F.cdata, 'image.png');

在此处输入图像描述

当然,这个解决方案只适用于报告过程的最后一步(我绝对不会将它用于科学文章 - 请参阅评论 - 但用于壮观的演示文稿)。使用比 Matlab 更好地处理透明度/OpenGL 的替代软件也可能更有效。

于 2013-07-22T21:31:00.167 回答
2

尽管您建议尝试这样做,但我发现交换补丁的顺序有很大的不同。

我的示例版本,首先没有交换:

t=[1:100];
y=t.^2;
cov=t.^2;

t2=[1:100];
y2=t2.^2.05;
cov2=t2.^2;

figure

t = t(:);
y = y(:);
cov = cov(:);
a = ones(size(t));

t2 = t2(:);
y2 = y2(:);
cov2 = cov2(:);

a = ones(size(t2));

regions(1) = patch('XData', [t; t(end:-1:1)], ...
    'YData', [y + 2*cov; y(end:-1:1)], ...
    'FaceVertexAlphaData', [0*a; a], ...
    'FaceAlpha', 'interp', 'EdgeColor', 'none', 'FaceColor', 'r');

regions(2) = patch('XData', [t; t(end:-1:1)], ...
    'YData', [y - 2*cov; y(end:-1:1)], ...
    'FaceVertexAlphaData', [0*a; a], ...
    'FaceAlpha', 'interp', 'EdgeColor', 'none', 'FaceColor', 'r');
ls = line('XData', t, 'YData', y,'Linewidth',1.5);

regions(3) = patch('XData', [t2; t2(end:-1:1)], ...
    'YData', [y2 - 2*cov2; y2(end:-1:1)], ...
    'FaceVertexAlphaData', [0*a; a], ...
    'FaceAlpha', 'interp', 'EdgeColor', 'none', 'FaceColor', 'b');
ls = line('XData', t2, 'YData', y2,'Linewidth',1.5);

regions(4) = patch('XData', [t2; t2(end:-1:1)], ...
    'YData', [y2 + 2*cov2; y2(end:-1:1)], ...
    'FaceVertexAlphaData', [0*a; a], ...
    'FaceAlpha', 'interp', 'EdgeColor', 'none', 'FaceColor', 'b');

未交换

然后交换:

regions(1) = patch('XData', [t; t(end:-1:1)], ...
    'YData', [y + 2*cov; y(end:-1:1)], ...
    'FaceVertexAlphaData', [0*a; a], ...
    'FaceAlpha', 'interp', 'EdgeColor', 'none', 'FaceColor', 'r');

regions(3) = patch('XData', [t2; t2(end:-1:1)], ...
    'YData', [y2 - 2*cov2; y2(end:-1:1)], ...
    'FaceVertexAlphaData', [0*a; a], ...
    'FaceAlpha', 'interp', 'EdgeColor', 'none', 'FaceColor', 'b');
ls = line('XData', t2, 'YData', y2,'Linewidth',1.5);


regions(2) = patch('XData', [t; t(end:-1:1)], ...
    'YData', [y - 2*cov; y(end:-1:1)], ...
    'FaceVertexAlphaData', [0*a; a], ...
    'FaceAlpha', 'interp', 'EdgeColor', 'none', 'FaceColor', 'r');
ls = line('XData', t, 'YData', y,'Linewidth',1.5);


regions(4) = patch('XData', [t2; t2(end:-1:1)], ...
    'YData', [y2 + 2*cov2; y2(end:-1:1)], ...
    'FaceVertexAlphaData', [0*a; a], ...
    'FaceAlpha', 'interp', 'EdgeColor', 'none', 'FaceColor', 'b');

交换了

效果很好,我以前在Matlab中没见过这个。

于 2013-07-22T20:23:51.050 回答