I am trying to create functions to allow a user to trace over an image in matlab and record / plot in real time the coordinates of where they trace on top of that image.
Following this guide: https://www.mathworks.com/videos/capture-mouse-movement-97322.html I was able to create the following functional, proof of concept code which records and plots in real time where the user traces within a figure without an image present in the background:
function traceVelocityCurve()
fig = figure;
plotAxes = axes('Xlim', [0, 1], 'Ylim', [0 1], 'ButtonDownFcn', @startDragFcn);
hold all
xValues = [];
yValues = [];
tracing = scatter(xValues, yValues);
tracing.Marker = '.';
tracing.MarkerFaceColor = 'red';
tracing.MarkerEdgeColor = 'red';
set(fig, 'WindowButtonUpFcn', @stopDragFcn);
function startDragFcn(varargin)
set(fig, 'WindowButtonMotionFcn', @draggingFcn);
end
function draggingFcn(varargin)
point = get(plotAxes, 'CurrentPoint');
xValues = [xValues; point(1, 1)];
yValues = [yValues; point(1, 2)];
set(tracing, 'XData', xValues);
set(tracing, 'YData', yValues);
end
function stopDragFcn(varargin)
set(fig, 'WindowButtonMotionFcn', '');
end
end
It is also possible to remove the call to scatter() and substitute in a call to plot(). I believe this would be more in line with what is required for plotting on top of an image:
function traceVelocityCurve()
fig = figure;
plotAxes = axes('Xlim', [0, 1], 'Ylim', [0 1], 'ButtonDownFcn', @startDragFcn);
hold all
xValues = [];
yValues = [];
set(fig, 'WindowButtonUpFcn', @stopDragFcn);
function startDragFcn(varargin)
set(fig, 'WindowButtonMotionFcn', @draggingFcn);
end
function draggingFcn(varargin)
point = get(plotAxes, 'CurrentPoint');
xValues = [xValues; point(1, 1)];
yValues = [yValues; point(1, 2)];
plot(xValues, yValues, 'Color', 'red');
end
function stopDragFcn(varargin)
set(fig, 'WindowButtonMotionFcn', '');
end
end
However, if I attempt to first import an image and set it as the figure background and then try to trace / plot on top of that image within the same figure, I am unable to do so. For example, the following code correctly displays an image in the background of my figure, but I lose my tracing functionality (nothing is plotted when I click and drag across the figure):
function traceVelocityCurve()
fig = figure;
plotAxes = axes('Xlim', [0, 1], 'Ylim', [0 1], 'ButtonDownFcn', @startDragFcn);
loadedImage = imread('index.jpg');
image(loadedImage, 'Parent', plotAxes);
hold all
xValues = [];
yValues = [];
set(fig, 'WindowButtonUpFcn', @stopDragFcn);
function startDragFcn(varargin)
set(fig, 'WindowButtonMotionFcn', @draggingFcn);
end
function draggingFcn(varargin)
point = get(plotAxes, 'CurrentPoint');
xValues = [xValues; point(1, 1)];
yValues = [yValues; point(1, 2)];
plot(xValues, yValues, 'Color', 'red');
end
function stopDragFcn(varargin)
set(fig, 'WindowButtonMotionFcn', '');
end
end
Thank you in advance for your help!
By adding an image in your axes, you have made it so that you can't click on the axes any more. When you click, the image gets an event, but the axes no longer does.
However, the figure always gets the event as well. Set the figure's 'WindowButtonDownFcn'
to your startDragFcn
, and it will work:
function traceVelocityCurve()
fig = figure;
plotAxes = axes('Xlim', [0, 1], 'Ylim', [0 1]);
% ...
set(fig, 'WindowButtonDownFcn', @startDragFcn);
set(fig, 'WindowButtonUpFcn', @stopDragFcn);
% ...