How to show multiple images in the same figure and ensure that each image pixel is shown as a screen pixel?

7 ビュー (過去 30 日間)
I am doing some simple image processing and must dispay the resulting images without re-scaling. For example, I would like to do something like this:
in = imread('..\images\david.png');
out = dither(in);
subplot(1,2,1); imshow(in,'InitialMagnification',100); title('original')
subplot(1,2,2); imshow(out,'InitialMagnification',100); title('floyd steinberg')
Unfortunately, the 'InitialMagnification' parameter seems to be ignored when subplot is being used. If figure size is manipulated to be too small to fit both images, images are reduced in size (this is logical). If figure size is manipulated to be large enough to fit both images, images are resized to fit the window (this is very annoying). Since the size of image margins when using subplot does not seem to be documented, I can see no way of reliably generating exactly right size of the figure to ensure 100% scaling (and it does not sound like a healthy way of doing things in any case).
What would be a more robust way to display figure with multiple images shown at 100% each?

回答 (1 件)

DGM
DGM 2021 年 5 月 14 日
編集済み: DGM 2021 年 5 月 18 日
The 'InitialMagnification' parameter doesn't really work in any way that seems to be helpful for controlled resolution output. Instead of your 100% geometry reference being something predictable (like the image geometry) it's the axes geometry (whatever that is depending on the circumstances). This makes figure setup a bit of a chore. You need to get the parent axes geometry to match the image geometry. In this example, I did that by simply adjusting (recenter and scale) after each axes was generated.
inpict = rgb2gray(imread('sources/lena.tif'));
s = size(inpict); % 512x512 in this case
bnd = noisedither(inpict,'blue');
ord = orddither(inpict);
zfd = zfdither(inpict);
% generally, using 'bilinear' interpolation helps when scaling isn't integer
% may need to use tight borders so there's enough room for 1:1 display
options = {'interpolation','nearest','border','tight'};
h1 = subplot(1,3,1,'units','pixels');
h1.Position(1:2) = h1.Position(1:2) + h1.Position(3:4)/2 - s([2 1])/2;
h1.Position(3:4) = s([2 1]);
imshow(bnd,options{:});
h2 = subplot(1,3,2,'units','pixels');
h2.Position(1:2) = h2.Position(1:2) + h2.Position(3:4)/2 - s([2 1])/2;
h2.Position(3:4) = s([2 1]);
imshow(ord,options{:});
h3 = subplot(1,3,3,'units','pixels');
h3.Position(1:2) = h3.Position(1:2) + h3.Position(3:4)/2 - s([2 1])/2;
h3.Position(3:4) = s([2 1]);
imshow(zfd,options{:});
this gives:
right-click, view image to see that it's actually 1:1 scaling
You may have to do a lot more position wrangling to get your layout to look as you want.
  2 件のコメント
Alexey Pichugin
Alexey Pichugin 2021 年 5 月 18 日
編集済み: Alexey Pichugin 2021 年 5 月 18 日
Thank you very much, I appreciate your comments. I understand what you propose doing, however, it does not seem to work for my copy of Matlab 2020b. This is the relevant part of my test script:
s = size(in); figure('Position',[0 0 640 480])
options = {'interpolation','nearest','border','tight'};
h1 = subplot(1,2,1,'units','pixels');
h1.Position(1:2) = h1.Position(1:2) + h1.Position(3:4)/2 - s(1:2)/2;
h1.Position(3:4) = s(1:2);
imshow(in,options{:})
h2 = subplot(1,2,2,'units','pixels');
h2.Position(1:2) = h2.Position(1:2) + h2.Position(3:4)/2 - s(1:2)/2;
h2.Position(3:4) = s(1:2);
imshow(dither(gmin),options{:}) % this is a gamma corrected version of "in"
(I cannot use "lena.tif", esp. because it has now been removed from USC-SIPI database.)
However, this is what my copy of Matlab comes up with (please see the attached image, because the included image seems to be resized again). So, unfortunately, I cannot accept your answer, as the issue still stands from my perspective.
DGM
DGM 2021 年 5 月 18 日
編集済み: DGM 2021 年 5 月 18 日
Okay, That's totally my fault.
% test pattern to reveal interference
x = mod(1:250,2);
y = mod(1:210,2);
inpict = xor(x,y');
s = size(inpict);
set(gcf,'position',[0 0 640 480])
% generally, using 'bilinear' interpolation helps when view mag isn't integer
% may need to use tight borders so there's enough room for 1:1 display
options = {'interpolation','nearest','border','tight'};
h1 = subplot(1,2,1,'units','pixels');
h1.Position(1:2) = h1.Position(1:2) + h1.Position(3:4)/2 - s([2 1])/2;
h1.Position(3:4) = s([2 1]);
imshow(inpict,options{:});
h2 = subplot(1,2,2,'units','pixels');
h2.Position(1:2) = h2.Position(1:2) + h2.Position(3:4)/2 - s([2 1])/2;
h2.Position(3:4) = s([2 1]);
imshow(inpict,options{:});
I fell for the fact that position properties are specified [x y] and array geometry is [y x], so it would only work right if the image were square.
You might still need to adjust the position offset to get both images comfortably spaced/centered in the figure.

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeSubplots についてさらに検索

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by