【问题标题】:Removing deadspace in subplots while retaining title & labels删除子图中的死区,同时保留标题和标签
【发布时间】:2013-09-22 03:13:34
【问题描述】:

您好,我在 matlab 中遇到问题 我想创建一个包含 10 个子图的图形。在 2X5 方向。但问题是我想减少它们之间的死角区域。我还需要保留第一行图像的标题、xlabel 和第二行图像的 xlabel(only)。不需要 ylabels。

到目前为止,我已经完成了这段代码(第一行):一旦我确定了第一行,第二行应该是小菜一碟。

close all

figure,set(gca,'Color','none')
subplot(2,5,1);subplot('Position',[0.02 0.51  0.18 0.45]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
imshow(I);hold on; axis off;
contour((BW(:,:,1)), [0 0], 'r','LineWidth',2);
hold off;title('1st curve','FontSize',12);xlabel('(a)','FontSize',12)
subplot(2,5,2);subplot('Position',[0.215 0.51  0.18 0.45]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
imshow(I);hold on; axis off;
contour((BW(:,:,2)), [0 0], 'r','LineWidth',2);
hold off;title('2nd curve','FontSize',12);xlabel('(b)','FontSize',12)
subplot(2,5,3);subplot('Position',[0.410 0.51  0.18 0.45]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
imshow(I);hold on; axis off;
contour((BW(:,:,3)), [0 0], 'r','LineWidth',2);
hold off;title('3rd curve','FontSize',12);xlabel('(c)','FontSize',12)
subplot(2,5,4);subplot('Position',[0.605 0.51  0.18 0.45]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
imshow(I);hold on; axis off;
contour((BW(:,:,4)), [0 0], 'r','LineWidth',2);
hold off;title('4th curve','FontSize',12);xlabel('(d)','FontSize',12)
subplot(2,5,5);subplot('Position',[0.8 0.51  0.18 0.45]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
imshow(I);hold on; axis off;
contour((BW(:,:,5)), [0 0], 'r','LineWidth',2);
hold off;title('5th curve','FontSize',12);xlabel('(e)','FontSize',12)

这给了我这样的输出:

如您所见,第四张图片不存在。代码有什么问题?我已经多次重新检查了我的代码和计算,但找不到任何错误。

有趣的是,当我运行此代码时 [只有第 4 个子图]

subplot(2,5,4);subplot('Position',[0.605 0.51  0.18 0.45]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
imshow(I);hold on; axis off;
contour((BW(:,:,4)), [0 0], 'r','LineWidth',2);
hold off;title('4th curve','FontSize',12);xlabel('(d)','FontSize',12)

我得到这个答案!

请谁能告诉我我哪里错了?请注意,我确实需要图像第一行的 xlabel 和标题。

编辑:然后我去做了这件事。现在我得到了五个图像。然而,在所有情况下,图像之间的间距并不均匀,特别是第一张和第二张图像之间的间距与其他图像之间的间距不同。

我的代码:

close all

figure,set(gca,'Color','none')
subplot(2,5,1);subplot('Position',[0.02 0.51  0.18 0.45]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
imshow(I);hold on; axis off;
contour((BW(:,:,1)), [0 0], 'r','LineWidth',2);
hold off;title('1st curve','FontSize',12);xlabel('(a)','FontSize',12)
subplot(2,5,2);subplot('Position',[0.210 0.51  0.18 0.45]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
imshow(I);hold on; axis off;
contour((BW(:,:,2)), [0 0], 'r','LineWidth',2);
hold off;title('2nd curve','FontSize',12);xlabel('(b)','FontSize',12)
subplot(2,5,3);subplot('Position',[0.405 0.51  0.18 0.45]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
imshow(I);hold on; axis off;
contour((BW(:,:,3)), [0 0], 'r','LineWidth',2);
hold off;title('3rd curve','FontSize',12);xlabel('(c)','FontSize',12)
subplot(2,5,4);subplot('Position',[0.600 0.51  0.18 0.45]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
imshow(I);hold on; axis off;
contour((BW(:,:,4)), [0 0], 'r','LineWidth',2);
hold off;title('4th curve','FontSize',12);xlabel('(d)','FontSize',12)
subplot(2,5,5);subplot('Position',[0.795 0.51  0.18 0.45]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
imshow(I);hold on; axis off;
contour((BW(:,:,5)), [0 0], 'r','LineWidth',2);
hold off;title('5th curve','FontSize',12);xlabel('(e)','FontSize',12)

现在我得到了这个答案:

我该如何纠正这个问题?请帮忙!提前致谢!!

编辑:我似乎已经解决了这个问题。请在下面看到我的答案。但是我确实有疑问。 我想让代码循环运行,所以实现了这段代码。

I = imread('coins.png');
I = imresize(I,[128 128]);
for no = 1:5
    subplot('Position',[0.025+0.19*(no-1) 0.51 0.19 0.48]);
    imshow(I);
    get(gca,'Position');set(gca, 'XTick', []);set(gca, 'YTick', []);
    title({'Image' num2str(no)});
    subplot('Position',[0.025+0.19*(no-1) 0.03  0.19 0.48]);
     imshow(I);
    get(gca,'Position');set(gca, 'XTick', []);set(gca, 'YTick', []);
    title({'Image' num2str(no)});
end

答案是这样的

这段代码可以向量化吗?

【问题讨论】:

  • 您不必致电subplot 两次。它创建了第二个子图。帮助说 subplot('Position',positionVector) 在 positionVector 指定的位置创建一个新轴。如果您想沿 x 轴分布图像,您可以使用 linspace(0.02,0.8,5) 创建等距值的向量。
  • MATLAB subplot margin 的可能重复项

标签: image matlab plot subplot


【解决方案1】:

当然可以用一个循环来完成 (对变量使用元胞数组,对绘图函数使用元胞数组) 但为了简单起见 我只是把它归为两个循环。

labels = {'(a)' , '(n)' , '(etc)' , 'asdf','asddf'}
jay=1
for aye =1:5
     subplot('Position',[0.025+0.19*(aye-1) 0.51-0.48*(jay-1)  0.19 0.48]);
    ...
     h=xlabel(labelsabc{aye},'FontSize',12);
     ....
end

【讨论】:

  • 我有一个问题。 “位置”的第一个参数似乎工作正常,但为什么第二个参数在每次迭代时都会发生变化?可能是因为我没有完全得到你的答案。你能详细说明你的答案吗?
  • jay 已修复。一排是 1,另一排是 2。但是因为您还更改了数据源和绘图功能,所以将其拆分更易读 contour((BW(:,:,aye)) vs seg = phi0(:,:,aye)
【解决方案2】:

内置的subplot功能真的很强大很好看。我认为最好坚持使用subplot,而不是使用自定义计算位置。问题当然是subplot 停留在“额外”空间中。这个空间受两个因素控制。第一个是用户控制的SubplotDefaultAxesLocation属性的应用程序数据的数字。第二个是subplot 函数中的硬编码insetSubplotDefaultAxesLocation 属性控制图形边缘周围的空白,而inset 控制面板之间的空间。您可以删除图形周围的空间

hfig = figure;
setappdata(hfig, 'SubplotDefaultAxesLocation', [0, 0, 1, 1])

要删除面板之间的空间,您需要编辑(或复制编辑)subplot.m 在 R2013a 中,违规行是 129 和 130

% This is the percent offset from the subplot grid of the plotbox.
inset = [.2, .18, .04, .1]; % [left bottom right top]

如果将第 130 行更改为

inset = [0.0, 0.0, 0.0, 0.0]; % [left bottom right top]

那么面板之间将没有任何空间。更好的是像

% This is the percent offset from the subplot grid of the plotbox.
if ~isappdata(ancestorFigure, 'SubplotDefaultInset')
    inset = [.2, .18, .04, .1]; % [left bottom right top]
else
    inset = getappdata(ancestorFigure, 'SubplotDefaultInset');
end

这样您就可以控制inset。有了这个稍加修改的subplot 函数

I = imread('coins.png');
I = imresize(I,[128 128]);

voffset = 0.3;
hfig = figure;
setappdata(hfig, 'SubplotDefaultAxesLocation', [0, voffset/2, 1, 1-voffset]);
setappdata(hfig, 'SubplotDefaultInset', [0, 0, 0, 0]);

nrow = 2;
ncol = 5;
hax = nan(nrow, ncol);
for irow = 1:nrow
    for icol = 1:ncol
        hax(irow, icol) = mysubplot(nrow, ncol, icol+(irow-1)*ncol, 'align');
        imshow(I);
        if irow == 1
            title(hax(irow, icol), ['Curve #', num2str(icol)], 'FontSize',12);
        end
        if irow == nrow
            xlabel(hax(irow, icol), ['(', char(96+icol), ')'], 'FontSize',12);
        end
    end
end
set(hax,  'XTick', [], 'YTick', []);

pos = get(hfig, 'Position');
set(hfig, 'Position', [pos(1:2), (1-voffset)*pos(3), nrow/ncol*pos(3)]);

您需要 voffset 以允许标题和 xlabel 适合该图。您需要缩放图形,使其具有正确的纵横比来处理面板。结果是

曲线 1 和 2 以及曲线 3 和 4 之间的小间隙似乎是渲染伪影。

如果你想要行之间的标签,你需要添加一些额外的空间。例如,只在 x 轴上添加标签,您可以这样做

voffset = 0.35;
setappdata(hfig, 'SubplotDefaultAxesLocation', [0, voffset/4, 1, 1-voffset/2]);
setappdata(hfig, 'SubplotDefaultInset', [0, voffset/2, 0, 0]);

【讨论】:

  • 感谢您的回答,但如果我想让 xlabels 出现在顶行的图像中,我该怎么办?
  • 再次感谢。我会检查并通知您!
【解决方案3】:
close all
figure,set(gca,'Color','none')
subplot('Position',[0.025 0.51  0.19 0.48]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
imshow(I);hold on; axis off;
contour((BW(:,:,1)), [0 0], 'r','LineWidth',2);
hold off;title('1st curve','FontSize',12);h=xlabel('(a)','FontSize',12);
s=get(h,'Position');
s(2)=s(2)-28;
set(h,'Position',s);
subplot('Position',[0.025+0.19*1 0.51  0.19 0.48]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
imshow(I);hold on; axis off;
contour((BW(:,:,2)), [0 0], 'r','LineWidth',2);
hold off;title('2nd curve','FontSize',12);h=xlabel('(b)','FontSize',12);
s=get(h,'Position');
s(2)=s(2)-28;
set(h,'Position',s);
subplot('Position',[0.025+0.19*2 0.51  0.19 0.48]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
imshow(I);hold on; axis off;
contour((BW(:,:,3)), [0 0], 'r','LineWidth',2);
hold off;title('3rd curve','FontSize',12);h=xlabel('(c)','FontSize',12);
s=get(h,'Position');
s(2)=s(2)-28;
set(h,'Position',s);
subplot('Position',[0.025+0.19*3 0.51  0.19 0.48]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
imshow(I);hold on; axis off;
contour((BW(:,:,4)), [0 0], 'r','LineWidth',2);
hold off;title('4th curve','FontSize',12);h=xlabel('(d)','FontSize',12);
s=get(h,'Position');
s(2)=s(2)-28;
set(h,'Position',s);
subplot('Position',[0.025+0.19*4 0.51  0.19 0.48]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
imshow(I);hold on; axis off;
contour((BW(:,:,5)), [0 0], 'r','LineWidth',2);
hold off;title('5th curve','FontSize',12);h=xlabel('(e)','FontSize',12);
s=get(h,'Position');
s(2)=s(2)-28;
set(h,'Position',s);

subplot('Position',[0.025 0.03  0.19 0.48]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
seg = phi0(:,:,1)<=0;imshow(seg);
h=xlabel('(f)','FontSize',12);
s=get(h,'Position');
s(2)=s(2)-28;
set(h,'Position',s);
subplot('Position',[0.025+0.19*1 0.03  0.19 0.48]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
seg = phi0(:,:,2)<=0;imshow(seg);
h=xlabel('(g)','FontSize',12);
s=get(h,'Position');
s(2)=s(2)-28;
set(h,'Position',s);
subplot('Position',[0.025+0.19*2 0.03  0.19 0.48]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
seg = phi0(:,:,3)<=0;imshow(seg);
h=xlabel('(h)','FontSize',12);
s=get(h,'Position');
s(2)=s(2)-28;
set(h,'Position',s);
subplot('Position',[0.025+0.19*3 0.03  0.19 0.48]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
seg = phi0(:,:,4)<=0;imshow(seg);
h=xlabel('(i)','FontSize',12);
s=get(h,'Position');
s(2)=s(2)-28;
set(h,'Position',s);
subplot('Position',[0.025+0.19*4 0.03  0.19 0.48]);get(gca,'position');set(gca, 'XTick', []);set(gca, 'YTick', []);
seg = phi0(:,:,5)<=0;imshow(seg);
h=xlabel('(j)','FontSize',12);
s=get(h,'Position');
s(2)=s(2)-28;
set(h,'Position',s);

谢谢大家,我得到了正确的答案。我稍微改了一下代码。

这是我得到的答案:

【讨论】:

    【解决方案4】:

    当子图重叠时,较早的会被隐藏。

    尝试稍微减小“位置”宽度。

    他们应该再次出现

    另外,可能存在一些“对齐网格”问题, 当您调整窗口大小时,它的行为如何?

    【讨论】:

    • 一开始我的想法是子情节是重叠的。无论如何,我似乎已经修复了它。请检查我编辑的帖子。顺便说一下,当我调整窗口大小时,它保持不变。
    • 请在下面查看我的答案。它运作良好。但是可以循环完成吗?
    【解决方案5】:

    您可以在 Aslak Grinsted 的 Matlab File Exchange: subaxis 上找到 subaxis 功能,为您提供非常方便的解决方案。

    【讨论】:

    • 谢谢,但我不想使用别人的作品。你能告诉我我的代码有什么问题吗?
    • 我可以理解,但正如您所见,进入 subplot 函数需要相当多的努力。很抱歉,我也必须做很多研究。
    • 请在下面查看我的答案。它似乎运作良好。但是可以循环完成吗?
    • 当然,您只需将所有位置放在一个矩阵中,每次迭代都转到下一行。其他参数也是可迭代的。带有字母的标签有点棘手。您必须将字母存储在字符向量中,并通过迭代变量进行寻址。
    • 我对此表示怀疑。我的意思是每个子图都需要绘制,这不能通过矢量化解决方案来完成。但是由于您的解决方案中一行的所有图像都链接在一起,您可以在绘图之前将它们组合起来。然后需要再次为标签努力。我会保持原样。使用单元格的代码折叠来隐藏所有这些东西,它不会再打扰你了。
    猜你喜欢
    • 2018-08-15
    • 1970-01-01
    • 1970-01-01
    • 2020-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多