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
Related
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.
In Matlab GUI, I need a user mouse input as a rectangle that I have to plot on the axes1.
For this, I have code below:
axes(handles.axes1);
filename = 'A';
img = imread(filename);
imshow(img);
hold on;
rect_cord = getrect(handles.axes1);
rectangle('Curvature', [0 0],'Position', [rect_cord],'EdgeColor',[1 0 0]);
This code runs fine (takes user input and plots the rectangle). However, for some images I don't want to get the user input from mouse (using getrect). In this case, how to skip the getrect function and move on to next image?
I have a pushbutton ("next"), I want to show next image when push button is pressed instead of taking user input.
Thanks,
I will try to rephrase and modify a bit: you want to draw a rectangle only if one clicks on the axes or image.
Therefore:
First of all I would suggest to put the getrect-part into another function. This function should only be triggered if one clicks on the image. The so called "ButtownDownFcn" seems to be suitable for this job. When using GUIDE, you will find it double-clicking on the axes within the property-inspector that is popping up.
Then put the getrect-part into this function:
function axes1_ButtonDownFcn(hObject, eventdata, handles)
% hObject handle to axes1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
rect_cord = getrect(handles.axes1);
rectangle('Curvature', [0 0],'Position', [rect_cord],'EdgeColor',[1 0 0]);
Now I thought that this is all that has to be done. But testing this with a plot or image within the axes prooved me wrong :o
Sadly one has to redirect the children of the axes to this function, because by default, it is only assigned to the background of the axes (=the blank axes).
by searching the net, I found the following solution here:
Matlab in Chemical Engineering: Interacting with your graph through mouse clicks
It works like this:
when plotting the image, you have to add the line
% and we also have to attach the function to the children, in this
% case that is the line in the axes.
set(get(gca,'Children'),'ButtonDownFcn', #mouseclick_callback)
Hope that helps!
I have a piece of code that is 300 lines long. There is 3 different instances of imshow throughout the code that displays figures as the code is run..
The GUI I am creating will be very simple. Currently I have a push button that initiates the m file.
I am trying to get the images to be displayed within the GUI that I am creating and not in separate Figure windows.
I have being looking at tutorials online but cant get a quick fix for my problem, they all get a bit convoluted and I cant figure out what exactly to do.
I have 3 axis inserted onto the GUI, In the "view callbacks" for each axis I can createfcn, deletefcn and buttonDownFcn. When I createFcn it gives me a hint to "place code in OpeningFcn to populate axes1" in the auto generated code.
I have tried to do this but I am not able to find the correct place to write the code.
Can somebody tell me if I am going in the correct direction or if I have it wrong.
Thanks
In order to display these images, you need to declare the parent in imshow. The parent is what you want to act as the canvas for your image, and in your case will be an axes.
I created a very simple gui with three axes and a push button. MATLAB named my axes axes1, axes2 and axes3. Guide saves the handles to these axes so that you can interact with them throughout your gui code. For example, you mentioned the opening function... here is mine with a call to imshow (the only lines I added were the last three ones):
% --- Executes just before myGUI is made visible.
function myGUI_OpeningFcn(hObject, eventdata, handles, varargin)
% Choose default command line output for myGUI
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes myGUI wait for user response (see UIRESUME)
% uiwait(handles.figure1);
imshow('myImage1.png', 'Parent', handles.axes1)
imshow('myImage2.png', 'Parent', handles.axes2)
imshow('myImage3.png', 'Parent', handles.axes3)
Notice that I can grab the handles of my axes and then declare them to be the parents for the results of my imshow call.
If you're not sure what the names of your handles are, you can check in the GUI editor by right clicking, looking at the property inspector, and the tag property.
If you want to perform a similar operation for when you click on your pushbutton, right click on the button in the editor, and click on View Callbacks -> Callback, and you can add your imshow code there.
Good luck.
If I understand correctly you just want your images to appear in the axes instead of a figure. Try setting the focus to the axes itself before showing the image.
axes(1);%you may need to change the one to your axes handle.
imagesc(imageToBeDisplayed);
axes(2);
imagesc(secondImage);
axes(3);
imagesc(thirdImage);
This way before you call imagesc you make sure your program knows where to send the image. Otherwise it may just create a figure.
With Guide I made a Matlab Gui that have 10 Axes in which i want to display images, in all of them at once, after i press a Button.
I made a separate .m file with function Load_Write_Img_Results(img_index) that i call from the Button Callback which have the following code:
for i = 1 : 10
handles_imgOut = findobj('Tag', ['imgOut' num2str(i)]);
set(handles_imgOut, 'HandleVisibility', 'ON');
axes(handles_imgOut);
image(imgs_data{img_index(i)});
...
end
Every time when i run the main Gui and press the button for the first time, images are displayed in all axes, so everything works ok.
The problem appear when i press the button for the second time and i get this error:
Error using axes
Invalid object handle
on this line:
axes(handles_imgOut);
When debugging, i saw that after handles_imgOut = findobj('Tag', ['imgOut' num2str(i)]); the handles_imgOut is not getting any value and is empty, so it's obvious that error.
Is there any chance i can't get handles for axes at the second press of the button?
Also, i want to know how can i solve this warning from Matlab:
Calling AXES(h) in a loop can be slow. Consider moving the call to AXES outside the loop.
Thanks in advance, any suggestions are welcome!
[SOLUTION]:
for i = 1 : 10
handles_imgOut = findobj('Tag', ['imgOut' num2str(i)]);
set(handles_imgOut, 'HandleVisibility', 'ON');
axes(handles_imgOut);
image(imgs_data{img_index(i)});
set(gca, 'Tag', ['imgOut' num2str(i)]); //! renew the tag
...
end
I'm fairly new to GUIDE and I've encountered similar problems, with the graph not being updated more than once / axes not found.
In the end, I used the following approach, which I hope can be useful to you too:
% I get my axes directly from the handles object, instead of using findObj:
graph1 = handles.axes1;
graph2 = handles.axes2;
% clear axes
cla(graph1);
cla(graph2);
% showTrial is my function that draws the graphs -
%notice that I used handles to store other variables as well (.data, .trials)
showTrial(handles.data, handles.trials(1), graph1, graph2)
To sum it up:
don't use findObj, get your axes from handles (it should automatically contain them as imgOut1,imgOut2, etc.)
pass the axes to your drawing function or pass directly the handles variable e.g. Load_Write_Img_Results(img_index, handles)
The fact that it works on the first button press, but not thereafter hints that
image(imgs_data{img_index(i)});
opens new axes instead of drawing into the existing ones. Since the new axes are not initialized with your tags, findobj will not find them. Either
(1) make sure to hold the original axes by placing a hold on command right after their creation,
or
(2) renew the tag right after the image command by
set(gca, 'Tag', ['imgOut' num2str(i)]);
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.