MATLAB GUIDE button must be pressed twice? - matlab

I'm making a GUI with guide. I have a push button the user clicks and the callback is as folows : (what matters are the tirst two lines really...
function SetParticleRoiSize_Callback(hObject, eventdata, handles)
% hObject handle to SetParticleRoiSize (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);
particleroiSize=imrect;% - draw a rectagle around the particle to get a meausr eof ROI size
roiPoints=getPosition(particleroiSize); %-get tha parameters fo the rectanlge
partX1 = round(roiPoints(1));
partY1 = round(roiPoints(2));
partX2 = round(partX1 + roiPoints(3));
partY2 = round(partY1 + roiPoints(4)); % these are the ROi positions in pixels
roiHeight = round(roiPoints(3)); % - these are just the ROI width and height
roiWidth = round(roiPoints(4));
handles=guidata(hObject); %_ update all the handles...
handles.partX1=partX1;
handles.partX2=partX2;
handles.partY1=partY1;
handles.partY2=partY2;
handles.roicenterX = (partX1 + round(roiPoints(3))/2);
handles.roicenterY= (partY1 + round(roiPoints(4))/2);
handles.roiHeight = roiHeight;
handles.roiWidth = roiWidth;
current_slice = round(get(handles.Image_Slider,'Value'));
handles.current_slice=current_slice;
particleImage=handles.Image_Sequence_Data(partY1:partY2,partX1:partX2,current_slice);
handles.particleImage=particleImage;
set(handles.RoiSizeDisplay,'String',['Particle ROI is ',' ',num2str(roiHeight),' ', ' by ',num2str(roiWidth)] );
guidata(hObject,handles); %- at this point we now have the particle in the roi and the size of the roi stored.
The issue I am having is that when the user clicks the button the first time, nothing happens (i.e. the imrect line seems to not get called at all). When the user clicks the button again then they can draw a rectangle on the image but my program throws out an error
Error in imrect (line 83)
[h_group,draw_api] = imrectAPI(varargin{:});
Error in SemiAutomated_Fionv2p2_5>SetParticleRoiSize_Callback (line 291)
particleroiSize=imrect;% - draw a rectagle around the particle to get a meausr eof ROI size
Error in gui_mainfcn (line 96)
feval(varargin{:});
Error in SemiAutomated_Fionv2p2_5 (line 56)
gui_mainfcn(gui_State, varargin{:});
Error in
#(hObject,eventdata)SemiAutomated_Fionv2p2_5('SetParticleRoiSize_Callback',hObject,eventdata,guidata(hObject))
Error while evaluating uicontrol Callback
I guess the error is because there is no imrect created on the first button click.
Can someone please explain to me why this button needs to be clicked twice to work? (and even then it still gives an error...)
thanks...
-j

It looks like this call:
handles=guidata(hObject); %_ update all the handles...
is incorrectly used; you might need to replace it with guidata(hObject,handles) in order to actually update the handles structure. Moreover, since you already call guidata(hObject,handles) at the end of the callback you can delete this line altogether I think.
As it's currently implemented, you:
1) get the handles structure with handles = guidata(hObject);
2) store information in it
particleroiSize=imrect;% - draw a rectagle around the particle to get a meausr eof ROI size
roiPoints=getPosition(particleroiSize); %-get tha parameters fo the rectanlge
partX1 = round(roiPoints(1));
partY1 = round(roiPoints(2));
partX2 = round(partX1 + roiPoints(3));
partY2 = round(partY1 + roiPoints(4)); % these are the ROi positions in pixels
roiHeight = round(roiPoints(3)); % - these are just the ROI width and height
roiWidth = round(roiPoints(4));
3) then call it again (handles = guidata(hObject))`.
Hence on your second call to retrieve the data you have not previously updated it, so I guess Matlab does not like it.
It might not be the specific cause of your error but I think it's worth checking.

I had 3 different axes in my figure. The first version of the program only had 1 axes so it worked fine. After adding the other axes to the GUI (via GUIDE) when I ran just imrect.. I think it was not choosing the axes I wanted..I added a parent handles.correct axes and now it works perfectly!

Related

Error: Missing multiplication operator, missing or unbalanced delimiters. To construct matrices, use brackets instead of parentheses

am trying to design an interface using the MATLAB APP DESIGNER. However, I am getting an error message.
This is for creating a user interface in using MATLAB APP DESIGNER
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function startupFcn(app, varargin)
% Configure image axes
app.ImageAxes2.Visible = 'off';
app.ImageAxes.Colormap = gray(256);
axis(app.ImageAxes, 'image');
app.ImageAxes3.Visible = 'off';
app.ImageAxes.Colormap = gray(256);
axis(app.ImageAxes, 'image');
end
% Callback function
function DropDownValueChanged(app, event)
% Update the image and histograms
updateimage(app, app.DropDown.Value);
end
% Callback function
function LoadButtonPushed(app, event)
% Display uigetfile dialog
filterspec = {'*.jpg;*.tif;*.png;*.gif','All Image Files'};
[f, p] = uigetfile(filterspec);
% Make sure user didn't cancel uigetfile dialog
if (ischar(p))
fname = [p f];
updateimage(app, fname);
end
end
I expected the user interface to be displayed after running the simulation. But I am getting the following error message:
"Missing multiplication operator, missing or unbalanced delimiters. To construct matrices, use brackets instead of parentheses".
The errors point to the line that uses the METHODS function. However, that particular line in MATLAB APP DESIGNER code view is gray in color. As a result, I am unable to edit that particular line. Any suggestion would be appreciated.

Matlab: display crosshairs simultaneously on two images in GUI

I'm building a MATLAB GUI using GUIDE for processing medical images (brain tumor segmentation on MRI scans). As a preprocessing step, the program coregisters different scans, which looks like this:
I now want to display crosshairs on both images as a visual check of the coregistration. The crosshairs should be linked to one another, such that they point to the same pixel in both images. Moreover, it should move when hovering over (or clicking on) one of the images. This is what I want to achieve:
Does a build-in MATLAB function exist that can achieve this? Or, if I have to write it myself, how would one tackle this problem?
I'll use a Toy GUI in order to show how it works :
Let's first try to make it work for the first image only. What you want to achieve is :
When the user clicks on the figure, we want to have access to the location of the mouse click.
Then we want to check if the click was located inside the first image
If it is, we want to update the position of the crossbar, which will be represented by two lines overlayed on the image and crossing at the selected point.
Step 0 : Initial settings
You want to make sure of some details first :
Make sure you add a call to hold on after both your imshow calls, otherwise the crossbars will delete your image instead of overlaying on it.
Step 1 : Getting the position of the mouse click
In your GUI opening function (here it will be SuperDuperGUI_OpeningFcn), you want to add a call to :
set(gcf, 'WindowButtonDownFcn', #getMousePositionOnImage);
This will trigger the function getMousePositionOnImage everytime the user clicks inside your GUI.
Then, you want to add and implement the function getMousePositionOnImage :
function getMousePositionOnImage(src, event)
% Fetch the current handles structure
handles = guidata(src);
% Get the coordinate IN THE AXES UNITS OF AXES1 (Here I chose to define them
% as pixels) of the point where the user clicked
cursorPoint = get(handles.axes1, 'CurrentPoint')
Step 2 : Check if the mouse click is inside the first image
Still in the getMousePositionOnImage function :
% Get the Position of the first image (We're only interested by the width
% and height of the axes1 object)
Img1Pos=get(handles.axes1,'Position')
% Check if inside
if(cursorPoint(1,1)<Img1Pos(3)&&cursorPoint(1,2)<Img1Pos(4)&&cursorPoint(1,1)>=0&&cursorPoint(1,2)>=0)
% Do stuff
end
Step 3 : If the click was inside the first image, update the position of the crossbar
% Check if inside
if(cursorPoint(1,1)<Img1Pos(3)&&cursorPoint(1,2)<Img1Pos(4)&&cursorPoint(1,1)>=0&&cursorPoint(1,2)>=0)
Lines=findobj('Type','line','Parent',handles.axes1);
if isempty(Lines)
% If Lines is empty, we need to create the line objects
line([0 Img1Pos(3)],[cursorPoint(1,2) cursorPoint(1,2)],'Color','g','Parent',handles.axes1);
line([cursorPoint(1,1) cursorPoint(1,1)],[0 Img1Pos(4)],'Color','g','Parent',handles.axes1);
else
% If not, we just update the fields XData and YData of both Lines
Lines(1).XData=[0 Img1Pos(3)]; % Unnecessary but I'll leave it there for clarity
Lines(1).YData=[cursorPoint(1,2) cursorPoint(1,2)];
Lines(2).XData=[cursorPoint(1,1) cursorPoint(1,1)];
Lines(2).YData=[0 Img1Pos(4)]; % Unnecessary but I'll leave it there for clarity
end
end
Result :
Now I'll let you do the last part, which involves linking the two crossbars. Instead of only checking if the click was on first image, you'll check both separately. Then, if it is in one of the image, you'll update both crossbar to the position of the click in the right axes object
Edit
The code below is inspired by the answer of BillBokeey, for which I'm very grateful.
First, do steps 0 and 1 of BillBokeey's solution. Then I put this function in my code:
function getMousePositionOnImage(src, event)
% Fetch the current handles structure
handles = guidata(src);
% Get the coordinate IN THE AXES UNITS OF AXES1 (Here I chose to define them
% as pixels) of the point where the user clicked
cursorPoint1 = get(handles.axes2, 'CurrentPoint');
cursorPoint2 = get(handles.axes3, 'CurrentPoint');
% Get the Position of the first image (We're only interested by the width
% and height of the axes1 object)
Img1Pos = getpixelposition(handles.axes2);
Img2Pos = getpixelposition(handles.axes3);
XLim1 = get(handles.axes2, 'XLim');
YLim1 = get(handles.axes2, 'YLim');
XLim2 = get(handles.axes3, 'XLim');
YLim2 = get(handles.axes3, 'YLim');
% Check if inside
if (cursorPoint1(1)<XLim1(2) && cursorPoint1(2)<YLim1(2) && cursorPoint1(1)>=XLim1(1) && cursorPoint1(1)>=YLim1(1))
Lines1=findobj('Type','line','Parent',handles.axes2);
Lines2=findobj('Type','line','Parent',handles.axes3);
if isempty(Lines1)
% If Lines is empty, we need to create the line objects
line(XLim1,[cursorPoint1(1,2) cursorPoint1(1,2)],'Color','g','Parent',handles.axes2);
line([cursorPoint1(1,1) cursorPoint1(1,1)],YLim1,'Color','g','Parent',handles.axes2);
line(XLim2,[cursorPoint1(1,2) cursorPoint1(1,2)],'Color','g','Parent',handles.axes3);
line([cursorPoint1(1,1) cursorPoint1(1,1)],YLim2,'Color','g','Parent',handles.axes3);
else
% If not, we just update the fields XData and YData of both Lines
Lines1(1).XData=XLim1; % Unnecessary but I'll leave it there for clarity
Lines1(1).YData=[cursorPoint1(1,2) cursorPoint1(1,2)];
Lines1(2).XData=[cursorPoint1(1,1) cursorPoint1(1,1)];
Lines1(2).YData=YLim1; % Unnecessary but I'll leave it there for clarity
Lines2(1).XData=XLim2; % Unnecessary but I'll leave it there for clarity
Lines2(1).YData=[cursorPoint1(1,2) cursorPoint1(1,2)];
Lines2(2).XData=[cursorPoint1(1,1) cursorPoint1(1,1)];
Lines2(2).YData=YLim2; % Unnecessary but I'll leave it there for clarity
end
elseif (cursorPoint2(1)<XLim2(2) && cursorPoint2(2)<YLim2(2) && cursorPoint2(1)>=XLim2(1) && cursorPoint2(1)>=YLim2(1))
Lines1=findobj('Type','line','Parent',handles.axes2);
Lines2=findobj('Type','line','Parent',handles.axes3);
if isempty(Lines2)
% If Lines is empty, we need to create the line objects
line(XLim1,[cursorPoint2(1,2) cursorPoint2(1,2)],'Color','g','Parent',handles.axes2);
line([cursorPoint2(1,1) cursorPoint2(1,1)],YLim1,'Color','g','Parent',handles.axes2);
line(XLim2,[cursorPoint2(1,2) cursorPoint2(1,2)],'Color','g','Parent',handles.axes3);
line([cursorPoint2(1,1) cursorPoint2(1,1)],YLim2,'Color','g','Parent',handles.axes3);
else
% If not, we just update the fields XData and YData of both Lines
Lines1(1).XData=XLim1; % Unnecessary but I'll leave it there for clarity
Lines1(1).YData=[cursorPoint2(1,2) cursorPoint2(1,2)];
Lines1(2).XData=[cursorPoint2(1,1) cursorPoint2(1,1)];
Lines1(2).YData=YLim1; % Unnecessary but I'll leave it there for clarity
Lines2(1).XData=XLim2; % Unnecessary but I'll leave it there for clarity
Lines2(1).YData=[cursorPoint2(1,2) cursorPoint2(1,2)];
Lines2(2).XData=[cursorPoint2(1,1) cursorPoint2(1,1)];
Lines2(2).YData=YLim2; % Unnecessary but I'll leave it there for clarity
end
end

Matlab Error: 'Cell contents reference from a non-cell array object.' when using ContinuousValueChange listener

I'm fairly new to MATLAB.
I am trying to add a slider as a ContinuousValueChange listener to continuously display pictures through an axis using GUIDE. I already have the basic functionality of the slider working (i.e. a mouse click in the slider will change the picture accordingly), but I would like to implement continuous updating by dragging the slider.
For some reason, when I try to update the picture using the value from the continuous change I get an error. I peg this error to be strange because I do not receive it when simply clicking on the slider nor do I receive it when I use the next/previous buttons in my GUI
Code:
function slider1_CreateFcn(hObject, eventdata, handles)
handles.sliderListener = addlistener(handles.slider1,'ContinuousValueChange', ...
#(a,b) continuousUpdate(handles));
% function to update displayed picture/counter upon change
function updatePicture(handles)
guiControl = gcf;
files = getappdata(guiControl, 'currentPics');
i = getappdata(guiControl, 'currentCounter');
length = max(size(files));
img = imread(files{i});
imageHandle = imshow(img);
imagesc(img);
% update slider
step = 1/(length - 1);
set(handles.slider1, 'SliderStep', [step step]);
set(handles.slider1, 'Max', length);
function continuousUpdate(handles)
currentValue = get(handles.slider1, 'Value');
setappdata(gcf, 'currentCounter', round(currentValue));
guidata(handles.slider1, handles);
disp(currentValue);
updatePicture(handles);
Error:
Warning: Error occurred while executing the listener callback for event ContinuousValueChange defined for class matlab.ui.control.UIControl:
Cell contents reference from a non-cell array object.
Error in test>updatePicture (line 287)
img = imread(files{i});
Error in test>continuousUpdate (line 582)
updatePicture(handles);
Error in test>#(a,b)continuousUpdate(handles) (line 263)
#(a,b) continuousUpdate(handles));

GUI won't run correct unless radio buttons are cycled through

I've created a GUI that estimates the materials and pricing involved in building a home given a few criteria provided in ui panels with radio buttons as options. The problem is that hitting the go button for the GUI throws errors unless the radio buttons are played with first. I cannot leave my buttons on the selection that they are when the GUI is run. How can I run the .m file and then hit go on the .fig without having to touch anything (aside from filling in the square footage edit box)?
function uibuttongroup3_SelectionChangedFcn(hObject, eventdata, handles)
% hObject handle to the selected object in uibuttongroup3
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
tag = eventdata.NewValue;
switch get(tag,'Tag')
case 'OneHalfBath'
BathRoom = 1
case 'TwoHalfBath'
BathRoom = 2
case 'ThreeHalfBath'
BathRoom = 3
end;
if BathRoom == 1
BathWall = 30
BathSq = 36
elseif BathRoom == 2
BathWall = 48
BathSq = 72
elseif BathRoom == 3
BathWall = 66
BathSq = 108
end;
setappdata(handles.uibuttongroup3,'BathWall',BathWall);
setappdata(handles.uibuttongroup3,'BathSq',BathSq);
setappdata(handles.uibuttongroup3,'BathRoom',BathRoom);
The above is one of four UI panels with radio buttons, just for an example. All are written roughly the same way. Snippets of the go button callback are below.
function GoBut_Callback(hObject, eventdata, handles)
% hObject handle to GoBut (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
run('UrlPrice.m');
BathRoom = getappdata(handles.uibuttongroup3,'BathRoom');
BathSq = getappdata(handles.uibuttongroup3,'BathSq');
BathWall = getappdata(handles.uibuttongroup3,'BathWall');
% Floor = get(handles.Floor,'value')
HomeName = get(handles.HomeName,'string');
Base = get(handles.BaseSqFt, 'string');
BaseSqFt = str2num(Base);
TotSqFt = BaseSqFt .* Floor;
Perim = (((BaseSqFt .^ .5) .* 4) .* Floor);
Perim2 = (BaseSqFt .^ .5) .*4;
Perim3 = (BaseSqFt .^ .5);
WallLnFt_01 = Perim + (BedWall .* 2) + (BathWall .* 2); % double side wall
WallLnFt_02 = Perim + BedWall + BathWall; % one side wall
IntDoor = (BedRoom .* 2) + (BathRoom) + 2;
Tile = ceil(BathSq/17.44287);
Thinset = BathRoom + 1;
Index of element to remove exceeds matrix dimensions.
The Error Messages:
Index of element to remove exceeds matrix dimensions.
Error in cur2str (line 75)
t(1,:) = [];
Error in HomeBuilding>GoBut_Callback (line 267)
EstMat = cur2str(EstMat1,2);
Error in gui_mainfcn (line 95)
feval(varargin{:});
Error in HomeBuilding (line 42)
gui_mainfcn(gui_State, varargin{:});
Error in #(hObject,eventdata)HomeBuilding('GoBut_Callback',hObject,eventdata,guidata(hObject))
Error while evaluating UIControl Callback
You use setappdata to store variables for later use in uibuttongroup3_SelectionChangedFcn. The problem is that this is done only in that function. That means the the variables are not stored until uibuttongroup3_SelectionChangedFcn is called, which happens only when the radio buttons are played with as you said.
When the GUI opens, the variables are not defined yet. Therefore you should define the three variables in OpeningFcn with some default value, or make sure that the user set the buttons before hitting go.

can't apply image gaussian blur filter using slider in matlab

I am working in image processing task using matlab,I have made a slider inside a dialog to apply and update gaussian blur filter on an image which is shown in axes
but it can not apply it,it shows that error
Error in ==> MatlabTestProject>name at 392
axes(handles.axes4);
??? Error while evaluating uicontrol Callback
this is my code
function mygui()
out = dialog('WindowStyle', 'normal', 'Name', 'My Dialog','Resize','off');
hSlider = uicontrol('Style','slider','Min',3,'Max',15,'Value',3,'Callback',#gaussian_blur);
%hListener = addlistener(hSlider,'Value','PostSet',#(s,e) disp('hi'));
function gaussian_blur(s,e,handles)
global imag;
slider_value = get(s,'Value');
slider_value=round(slider_value);
%display(slider_value);
%disp('hello')
%create filter
%sliderValueTxt=num2str(slider_value);
%set(handles.kSizeValueText ,'String',sliderValueTxt);
h = fspecial('gaussian', slider_value,0.5);
imag=imfilter(imag,h,'conv');
axes(handles.axes4);
imshow(imag)
% --------------------------------------------------------------------
function gaussianBlur_Callback(hObject, eventdata, handles)
% hObject handle to gaussianBlur (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
gaussian_dialog_Gui();
You're actually really close! All you need to do is include handles as an argument to the function gaussian_blur when defining the slider's listener object callback.
i.e replace this line: (it looks like a test line though)
hListener = addlistener(hSlider,'Value','PostSet',#(s,e) disp('hi'));
with something like this:
hListener = addlistener(hslider,'Value','PostSet',#(s,e) gaussian_blur(handles));
Just to be sure it works I created a test GUI programmatically using an axes and a slider and it works very well! Actually I changed a bit the filter to see an effect on my test image, but it should work as well in your case:
function GaussianSlider()
clear
clc
close all
handles.Image = imread('peppers.png');
handles.fig = figure('Position',[500 500 600 600],'Units','pixels');
handles.axes1 = axes('Units','pixels','Position',[50 100 400 400]);
handles.slider = uicontrol('Style','slider','Position',[50 50 400 20],'Min',3,'Max',15,'Value',3);%// I commented this for the purpose of demonstration. 'Callback',#gaussian_blur(handles));
%// That's the important part: add 'handles' as input argument to
%// gaussian_blur.
handles.Listener = addlistener(handles.slider,'Value','PostSet',#(s,e) gaussian_blur(handles));
imshow(handles.Image,'Parent',handles.axes1);
guidata(handles.fig);
function gaussian_blur(handles)
slider_value = round(get(handles.slider,'Value'));
%// I modified a bit the filter to see the effect
h = fspecial('gaussian',slider_value,slider_value);
handles.Image=imfilter(handles.Image,h,'conv');
axes(handles.axes1);
imshow(handles.Image)
end
end
If we look at 2 screenshots (i.e. 2 different slider positions):
and after moving the slider:
That's it! Hope that helps! If something is unclear please tell me.
Oh and in case you do not know: The actual callback of a slider is only executed when you release the button or press either arrow. As long as you hold the slider and move it, it's only the listener's callback that will be executed.