Problem for drawing on an image Matlab GUI
Show older comments
Hello ! I would like to create an interface where the user can upload on an image and draw on it and after save it. I already create the button which allowed the user to upload an image and another to save it. The functions works, now my problem is to draw on the image. I used buttondownfcn and windowbuttonmotionfcn to detect when the user clicks on the mouse and when he clicks I draw. These code works when the user draw next to the image but when I click on the image it doesn't works. It only works when I click next to the image. Please help me !!
function varargout = IHM(varargin)
Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @IHM_OpeningFcn, ...
'gui_OutputFcn', @IHM_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
% --- Executes just before IHM is made visible.
function IHM_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to IHM (see VARARGIN)
% Choose default command line output for IHM
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes IHM wait for user response (see UIRESUME)
% uiwait(handles.figure1);
setappdata(0 , 'LePath', gcf);
% --- Outputs from this function are returned to the command line.
function varargout = IHM_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT);
% Get default command line output from handles structure
varargout{1} = handles.output;
% --- Executes on button press in OpenButton.
function OpenButton_Callback(hObject, eventdata, handles)
axes(handles.axes1);
[Filename, Pathname] = uigetfile({'*.*'},'Select your picture(s)','MultiSelect','off');% recupere le chemin de l'image
Chemin= Pathname;
Chemin=strcat(Chemin, Filename);%concatene le chemin et le nom du fichier
Foto=imread(Chemin);
%adapate les axes et redimensionne en fonction de la taille de l'image
set(handles.axes1,'Units','pixels');
resizePos = get(handles.axes1,'Position');
Foto= imresize(Foto, [resizePos(3) resizePos(3)]);
imshow(Foto);
set(handles.axes1,'Units','normalized');
axis manual;
%conversion image dans un repère
RI = imref2d(size(Foto));
h = imshow(Foto,RI);
LePath = getappdata(0, 'LePath');
setappdata(LePath, 'PathName', Chemin);
function DrawButton_Callback(hObject, eventdata, handles)
% hObject handle to DrawButton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
axis manual;
%axis manual; %pour garder la taille des axes fixes (sinon tend vers infini quand on draw)
A=handles.axes1; % tag de l'axe
set(A,'buttondownfcn',@start_pencil)%envoie vers la fonction start_pencil si on clique sur image
function start_pencil(src,eventdata)
coords=get(src,'currentpoint'); %récupère les info sur la position du curseur
x=coords(1,1,1);
y=coords(1,2,1);
r=line(x, y, 'color', [0 0 1], 'LineWidth', 2, 'hittest', 'off'); %turning hittset off allows you to draw new lines that start on top of an existing line.
set(gcf,'windowbuttonmotionfcn',{@continue_pencil,r})
set(gcf,'windowbuttonupfcn',@done_pencil)
function continue_pencil(src,eventdata,r)
%Note: src is now the figure handle, not the axes, so we need to use gca.
coords=get(gca,'currentpoint'); %this updates every time i move the mouse
x=coords(1,1,1);
y=coords(1,2,1);
%get the line's existing coordinates and append the new ones.
lastx=get(r,'xdata');
lasty=get(r,'ydata');
newx=[lastx x];
newy=[lasty y];
set(r,'xdata',newx,'ydata',newy);
function done_pencil(src,evendata)
%all this funciton does is turn the motion function off
set(gcf,'windowbuttonmotionfcn','')
set(gcf,'windowbuttonupfcn','')
% --- Executes on button press in SaveButton.
function SaveButton_Callback(hObject, eventdata, handles)
% hObject handle to SaveButton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% sauvegarde de l'image
f = getframe(gca);
im = frame2im(f);
imwrite(im,'image2.png');
My code is in the attach file
Thank you
Rémy
Answers (1)
Geoff Hayes
on 6 Jun 2018
Rémy - try assigning the buttondownfcn to your handle to the image that you wish to draw upon. For example, in your OpenButton_Callback you would do
handles.hImg = imshow(Foto,RI);
guidata(hObject, handles);
So we update the handles structure with the handle to your image (presumably this is the one that you want to draw upon...it is unclear since you seem to show two images maybe on teh same axes?) and then we save the updated handles structure by calling guidata(...).
Now, in your DrawButton_Callback you would do
set(handles.hImg,'buttondownfcn',{@start_pencil, handles.axes1})
Note how we assign the callback to the image handle and
{@start_pencil, handles.axes1}
In the above, we are passing the axes handle as an additional parameter to the start_pencil callback. And so the start_pencil becomes
function start_pencil(src,eventdata, hAxes)
coords=get(hAxes,'currentpoint');
% etc.
Try the above and see what happens!
I guess the real problem here is that the image is placed on top of your axes and so swallows the mouse button down event i.e. prevents the axes (beneath the image) from getting the mouse button down event. So we do the above so that the image acts upon the mouse button down event. Alternatively, you could leave your code as is and turn off the ability of the image to swallow/capture the mouse button down event
set(handles.hImg, 'HitTest', 'off');
If you just add this one line of code, your app should work fine without the other changes discussed above. Please see Capturing Mouse Clicks for more details. In particular is the statement
HitTest — Determines if the object can respond to the mouse click it captures or passes the click to its closest ancestor.
1 Comment
Geoff Hayes
on 7 Jun 2018
Rémy's answer moved here
Thank you very much ! I will try with your notes :)
Categories
Find more on Interactive Control and Callbacks in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!