I am using Matlab's GUIDE for the first time, I am trying to edit one of the two push button functions (both open an image), but editing one changes all of them. Here is a bit of code:
% --- Executes on button press in Floating.
function Floating_Callback(hObject, eventdata, handles)
clc;
axes(handles.axes1);
[Float, PathName, FilterIndex] = uigetfile('*.bmp');
if(Float ~= 0)
Floating = fullfile(PathName, Float);
FloatArray = imread(Floating);
imshow(FloatArray);
axis on;
end
% Update handles structure
guidata(hObject, handles);
% hObject handle to Floating (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% --- Executes on button press in Reference.
function Reference_Callback(hObject, eventdata, handles)
clc;
axes(handles.axes2);
[Ref, PathName, FilterIndex] = uigetfile('*.bmp');
if(Ref ~= 0)
Reference = fullfile(PathName, Ref);
ReferenceArray = imread(Reference);
image(ReferenceArray);
end
% Update handles structure
guidata(hObject, handles);
For example,
image(ReferenceArray)
will open an image in RBG, but
imshow(FloatArray)
will open in grayscale (I also do not understand why that is). But my main concern is after opening up
imshow(FloatArray)
the other image will automatically turn grayscale. I am very confused... Also, as far as I know the images ARE already grayscale, at least they are when I open them in MS paint or ImageJ.
It would be better to explicitly specify the parent handle whenever you are doing GUI stuff. For example:
imshow(img, 'Parent',handles.ax1)
and
axis(handles.ax1, 'on')
As for images and colormaps, you should understand the type of images MATLAB supports (indexed vs. truecolor). Also note that a figure has only one colormap applied to all images, although there are techniques to overcome this.
Related
I am attaching a sample GUI codes, which has two axes with 2 images and when I use ginput to select seed point I am able to select on either axes, Is there anyway to limit the ginput to a specific axes
% --- Executes on button press in open.
function open_Callback(hObject, eventdata, handles)
% hObject handle to open (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
global img1;
global img2;
img1 = imread('peppers.png');
img2 = imread('rice.png');
axes(handles.axes1);
imshow(img1,[]);
axes(handles.axes2);
imshow(img2,[]);
% --- Executes on button press in seedpointSelect.
function seedpointSelect_Callback(hObject, eventdata, handles)
% hObject handle to seedpointSelect (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
global img1;
global img2;
global x;
global y;
axes(handles.axes1);
imshow(img1,[]);
[y,x] = ginput(handles.axes1);
y = round(y); x = round(x);
set(handles.xcord,'String',num2str(x));
set(handles.ycord,'String',num2str(y));
Any help on limiting ginput to a specific axes,
Thanks,
Gopi
In older versions of MATLAB you used to be able to change the HitTest property of the axes to ignore the click from ginput
set(handles.axes2, 'Hittest', 'off')
The better approach though is to use ButtonDownFcn as you have much more control over mouse events with an axes object.
From within your OpeningFcn
set(handles.axes1, 'ButtonDownFcn', #mouseCallback)
Then you'll need to create the callback function
function mouseCallback(src, evnt)
handles = guidata(src);
% Get the current point
xyz = get(src, 'CurrentPoint');
x = xyz(1,1);
y = xyz(1,2);
% Store x/y here or whatever you need to do
end
Don't use ginput, create a mouse click callback instead (ButtonDownFcn). You can set the callback to, for example, remove the callback function from the axis. In your main program, which sets the callback, you then waitfor that property to change. As soon as the user clicks, you get control back, and you can then read the location of the last mouse click (CurrentPoint). Note that the position you read out is in axis coordinates, not screen pixels. This is a good thing, it most likely corresponds to a pixel in the image displayed.
So I'm building a classifier of images. In the GUI a image loads and insert a value on a text box, and push a button. I'm having a problem loading the image in the axes. Because when the axes function is called the handles is zero(due to:% handles empty - handles not created until after all CreateFcns called). And my problem is, how do I get to just call one image at a time for the axes.
The ideal solution, is I create a handles.images=imagedatastore, and every time I push the button I add to a counter(which I already have made) and then that give the indices to get the image from the datastore. My problem with this is that I can't get the first picture, because in the beginning the handles are empty. I have made the callfunction for the axes:
% --- Executes during object creation, after setting all properties.
function axes1_CreateFcn(hObject, eventdata, handles)
% hObject handle to axes1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
[pict_croped,Nphotos,Date_img] =getcropedimagages;
handles.img =pict_croped;
i=readimage(handles.img,1);
% axes(hObject)
imshow(i)
% Hint: place code in OpeningFcn to populate axes1
but this has two problems, first, I don't really want to call the function that creates the datastore all the time I push the button, second, I still can't get the indice of the counter to be in the function,if I have:
i=readimage(handles.img,handles.counter)
it will give me the error in the first time, of not having handles.counter
Any idea how to solve this?This is the first GUI I'm building.
The issue is very clearly in the comment that GUIDE provides for you. The handles struct isn't populated until all CreateFcn have been run so you'll want to use the OpeningFcn to do any initialization of the graphics objects. You can then add any data you need to the handles struct and save it using guidata so that it's available from within all of your other callback functions.
function OpeningFcn(hObject, eventData, handles)
[pict_croped,Nphotos,Date_img] = getcropedimagages;
handles.img = pict_croped;
i = readimage(handles.img,1);
imshow(i, 'Parent', handles.haxes1)
% "Save" the changes to the handles object
guidata(hObject, handles)
Well, I end up with:
in the opening fucntion:
i = readimage(handles.img,handles.counter);
imshow(, 'Parent', handles.axes1)
and in the button call back:
i = readimage(handles.img,handles.counter);
imshow(i, 'Parent', handles.axes1)
inthe end is a very simple solution, I think I was just mind blocked over the first iteration...
I'm working on a program and have decided to build a GUI around it. What I'd like to start with is pretty simple, load up a movie and be able to scroll through it. I've looked at a lot of the questions regarding listeners, and in fact someone asked this question but the solution there didn't seem to work for me.
in my opening function of the gui I have
handles.output = hObject;
handles.sliderListener = addlistener(handles.Image_Slider,'ContinuousValueChange', ...
#(hObject, event) Image_Slider_ContValueCallback(...
hObject, eventdata, handles));
% Update handles structure
guidata(hObject, handles);
And then I have the following two call backs :
function Image_Slider_Callback(hObject, eventdata, handles)
% hObject handle to Image_Slider (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
handles=guidata(hObject);
current_slice = round(get(handles.Image_Slider,'Value'));
%size(handles.Image_Sequence_Data(:,:,current_slice));
im =imagesc(handles.Image_Sequence_Data(:,:,current_slice),'Parent',handles.Image_Sequence_Plot);
colormap('gray');
which works fine (without the listener everything behaves properly)
AND then I also have
function Image_Slider_ContValueCallback(hObject, eventdata, handles)
% hObject handle to Image_Slider (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
handles=guidata(hObject);
current_slice = round(get(handles.Image_Slider,'Value'));
%size(handles.Image_Sequence_Data(:,:,current_slice));
handles=guidata(hObject);
%im =
imagesc(handles.Image_Sequence_Data(:,:,current_slice),'Parent',handles.Image_Sequence_Plot);
colormap('gray');
which I think should be called when the slider is moved continuously. My issue is that EACH time the slider value is changed a blank ("figure 1") appears. The actual GUI data responds correctly, but I don't understand why/where this 'rogue' figure is coming from..
someone please help. Also, any opinions on imshow vs. imagesc as to which is better (this GUI will involve a lot of user interaction with the image)
I had pretty much the same problem once! I don't have access to Matlab right now so I can't test a working example , but for the moment I would suggest to place this line:
handles.sliderListener = addlistener(handles.Image_Slider,'ContinuousValueChange', ...
#(hObject, event) Image_Slider_ContValueCallback(...
hObject, eventdata, handles));
in the CreateFcn of your slider. Maybe a blank figure appears each time you move the slider since it does not know that it's linked to a listener object and thus creates one continuously.
If it does not work, you can call a function outside of the GUI to update the current frame displayed in your axes, for instance:
handles.sliderListener = addlistener(handles.Image_Slider,'ContinuousValueChange', ...
#(a,b) UpdateCurrentFrame);
instead of the callback in your GUI. a and b are dummy input arguments and UpdateCurrentFrame can simply contain a call to imshow for example. It might not be the most elegant way but it worked perfectly for me.
Oh and as for your question about imagesc and imshow, I personnally prefer imshow. In my case, I used text annotations and rectangles for ROI selection and so on, and had little problems with imagesc in terms of images not updating correctly or rectangles being stuck...but it might be that I was not using it correctly though.
Hope that helps!
I am quite new to MATLAB GUI programming (using GUIDE sorry) and I have the following issue: The GUI displays on an axis an image sequence stored in a cell array. I have a couple of pushbuttons and a slider to scroll through the sequence. In order to get a 'continuous slider' I use a listener, which kind of works but creates some problems:
1) When I press the slider, a figure is created and the first frame of the sequence is displayed in it, but as I move the slider the sequence is displayed in the axis of my GUI (which is what I want) and the figure becomes empty. Can anybody tell me why this figure is created and how can I avoid it?
2) Once I press the slider button and thus use the listener, all handles inside the GUI are not functionnal as Matlab does not recognize them and I'm stuck with a functionnal slider/display but I can't use the pushbuttons.
Any ideas on why this happens? Here is the code I use in the Create Function of the slider:
function slider2_Frame_Video_Callback(hObject, eventdata, handles)
hListener = addlistener(hObject,'ContinuousValueChange',#(a,b) slider2_Frame_Video_Callback(hObject, eventdata, handles)); % a and b are dummy arguments
guidata(hObject,handles)
In the slider callback, the code looks like this (basically imshow in the current axis):
axes(hAxis)
imshow(Movie{frame},'parent',hAxis);
drawnow
% This does not work either as handles.edit_FrameNumber is not recognized by Matlab
set(handles.edit_FrameNumber, 'String', frame);
guidata(hObject,handles);
Any hints are welcome thanks!
I wonder if part of the problem is that a listener is being instantiated each time the user moves the slider since the listener code is within this callback AND that the callback being provided to the listener (seems like some kind of strange back-and-forth there). So every time the user releases the mouse button after a slide, a new listener is created. This may be causing some problems with the other buttons not being responsive.
Rather than instantiating the listener there, I would do this in the Opening_Fcn of your GUI:
% --- Executes just before frameSlider is made visible.
function frameSlider_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 frameSlider (see VARARGIN)
% Choose default command line output for frameSlider
handles.output = hObject;
if ~isfield(handles,'hListener')
handles.hListener = ...
addlistener(handles.slider1,'ContinuousValueChange',#respondToContSlideCallback);
end
% Update handles structure
guidata(hObject, handles);
My GUI is named frameSlider; yours will be something else. The above creates one listener with a callback to a function that you will need to define in the same *.m file, respondToContSlideCallback.
A sample body for the callback that is to respond to the continuous slide is
% --- Executes on slider movement.
function respondToContSlideCallback(hObject, eventdata)
% hObject handle to slider1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% Hints: get(hObject,'Value') returns position of slider
% get(hObject,'Min') and get(hObject,'Max') to determine range of slider
% first we need the handles structure which we can get from hObject
handles = guidata(hObject);
% test to display the current value along the slider
disp(['at slider coordinate ' num2str(get(hObject,'Value'))]);
If you run this code, the Command Window will display continuously the slider coordinate as you move the slider from end to end.
Your above code has a Movies cell array. How is that being accessed by your callback? Is it a global variable or ..? Where does hist come from? If Movies is the result of some other function call, then it can be saved to handles too (in whichever location it gets loaded from file). I suppose you will also have to map the slider control coordinates to the number of frames that you have (though maybe you have already done this?).
I want to program the 'axes1' section of a new GUIDE project in a way that it scatters the points inside the axes when the user clicks on them.
I am new to GUIDE and I don't fully understand how hObjec, handles, etc. work. What I have gathered so far from other posts is the following piece of code:
% --- Executes on mouse press over axes background.
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)
%axesHandle = get(hObject,'Parent');
coordinates = get(hObject,'CurrentPoint');
coordinates = coordinates(1,1:2);
scatter(coordinates(1),coordinates(2));
I am not using the 'get(hObject,'Parent')' section because that was used in the case you use an image to display in the axes and that is not my case.
Can someone please explain how can I do this?
Thanks in advance for your time
I solved this months ago but I didn't post the solution!
It was easier than I thought, I just had to store each mouse press as a (x, y) point and then use plot:
% ND = Nodes in the network
ND = zeros(N,2);
ND(1,:) = ginput(1);
plot(ND(1,1),ND(1,2),'ko','MarkerSize',12);
hold on;
for i=2:N
ND(i,:) = ginput(1);
plot(ND(i,1),ND(i,2),'ko','MarkerSize',12);
end