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.

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.

plot(x,y,'b-*','linewidth',1.5);

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:

figure; imagesc(img); xlabel('Raster Column'); ylabel('Raster Row'); colormap(gray);

The above code produces this:

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).

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; plot(x,y,'b-*','linewidth',1.5);

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:

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; plot(x,y,'b-*','linewidth',1.5); % set the y-axis back to normal. set(gca,'ydir','normal');

This is the result:

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); plot(x,y,'b-*','linewidth',1.5); % set the y-axis back to normal. set(gca,'ydir','normal');

The result will look like this:

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; plot(x,y,'b-*','linewidth',1.5); % set the y-axis back to normal. set(gca,'ydir','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:

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`

:

flipdim(img,1);

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.