MATLAB ButtonDownFcn - matlab

I have a project of "Optical Character Recognition" in MATLAB and i need your help:
how do i recognize when the user press the mouse on an image?
i trying to do this with ButtonDownFcn but even when i just printing message
the message is not printed.
i want to allow the user to select the license plate from the image.
how can i do this and save the Pixels of the selected area?
thanks in advance.

Addressing your two questions:
I'm guessing that you are trying to set the 'ButtonDownFcn' of the figure window, which won't work how you expect it to. If you want to do something when the user clicks on an image, you should make sure that you're setting the 'ButtonDownFcn' of the image, and not the figure window or the axes object. Note this line in the figure property documentation (emphasis added by me):
Executes whenever you press a mouse button while the pointer is in the figure window, but not over a child object (i.e., uicontrol, uipanel, axes, or axes child).
This is why you have to set a 'ButtonDownFcn' for each object you want it to work for. Setting it for the figure window won't make it work automatically for each object in the figure. Here's an example that sets the 'ButtonDownFcn' for the figure and an image object:
img = imread('peppers.png'); %# Load a sample image
hFigure = figure; %# Create a figure window
hImage = image(img); %# Plot an image
set(hFigure,'ButtonDownFcn',... %# Set the ButtonDownFcn for the figure
#(s,e) disp('hello'));
set(hImage,'ButtonDownFcn',... %# Set the ButtonDownFcn for the image
#(s,e) disp('world'));
Notice how clicking inside and outside the image displays a different message, since each calls the 'ButtonDownFcn' for a different object. Notice also that if you click on the tick mark label of one of the axes, nothing is displayed. This is because the axes object has its own 'ButtonDownFcn', which wasn't set to anything.
If you have access to the Image Processing Toolbox you can use the function IMFREEHAND to have the user draw an ROI (region of interest) in the image. Then you can use the createMask method to create a binary mask of the image with ones for pixels inside the ROI and zeroes for pixels outside the ROI.

Related

How can I prevent objects from blocking ButtonDownFcn callback in a figure?

I have a plot of an image, made with imagesc. I'm developing a workflow where a user can click on the image and interactively overlay a curve. My first issue was that the ButtonDownFcn for the figure is blocked by the image. I worked around this by setting the ButtonDownFcn on the image object instead (and walking back up the parents to get to the figure). Now I'm finding that the curve I'm plotting can also block callbacks intended for the image.
My searches have indicated that I should be able to disable the "hittest" property to prevent the problem, but this has been ineffective for both the image and plotted lines. Suggestions?
Example:
file 1
function testCallback(src,data)
disp('Hello')
file 2
fig = imagesc(rand(100,100));
set(fig,'ButtonDownFcn',#testCallback);
hold on
plot([0 100],[0 100],'m-','linewidth',5,'hittest','off')
Unable to trigger callback when clicking on the line.
You could also set the button down function for the line that you add. Change your plot command to this:
plot([0 100],[0 100],'m-','linewidth',5,'ButtonDownFcn',#testCallback)

How to use "ButtonDownFcn" in a populated GUI axes?

I have a very simple GUI made in guide where i have a plot function initiated by a pushbutton which plots a scatter plot in axes (called Method1axes1):
handles.plot = scatter(X,Y, 'parent', handles.Method1axes1);
Now I want the user to be able to click the axes (plot) to get en new larger figure. I tried the below code which is working if i DON'T plot in the axes first. As soon as I run the plot function the scatterplot appears in Method1axes1 but I can no longer click the figure.
% --- Executes on mouse press over axes background.
function Method1axes1_ButtonDownFcn(hObject, eventdata, handles)
figure
scatter(X,Y);
What am I doing wrong?
This is a kind of special case for MATLAB, and it is not extremely well documented.
There are 2 things you need to consider:
1) The most obvious part. When you plot something in your axes, the plot is on the foreground. So when you click on your axes, the top plot intercept that click and tries to process it. You need to disable the mouse click capture from the plot/scatter/image objects you have in your axes. For that, you have to set the HitTest property of your scatter object to 'off'. (recent MATLAB version have changed the name of this property, it is now called PickableParts).
2) Much less obvious and documented. It used to be in the doc for the axes ButtonDownFcn callback but it is not explained anymore (although the behaviour persist). This is what I could find on old forums:
When you call PLOT, if the axes NextPlot property is set to 'replace'
(which it is by default) most of the properties of the axes (including
ButtonDownFcn) are reset to their default values.
Change the axes NextPlot property to 'replacechildren' to avoid this,
or set the ButtonDownFcn after calling PLOT, or use the low-level LINE
function instead of the higher-level PLOT function.
This is also discussed and explained here: Why does the ButtonDownFcn callback of my axes object stop working after plotting something?
For your case, I tried set(axe_handle,'NextPlot','replacechildren') and it works ok to let the mouse click reach the ButtonDownFcn, but unfortunately it creates havoc with the axes limits and LimitModes ... so I opted for the second solution, which is to redefine the callback for ButtonDownFcn after every plot in the axes.
So in summary, your code for the pushbutton1_Callback should be:
function pushbutton1_Callback(hObject, eventdata, handles)
% Whatever stuff you do before plotting
% ...
% Plot your data
handles.plot = scatter(X,Y, 'parent', handles.Method1axes1);
% Disable mouse click events for the "scatterplot" object
set(handles.plot,'HitTest','off') ;
% re-set the "ButtonDownFcn" callback
set(handles.Method1axes1,'ButtonDownFcn',#(s,e) Method1axes1_ButtonDownFcn(s,e,handles) )
And for your axes mouse click event, you might as well keep the handle of the new generated objects:
function Method1axes1_ButtonDownFcn(hObject, eventdata, handles)
handles.newfig = figure ;
handles.axes1copy = copyobj( handles.Method1axes1 , handles.newfig ) ;
Note that instead of plotting a new set, I simply use the copyobj function, very handy when you need to reproduce a plot.
Illustration:
If you want to set the figure/graph to enlarge and shrink on mouse
scroll/click, then just set the zoom property of the required axes in
OpeningFcn within the m file.
For example within the OpeningFcn in the GUI's m file, put the below code. Please ensure that you put the below code within the OpeningFcn function.
h1 = zoom(handles.Method1axes1);
h1.Enable = 'on';
Now, on each mouse scroll/click, you would be able to zoom in/out the graphs.
A sample screenshot of openingFcn for a GUI named ZoomAxesDemo is given below.

How to Zoom in multi-axes in the same time in matlab GUI?

I have a GUI with two axes. The first one for original image while the second one is for interpolated image.
First in my code, I use imrect to select part of the original image and then I crop that part using imcrop . After that I display the cropped image in both axes.
What I want is to know how to zoom in the first axes (the original image) and it shows the same zooming the second axes ( interpolated image ) automatically.
Thanks a lot in advance.
It is not clear the relationship between the two actions you mention in your question:
using imrect and imcrop to work on the image
zooming on one axes and have the same zoom on the second
A possible solution to automatically apply the zoom made on the first axes to the second one could be using the linkaxes built-in function.
If in your GUI you have two axex with, respectively, tag axes1 and axes2, you can add the following statements in the GUI OpeningFcn
linkaxes([handles.axes1 handles.axes2])
This allows automatically applying the zoom you make on axes1 also to axes2.
Hope this helps.

How to use effectively radio buttons in a button group MATLAB GUI

I have 5 different filters as 5 different radio buttons in MATLAB GUI. I made them into a button group and now when i click the each button the noise image is shown through the axes. But i want to set the button group in such a way to show only one filter (one image). So, I followed this
(How to pass function to radio button in a button group created using guide in MATLAB?) which is given here at stackoverflow. But how do we "set" image in an axes.
I have attached the figure of my GUI.enter image description here
Thanks in advance
You "set" the image in an axes object using the normal plotting commands. Suppose the variable ax holds the handle to the axes object you want to draw on, you could write the following:
axes(ax); % Select the chosen axes as the current axes
cla; % Clear the axes
imagesc(im); % Now draw whatever you want - for example, an image.
Incidentally, in GUIDE you can get usually get the axes handle using the handles argument passed to all callbacks. So for example, if your axes are called axes1, your Button Group callback might look like this:
function uipanel1_SelectionChangeFcn(hObject, eventdata, handles)
ax = handles.axes1; % Get handle to axes
axes(ax); % Select the chosen axes as the current axes
cla; % Clear the axes
imagesc(rand(50) ); % Now draw

MATLAB hide datacursor box when using datacursor

I'm using MATLAB to create a GUI. I have an image on which the datacursormode is enabled. This works fine, every time I click a new point is added. For every point MATLAB displays a box with the coordinates (or whatever other text, I modified it using an update function). But how can I remove this text box, I just want a point to be added, no extra information should be displayed?
Thanks!
datacursormode on is used to enable data tip display on a graphic object. In other words that text box you want to hide. What the reason then to use datacursor?
Are you using UpdateFcn of data cursor to "add pixel" (you probably mean to change pixels color)? Consider using ButtonDownFcn callback function instead.
function interactive_image(im)
fh = figure;
hImage = imshow(im);
set(hImage,'ButtonDownFcn',#myfunction)
end
function output_txt = myfunction(obj,eventdata,handles)
pos = get(gca,'CurrentPoint')
x = get(obj,'CData');
x(uint32(pos(1,2)),uint32(pos(1,1))) = 0;
set(obj,'CData',x)
end
UPDATE:
According to your comment you better to use IMPOINT function available in Image Processing Toolbox.