提前道歉,将非编程问题带到SO,但the powers-that-be have determined that all MATLAB-related questions belong here。
我一直在做一些卡尔曼滤波器并绘制状态变量估计值,以了解它们如何随时间收敛。现在,我想直观地表示协方差矩阵,这表明估计的不确定性。所以我写了一个小函数,在估计值周围为一个乐队着色。
(编辑注释:先前的版本错误地使用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混合仍然不如基于概率混合颜色最佳。
任何想法如何同时渲染两者?我可以以某种方式利用我为这两个变量使用两个不同颜色平面这一事实吗?
答案 0 :(得分:3)
当情节太复杂时,matlab开始表现得像这里一样不规律。我经常尝试应用here描述的解决方案。
对于你的特定(和非常好的)情节,我会通过声明一个轴来修改函数:
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的替代软件也可能更有效。
答案 1 :(得分: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中看到过这个。