Overlay a plot on an image

Hi,
I have to overlay a plot on a image. Here is my code:
Imm = imread('imageLeft.png');
figure()
imshow(Imm)
hold on
plot(pos_sensor_Lx,pos_sensor_Ly,'-o')
where Imm is the image (634x484x3 uint 8) while pos_sensor_Lx and pos_sensor_Ly are two column vectors 3487x1 double with values all normalized between [0;1].
When I plot the vectors and the image separately, I get this results:
Overlaying them, I ideally had to see the scan path well distribuited on the white and red dots of the image. Anyway when I overlay them I can't see the scan path over the image because of the very small values of the vector elements. Here the result I get:
All the values are clustered as shown.
Is there a way to adjust the image dimensions or the value of the vector elements to get the result I want?
Thank you

4 Comments

The scale of your points is fairly small. Do those units represent pixels? Normalized location? Something else?
Using daspect([1 1 1]) will also do something you might want.
Fed
Fed on 8 Feb 2021
Edited: Fed on 8 Feb 2021
Thank you for your answer. They represent pupil's positions got from an eye tracker. They are by default normalized in [0;1].
I tried to use
daspect([1 1 1])
but nothing happened.
KALYAN ACHARJYA
KALYAN ACHARJYA on 8 Feb 2021
Edited: KALYAN ACHARJYA on 8 Feb 2021
@Federica In the image, pixels are positioned based on Indices [0-r] and [0-c] in both in y and x direction. In the 2nd data, the values within 0-1, you may check for the normalize the 2nd data with repect to the 1st one?
Actually how do consider the maping of 2nd data with respect to image indices?
Fed
Fed on 8 Feb 2021
Edited: Fed on 8 Feb 2021
Thank you for your answer.
How do you suggest to normalize the 2nd data respect to the 1st ones?
I would like to change the size of imageLeft so to have the same dimensions of the scan-path. In this way I could overlay them and see the data from the eye tracker on the first image.
It'd be great if it would be possible to represent imageLeft on the range [0.38 ; 0.46] for the x axis and [0.61 ; 0.67] for the y axis as in the scan - path

Sign in to comment.

 Accepted Answer

Hi Federica,
Use the following code as an example to normalize your 2nd data based on the first and overlay it on the image.
Imm = imread('image.jpeg');
figure()
% Synthesis - [0,1] Normalized random data
P = rand(1,50); % -> X-variable
Q = rand(1,50); % -> Y-Variable
% Normalizing with respect to image pixels and quantizing
C = size(Imm)
P = uint16(P*C(1));
Q = uint16(Q*C(2));
% Overlay Plot
imshow(Imm)
hold on
plot(P,Q)
hold off

3 Comments

Thank you so much!
Hey Kiran, what would I change to the code above to not only overlay the plot, but then to save that image with the overlayed plot as its own file?
Hi Skylar, just use the 'Get Current figure' and 'Saveas' function to save the figure.
For eg, add the following line after the last line of the above code, this will save the figure as a PNG file named 'saved'
saveas(gcf,'saved.png')

Sign in to comment.

More Answers (2)

Ravi Kumar Pallantla
Ravi Kumar Pallantla on 10 Aug 2022
There is a script in file exchange to plot data on an image file. Hope it will be helpful to you.
The accepted answer works for random test data, but it swaps the axes, and a few other things that matter for eye-tracker data were never covered. size(Imm) returns [rows cols], i.e. [634 484], so x has to be scaled by the number of columns (484) and y by the number of rows (634). The accepted answer does the opposite, which stretches the scan path horizontally (anything beyond x = 0.76 lands off the image) and squeezes it vertically. You can also skip the conversion completely by placing the image in normalized coordinates with the XData/YData options of imshow, which is what you asked for in your last comment. Set daspect so the pixels stay square, otherwise the image is stretched to a square. Next, check your tracker's vertical convention: image rows run top to bottom, but many eye trackers put normalized (0,0) at the bottom-left, and then y has to be flipped (1 - y) or the scan path appears upside down. Finally, and probably the real reason your points cluster in a tiny region: you mentioned these are pupil positions. Pupil position is where the pupil sits in the eye camera's image, not where the person is looking, which is why all values fall in a narrow range (x 0.39-0.46, y 0.61-0.66). Scaling those values, or stretching the image to fit them, will not make them line up with the dots. Use the tracker's calibrated gaze output instead (normalized to the screen or the scene camera), and if the image did not fill the whole screen, map screen coordinates to the area where the image was displayed. The code below shows both overlay options and saves the result with exportgraphics, which crops to the axes rather than saving the whole figure as saveas does.
Imm = imread('imageLeft.png');
[nRows, nCols, ~] = size(Imm);
% Image rows run top to bottom. If your tracker puts (0,0) at the
% bottom-left, flip y; if it uses the top-left, leave it as is.
originBottomLeft = true;
gx = pos_sensor_Lx;
gy = pos_sensor_Ly;
if originBottomLeft
gy = 1 - gy;
end
% Option 1: show the image in normalized coordinates and plot directly
figure
imshow(Imm, 'XData', ([1 nCols] - 0.5) / nCols, 'YData', ([1 nRows] - 0.5) / nRows)
daspect([nRows nCols 1]) % keep pixels square
axis on
hold on
plot(gx, gy, '-o', 'MarkerSize', 3)
hold off
title('Gaze in normalized coordinates')
% Option 2: convert gaze to pixel coordinates (x with columns, y with rows)
px = gx * nCols + 0.5;
py = gy * nRows + 0.5;
figure
imshow(Imm)
hold on
plot(px, py, '-o', 'MarkerSize', 3)
hold off
title('Gaze in pixel coordinates')
% Save the overlay (crops to the axes, unlike saveas(gcf,...))
exportgraphics(gca, 'overlay.png')
HTH,
WJ

Asked:

Fed
on 8 Feb 2021

Answered:

on 28 Oct 2026 at 12:47

Community Treasure Hunt

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

Start Hunting!