How can I plot and display image in MATLAB App Designer UIAxes?

I am creating a Turbocharging matching tool and an important part of this (for the user) is to see the operating points plotted on compressor maps.
The first problem I am running into is that it doesn't plot the points needed. These points should be taken from the edit fields next to 'Corr. Mass Air Flow' and 'Compressor PR' but it doesn't seem to work. The code for this part is under the callback function "MatchButton pushed".
The second problem I am facing is when I am trying to display the compressor map as an image in the background of the UIAxes. I have multiple compressor maps and I want to use a listbox along with an ifelse command to display the chosen compressor map as an image. The image does not display and the axes disappear. I attached a screenshot of what this looks like in the app itself and the image that I want displayed. The code for this is under the callback of list box value changed.
Thank you in advance!
% Button pushed function: MatchButton
function MatchButtonPushed(app, event)
x = [str2double(app.MassAirFlow1)
str2double(app.MassAirFlow2)
str2double(app.MassAirFlow3)
str2double(app.MassAirFlow4)
str2double(app.MassAirFlow5)
str2double(app.MassAirFlow6)];
y = [str2double(app.CompPR1)
str2double(app.CompPR2)
str2double(app.CompPR3)
str2double(app.CompPR4)
str2double(app.CompPR5)
str2double(app.CompPR6)];
plot(app.UIAxes,x,y, 'o');
end
% Value changed function: CompressorListBox
function CompressorListBoxValueChanged(app, event)
value = app.CompressorListBox.Value;
if strcmp(value, '62K80 (EFR 6258)')
hold(app.UIAxes, 'on')
I = imshow('62K80.jpg', 'Parent', app.UIAxes, ...
'XData', [1 app.UIAxes.Position(3)], ...
'YData', [1 app.UIAxes.Position(4)]);;
hold(app.UIAxes, 'off')
elseif strcmp(value, '67X80 (EFR 6758)')
hold(app.UIAxes, 'on')
I2 = imshow('67X80.png', 'Parent', app.UIAxes, ...
'XData', [1 app.UIAxes.Position(3)], ...
'YData', [1 app.UIAxes.Position(4)]);;
elseif strcmp(value, '70S75 (EFR 7064)')
hold(app.UIAxes, 'on')
I3 = imshow('70S75.png', 'Parent', app.UIAxes, ...
'XData', [1 app.UIAxes.Position(3)], ...
'YData', [1 app.UIAxes.Position(4)]);;
else strcmp(value, '76S75 (EFR 7670)')
hold(app.UIAxes, 'on')
I4 = imshow('76S75.png', 'Parent', app.UIAxes, ...
'XData', [1 app.UIAxes.Position(3)], ...
'YData', [1 app.UIAxes.Position(4)]);;
end

Answers (1)

Hello,
For your first problem, use numeric Editfield components, for those you don't need to use str2double. You should've seen the error that you cannot convert EditField component to double, the values in the box can be found in property Value.
For the second one, to display the image in UIAxes component you can do it this way
cImage = imread("62K80.jpg");
hImage = imshow(cImage, 'Parent', app.UIAxes);
Edit: comment section summed up
When you use imshow, it will use the size of image (height x width x page) to plot.
im = imread('pears.png');
imshow(im, 'Parent', uiax);
Without XData and YData it will use some sort of algorithm to determine XLim and YLim that would nicely display the data in plot.
You can use this to fill the plot area
app.UIAxes.XLim = [0 width(im)];
app.UIAxes.YLim = [0 height(im)];

12 Comments

Thank you for your note about the numeric/text edit fields. I noticed that one problem was that I didn't refer to the value using '.Value' for each object. But even with the values identified, it is still not plotting anything.
As for the image in the UIAxes, I am still reciving the same result with the code you provided me unfortunately.
There are few issues going on:
  • Why does the UIAxes component shrink? Maybe it's correctly plotted but you can't see it
  • In MatchButtonPushed callback, using plot function may remove the image depending on the value for NextPlot (this is what hold on sets)
  • Path to the images - Are images on the root folder where the app is? Is your current directory in the app folder?
I am not very familiar with app designer, I've only started using it a few days ago so I am not yet fully sure what is happening with the axes.
I set it up in a way that it plots the points before I show the image of the compressor map, so on paper, it should plot the points without a disruption from the image. I will look further into that.
Yes the images are in the root folder as the app and the current directory is also in the app folder. Is there a way to make the axes size constant while I display the image and make the image 'fit' into that size of the axes?
This will be a little bit hard task, especially since you are trying to plot specific values on the image.
I would first try to display the image, to make sure the DropDownMenu callback works.
You can use cla(app.UIFigure) to reset the image (XLim and other properties will remain the same) when you change the selection, so you don't have to use hold so many times. If your points should not remain on the axes when you change the dropdown, find the uiaxes component in Component Browser and under the Multiple Plots tab, set the NextPlot property to 'replaceall'. This allows you to have a single call to hold in the button pushed callback.
By using the XLim, YLim properties of the UIAxes, you can set the limits on the axes, let's say [0 200], you will have to use these numbers for the XData and YData name-value parameters in the imshow function. I think you can match the limits with the graph min and max values so you can plot the numbers from field directly without calculating where on the image is that point. By rescaling the image, you'll need to make sure that image has the same aspect ratio as it had before so the points are on the correct position.
Thank you so much for your input but I am still running into issues :(
I have tried what you suggested but only in a simple startup function (for now) just to simplify things first and manage to show and scale the image correctly.
This is the code:
% Code that executes after component creation
function startupFcn(app)
app.UIFigure.Position = [100 50 868 750];
app.CompressorListBox.Value = '62K80 (EFR 6258)';
app.UIAxes.XLim = [0 0.5];
app.UIAxes.XTick =linspace(0,0.52,14);
app.UIAxes.YLim = [1 3.8];
app.UIAxes.YTick = linspace(1,3.8,8);
I = imread('62K80.jpg');
imshow(I, 'Parent', app.UIAxes, 'XData', [0 0.5], 'YData', [1 3.8]);
end
The X and Y lims are set to match those of the graph on the image I want to display. When I use the same limits for the X and Y data of the imshow function, the image is displayed but just squeezed. I can't seem to figure out how to stretch the size of the image even when I specifically add it in the code specifying the 'position' of the UIAxes. It seems like the size of the x-axis is too small so I tried to play around with the limits, aspect ratios and position of the UIAxes. Also the axes ticks and tick labels seem to disappear.
This is what I see when I run the app:
You're getting quickly the grasp of App Designer, great!
app.UIFigure.Position = [100 50 868 750]; % This changes the position of UIFigure, the whole app window
Yes, unfortunately labels and ticks are gone when imshow is used.
My bad on the explanation for XData and YData. It is wrong. When you use imshow, it will use the size of image (height x width x page) to plot.
im = imread('pears.png');
imshow(im, 'Parent', uiax);
Without XData and YData it will use some sort of algorithm to determine XLim and YLim that would nicely display the data in plot.
If the images are of same size, it would be great, at least for the aspect ratio. You can use this to fill the plot area
app.UIAxes.XLim = [0 width(im)];
app.UIAxes.YLim = [0 height(im)];
You will have to interpolate your points to the image dimensions. I guess Interp1 or interp2 would be the way, but I can't be sure at the moment.
Awesome! This worked. All I have to do now is find a way to interpolate the values from the tool to correspond to the limits of the axes. Thank you so much!!
(Sorry for the very late response, I got frustrated with Matlab and decided to leave it for a bit haha)
Glad it worked out, you're welcome. I'd say that the thing you need to do is suitable for another question, if you need help with it.
You can accept this answer, I'll update it in a bit, thanks in advance.
I just used ratios to convert the values to ones that fit on the image's graph successfully.
I did run into the problem that I cannot display the ticks and tick labels while displaying an image. Do you know if there is a way I can display them?
axis(app.UIAxes, 'on');
This will make it out of proportiens you have set, so, you'll have to add some Name-Value parameters from above, like XLim and YLim. Using the image, Y direction is measured in opposite of usual.

Sign in to comment.

Categories

Find more on Develop Apps Using App Designer in Help Center and File Exchange

Asked:

on 14 Feb 2021

Commented:

on 2 Jun 2023

Community Treasure Hunt

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

Start Hunting!