Automatically align image and graph with shared x-axis
Asked Answered
C

1

2

I have an image that I want to plot under a graph showing the intensity of an arbitrary row of this image.

Apparently, there is no way I can "automatically" make the two graphs both aligned (they share the same x-axis) and not distorted.

Here is a MWE that uses the kobi.png image that should come with MATLAB. For this solution I used the answer to this question, but it's not exactly what I am looking for. The reason will be clear after the code.

im = imread('kobi.png'); % read default image
img = rgb2gray(im); % convert to grayscale

y = 600; % select line to "scan"

% plot image with highlithed line
subplot(3,3,4:9);
imagesc(img);
colormap gray
hold on
line([0 size(img,2)], [y y], 'Color', 'r', 'LineWidth', 1.5);
hold off
axis image

photoAxs = gca;
photoAxsRatio = get(photoAxs,'PlotBoxAspectRatio');

% plot intensity of selected row
subplot(3,3,1:3);
r = img(y, :);
plot(r);
axis tight

topAxs = gca;

% adjust ratios
topAxsRatio = photoAxsRatio;
topAxsRatio(2) = photoAxsRatio(2)/2.4; % I want to get rid of this number!  
set(topAxs,'PlotBoxAspectRatio', topAxsRatio)

Result

As you can see, this produces (almost) the expected result, but there is an hardcoded number (that in the answer I linked was different, 3.8, while here is 2.4), that I would like to eliminate. Also, I think this number gives only an apparently aligned solution, but with my slight OCD this room for error gives me the creeps!

So the question is:

Is there any viable way to automatically align a graph and an image that have the same x-axis while maintaining the image aspect ratio?

Calle answered 3/5, 2017 at 20:30 Comment(0)
I
2

Old code:

topAxsRatio = photoAxsRatio;
topAxsRatio(2) = photoAxsRatio(2)/2.4; % I want to get rid of this number!  
set(topAxs,'PlotBoxAspectRatio', topAxsRatio)

New code:

photoratio = photoAxs.PlotBoxAspectRatio(1)/photoAxs.PlotBoxAspectRatio(2);
ratio = photoratio * photoAxs.Position(4)/topAxs.Position(4);
topAxs.PlotBoxAspectRatio = [ratio, 1, 1];

Result:

enter image description here


A bit of explanation:

When figures are first plotted, you will notice only the heights are different, although you can clearly see the widths are also different.

I'm not 100% sure the reason Matlab does this, but this is my guess.

Usually, two properties, width and height, are sufficient to define the size of a 2D figure, but Matlab introduces an extra property, PlotBoxAspectRatio, to control the size. To avoid conflict, Matlab decides to give the width property a fixed number when a figure is first created. However, the actual width is calculated by height*PlotBoxAspectRatio.

Therefore, we have:

TopAxis.width = TopAxis.height * TopAxis.ratio 
Photo.width = Photo.height * Photo.ratio

In order to preserve the initial height of the TopAxis, we can only change the aspect ratio.

Let

TopAxis.width = Photo.width

We have

TopAxis.height * TopAxis.ratio = Photo.height * Photo.ratio
TopAixs.ratio = Photo.ratio * Photo.height / TopAxis.height

And the Matlab code equivalent is the new code proposed.

Inaction answered 3/5, 2017 at 23:1 Comment(2)
Thank you! Your explanation is excellent, and it explains that 2.4 (that was actually correct). It is the ratio between the heights of the two figures, isn't it? :)Calle
@Calle Indeed, I didn't realise that :DInaction

© 2022 - 2024 — McMap. All rights reserved.