Plot over an image background in MATLAB

This is a short tutorial that documents how to make a MATLAB plot on top of an image background. This can be useful for a variety of things but when I first learned about it, I was a bit confused by how the axes seem to be flipped sometimes when you do this. In this tutorial I will give several examples that should illustrate how to plot on top of an image properly. I have used this technique for a few things, such as visualizing 1D and 2D classifier decision boundaries when I was preparing my thesis. I have also written a tutorial on how to do a 3D version of this in which an image is shown as a plane in a surface plot.

MATLAB plotPlotting on an image

Getting started

First, make a new .m file and load any image you want. In this example, I used a gray scale version of one of the images in my artwork gallery, specifically Gentoo Kung Fu, because it is easy to see which way is up in the image unless you think it is possible for a penguin to take on three guys in hand-to-hand combat while standing upside down. You should try it with your own image. Put the following into the .m file:

% replace with an image of your choice
img = imread('myimage.png');
% set the range of the axes
% The image will be stretched to this.
min_x = 0;
max_x = 8;
min_y = 0;
max_y = 6;
% make data to plot - just a line.
x = min_x:max_x;
y = (6/8)*x;

The above code defines the axes range that the image is stretched to and creates some (x, y) data to plot. The code examples that follow use the above data and variables.

The following code creates the plot itself. (0,0) starts at the bottom left as expected for a regular plot.


Desired plot to be shown over the image

Before getting started with some examples, first show the image in a MATLAB plot to take a look at how the image array (matrix) is actually stored in MATLAB:

xlabel('Raster Column');
ylabel('Raster Row');

The above code produces this:

Raster coordinates of the image

The coordinates given by (Raster Row, Raster Column) are the 0-based image coordinates. The image array is stored with (0, 0) as the top left corner of the image. In MATLAB's internal memory, (0, 0) corresponds to subscript (1, 1).

Some wrong examples

It is necessary to understand a bit about what MATLAB is doing when you tell it to show an image and add a plot on top of it. Sometimes the result is wrong and here are some examples with an explanation of why.

Example 1

The first example that shows an image as well as a MATLAB plot.

imagesc([min_x max_x], [min_y max_y], img);
hold on;

Here, the imagesc command is issued in imagesc(x,y,C) form, which will specify the range of axes labels that the image is displayed within (determined here by [min_x max_x] and [min_y max_y]). The hold on command is issued and then the (x, y) data are plotted. This is the result:

Example 1 - Y-axis reversed

You will notice that the plot and the Y-axis are now upside down but the image is displayed properly. The reason is when imagesc is used, MATLAB has reversed the Y-axis so that Y gets larger as you move down. This corresponds to making the Y-axis increase in the same direction as image raster coordiantes. When the plot is made, it is using the new, reversed Y-axis, thus explaining why it is flipped.

Example 2

We can tell MATLAB to flip the axis back to normal, as in the following code with set(gca,'ydir','normal'):

imagesc([min_x max_x], [min_y max_y], img);
hold on;
% set the y-axis back to normal.

This is the result:

Example 2 - Image reversed

Now the image is flipped. That's because when the Y-axis is set back to normal, it affects how MATLAB displays the figure. Y is small at the bottom and large at the top, so MATLAB will show the image upside down. It turns out the Y-axis direction specifies how MATLAB displays the image; the image raster row axes is always displayed in the same direction as the Y-axis. In other words, the image is displayed in such a way that the smallest raster row (which is 0) is at the smallest Y value visible on the axes, and the largest raster row is at the largest Y value visible on the axes.

Example 3

The hold on command should be issued after the image is displayed. Otherwise, the figure will retain the default set of axes when you display the image, without adjusting to the width and height of the image.

For example, try moving hold on to before the imagesc command in Example 2:

hold on; % hold on before the image causes incorrect results
imagesc([min_x max_x], [min_y max_y], img);
% set the y-axis back to normal.

The result will look like this:

Hold on should be issued after the image is displayed

The correct way

In order to resolve the problem from Example 2, the image can be flipped before displaying with the flipud command:

% Flip the image upside down before showing it
imagesc([min_x max_x], [min_y max_y], flipud(img));
% NOTE: if your image is RGB, you should use flipdim(img, 1) instead of flipud.
hold on;
% set the y-axis back to normal.

Here, the image is flipped first before displaying, so that the bottom of the image is now Y = 0. Then, the y-axis is set back to normal (where Y = 0 is at the bottom). This means that the bottom of the image (which is now Y = 0 due to flipud) is at the bottom of the plot. The result:

Correctly plotting on top of an image

This correctly shows the image and the plot. A few readers have pointed out that if your image is RGB, you can use the flipdim command instead of flipud:


One caveat: Although Example 1 and Example 2 from the previous section are called “incorrect”, they may actually give you the right result in some cases. The image in this tutorial depicts a scene that independently has a “right side up”. Image Row 0 must always be displayed at the top. There may be cases where the image you want to show is created within MATLAB and Image Row 0 might simply need to be associated with the smallest Y-coordinate shown on the axes. In that case, Example 1 or Example 2 might give you want you want. An example might be when you need to visualize classifier decision boundaries. In any case, the information in this tutorial should be enough to figure it out if needed.

About Peter Yu I am a research and development professional with expertise in the areas of image processing, remote sensing and computer vision. I received BASc and MASc degrees in Systems Design Engineering at the University of Waterloo. My working experience covers industries ranging from district energy to medical imaging to cinematic visual effects. I like to dabble in 3D artwork, I enjoy cycling recreationally and I am interested in sustainable technology. More about me...

Feel free to contact me with any questions about this site at [user]@[host] where [user]=web and [host]

Copyright © 1997 - 2021 Peter Yu