Problem with uiwait; broken by impoly / imroi / roipoly

3 views (last 30 days)
Aline
Aline on 28 Aug 2014
Edited: user001 on 20 Dec 2016
I need a GUI where the user can draw several polygons in an image, and when he is done, the polygon vertices are saved.
So I created a GUI with guide, with an axes with the image, and two pushbuttons. I used 'uiwait' as proposed in guide at the end of the Opening Function. One button 'New' let's the user draw a polyon using 'impoly'. The other button 'OK' calls 'uiresume', so that the code jumps to the Output Function.
The problem is:
Apparently the 'imroi' functions like 'impoly' break 'uiwait' early, and as soon as the first polygon is closed, the Output Function is called. I found two other posts indicating this. The only answer they found was to use 'roipolyold'. But since it is supposed to be removed in future releases, and I'm otherwise quite happy with 'imploly', I would really like to find another solution. I tried avoiding 'uiwait' und using 'waitfor' instead, but it always closed the figure right after opening and then got stuck on 'waitfor'.
I will be happy about any clues or ideas as to how I could get around this. Thanks!

Answers (4)

Image Analyst
Image Analyst on 28 Aug 2014
Store the results of each polygon (the vertex coordinates) in a global variable cell array. Each time you click the button and draw a polygon, by whatever method, add it to the cell array variable as a new cell.
  8 Comments
Aline
Aline on 5 Sep 2014
OK. So you would just close the figure with the OK button press? But when would the Output Fcn run then? Do I need to put all the code I have in there into the button_callback then?
Image Analyst
Image Analyst on 5 Sep 2014
I suggest you put lines in like this to every function to see when they get run:
fprintf('Now entering blahblahblah()...\n')
% code for blahblahblah()
fprintf('Now leaving blahblahblah()...\n')
You'll see the OutputFcn() gets run both on startup and shutdown. I usually have a button called btnExit, but you can call it OK if that's what you want. When the user clicks it, this is the code that runs to shutdown the GUI:
%=====================================================
% --- Executes on button press in btnExit.
function btnExit_Callback(hObject, eventdata, handles)
% hObject handle to btnExit (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
try
fprintf(1, 'Just entered btnExit_Callback...\n');
fprintf('Saving settings and parameters...');
SaveUserSettings(handles, 1);
% Get rid of variables from the global workspace so that they aren't
% hanging around the next time we try to run this m-file.
clear global;
% Cause it to shutdown.
delete(handles.figMainWindow);
fprintf(1, 'Leaving btnExit_Callback.\n');
catch ME
errorMessage = sprintf('Error in function btnExit_Callback.\nError Message:\n%s', ME.message);
WarnUser(errorMessage);
end
SaveUserSettings() is a custom written routine where I save the state of all controls on the GUI (checkbox states, scroll bar values, etc.). WarnUser is simply this:
%======================================================
% Warn user via the command window and a popup message.
function WarnUser(warningMessage)
fprintf(1, '%s\n', warningMessage);
uiwait(warndlg(warningMessage));
return; % from WarnUser()

Sign in to comment.


Aline
Aline on 5 Sep 2014
I finally figured out, that if I call uiwait again in my pushbutton_callback, after calling impoly, the GUI works as it should. I still don't know why I had that problem, but it works now :)
Just for sake of completeness, this is my code (the changed part from GUIDE):
Opening Function:
% --- Executes just before DrawPolygon is made visible.
function DrawPolygon_OpeningFcn(hObject, eventdata, handles, Img)
% 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 DrawPolygon (see VARARGIN)
% Adjust image contrast
Img = imadjust(mat2gray(Img));
% Display Image in the figure's axes
imshow(Img,'Parent',handles.axes);
% Create handles object to pass along the functions and save the output
% The output will be the structure S with the user-created polygons.
handles.S = struct('Handle',{},'Polygon',{});
% Making the toolbar and menubar of the figure visible, so that amongst
% others zoom is enabled.
set(handles.figure1,'toolbar','figure');
set(handles.figure1,'menubar','figure');
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes DrawPolygon wait for user response (see UIRESUME)
uiwait(handles.figure1);
Output Function
% --- Outputs from this function are returned to the command line.
function varargout = DrawPolygon_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT);
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
for ii = 1:size(handles.S,2)
handles.S(ii).Polygon = getPosition(handles.S(ii).Handle);
% Should the endpoint of the polygon not be the startpoint, the polygon
% is not closed and problems arise later in the script.
if handles.S(ii).Polygon(end,:) ~= handles.S(ii).Polygon(1,:)
handles.S(ii).Polygon(end+1,:) = handles.S(ii).Polygon(1,:);
end
end
varargout{1} = handles.S;
% After output has been relayed, the figure can be closed and deleted
delete(handles.figure1);
Pushbutton Callbacks New Polygon
% --- Executes on button press in pushbutton_New.
function pushbutton_New_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton_New (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% If the 'New'
button is pressed, the user can start creating a new polygon
% in the image.
% The handle to the new polygon is saved in the handles.S structure. The
% structure is initially empty. A new element is added for each polygon
% created.
handles.S(size(handles.S,2)+1).Handle=impoly(handles.axes);
% Update handles structure
guidata(hObject, handles);
% Since impoly seems to break uiwait, it is called again.
uiwait(handles.figure1);
OK Button (jumps to output function)
% --- Executes on button press in pushbutton_OK.
function pushbutton_OK_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton_OK (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
uiresume(handles.figure1);

Jan
Jan on 19 Oct 2014
I recently experienced a very similar problem: The callback function of a button drawed several ROIs from memory using imellipse . Thereafter, a uiwait(f) was called for the user to corrigate these ROIs. However, this uiwait(f) did not work.
Solution: call uiwait twice, like you did. Alternatively, You can call pause(0.001) before calling uiwait (once).
I did not got to the root of this problem, but this worked for me. Apperently there are indeed some problems when combining imroi functions and uiwait.

user001
user001 on 20 Dec 2016
Edited: user001 on 20 Dec 2016
I too experienced the same problem (in R2014b) and found that re-calling `uiwait` in the `impoly`-containing callback function was necessary. Would be interested to know the reason the original `uiwait` is neglected in this case.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!