Create and save imfreehand() positions until the user clicks a button to finish

Hi,
I want an image to open and the user to draw ROI with imfreehand() until they are finished - with the co-ordinates saved into structured array - - the following code does it for 3 regions of interest - - but how can i do this until the user is finished? Would be good to have an undo button too - which not only deletes the region of interest but also deletes xy co-ordinates in the array. Thanks!!
img = imread('myfig.jpg')
imshow(img)
i = 1;
for i = 1:3
hFH(i) = imfreehand();
xy{i} = hFH(i).getPosition;
end

 Accepted Answer

You could use
img = imread('myfig.jpg')
imshow(img)
i = 1;
finished = 'NO';
i = 1;
while strcmpi(finished,'NO')
hFH(i) = imfreehand();
finished = questdlg('Finished?', ...
'confirmation', ...
'YES', 'NO', 'UNDO', 'NO');
if strcmpi(finished, 'UNDO')
delete(hFH(i))
finished = 'NO';
else
xy{i} = hFH(i).getPosition;
i = i + 1;
end
end

7 Comments

This is great thanks! but rather than a dialogue box how about a push button? i'm getting confused about how to interrogate the status of the push button in the while loop
Here's one way you could do it using push buttons in the figure. This is a simple trick that uses the axes's 'Tag' property to decide on what to do.
You will have to play around with the 'Position' properties to get them in the correct positions. I set the units to 'normalized', which is respective to the figure's position, which in turn is normalized to the computer screen.
img = imread('myfig.jpg');
%position vector is [left, bottom, width, height]
f = figure('Units','normalized', ...
'Position',[0.25 0.25 0.5 0.5]);
ax = axes('Position',[0 0 0.8 1]);
imshow(img)
nextButton = uicontrol('String', 'NEXT', 'Style', ...
'pushbutton', 'Units', 'normalized', 'FontSize', 14);
nextButton.Position = [0.8 0.8 0.1 0.05];
% This function executes when the button is clicked
nextButton.Callback = 'set(gca,''Tag'',''continue'');';
undoButton = uicontrol('String', 'UNDO', 'Style', ...
'pushbutton', 'Units', 'normalized', 'FontSize', 14);
undoButton.Position = [0.8 0.7 0.1 0.05];
undoButton.Callback = 'set(gca,''Tag'',''undo'');';
finishButton = uicontrol('String', 'FINISHED', 'Style', ...
'pushbutton', 'Units', 'normalized', 'FontSize', 14);
finishButton.Position = [0.8 0.6 0.1 0.05];
finishButton.Callback = 'set(gca,''Tag'',''finished'');';
ax.Tag = 'continue';
i = 1;
while strcmp(ax.Tag, 'continue')
hFH(i) = imfreehand();
ax.Tag = 'waiting';
%wait for ax.Tag to be changed by button click
waitfor(ax,'Tag')
if strcmp(ax.Tag, 'undo')
delete(hFH(i))
ax.Tag = 'continue';
elseif strcmp(ax.Tag, 'continue') || strcmp(ax.Tag, 'finished')
xy{i} = hFH(i).getPosition;
i = i + 1;
end
end
close(f)
This is brilliant thanks very much! :-) The delete in the dialogue box approach seems to just delete the region of interest on the image but not the data saved in the array, while in the push button example it deletes the saved XY co-ordinates too. Odd.
Just one last thing (sorry!!) when I click on the zoom in button on the figure (which is very useful) none of the buttons ('next', 'finish', 'undo') - work any more! is there an easy way to fix this?
That's because clicking on the zoom button stops the imfreehand() function. That can be solved with another waitfor() trick. P. S. if you like my answer, please accept it ;)
This version should be almost fool proof:
img = imread('myfig.jpg');
f = figure('Units','normalized', ...
'Position',[0.25 0.25 0.5 0.5]);
ax = axes('Position',[0 0 0.8 1]);
imshow(img)
nextButton = uicontrol('String', 'GET DATA', 'Style', ...
'pushbutton', 'Units', 'normalized', 'FontSize', 14);
nextButton.Position = [0.8 0.8 0.13 0.05];
% This function executes when the button is clicked
nextButton.Callback = 'set(gca,''Tag'',''continue'');';
undoButton = uicontrol('String', 'UNDO', 'Style', ...
'pushbutton', 'Units', 'normalized', 'FontSize', 14);
undoButton.Position = [0.8 0.7 0.13 0.05];
undoButton.Callback = 'set(gca,''Tag'',''undo'');';
undoButton.Enable = 'off';
finishButton = uicontrol('String', 'FINISHED', 'Style', ...
'pushbutton', 'Units', 'normalized', 'FontSize', 14);
finishButton.Position = [0.8 0.6 0.13 0.05];
finishButton.Callback = 'set(gca,''Tag'',''finished'');';
finishButton.Enable = 'off';
infoBox = uicontrol('String',{'Zoom in or out of image.',...
'Click GET DATA to place freehand region.'},'Style','Text',...
'Units', 'normalized', 'BackgroundColor', [1 1 1]);
infoBox.Position = [0.7 0.2 0.8 0.3];
infoBox.HorizontalAlignment = 'left';
infoBox.FontSize = 11;
ax.Tag = 'continue';
i = 1;
while strcmp(ax.Tag, 'continue')
ax.Tag = 'waiting';
waitfor(ax,'Tag')
f.MenuBar = 'none';
infoBox.String{1} = 'Place freehand region.';
infoBox.String{2} = '';
hFH(i) = imfreehand();
infoBox.String{1} = 'Click a button to continue.';
nextButton.String = 'NEXT';
undoButton.Enable = 'on';
finishButton.Enable = 'on';
ax.Tag = 'waiting';
%wait for ax.Tag to be changed by button click
waitfor(ax,'Tag')
if strcmp(ax.Tag, 'undo')
delete(hFH(i))
ax.Tag = 'continue';
elseif strcmp(ax.Tag, 'continue') || strcmp(ax.Tag, 'finished')
xy{i} = hFH(i).getPosition;
i = i + 1;
end
undoButton.Enable = 'off';
finishButton.Enable = 'off';
f.MenuBar = 'figure';
nextButton.String = 'GET DATA';
infoBox.String{1} = 'Zoom in or out of image.';
infoBox.String{2} = 'Click GET DATA to place freehand region.';
end
close(f)
This is great!!! - -thanks very much !! :-) I am going to try and incorporate a "back" button as well, just in case they start doing a ROI but then think better of it - i'll have a think about that Charlie
No problem :) I would suggest you look into object oriented programming in Matlab. If you create your GUI as a class, it'll be a lot more flexible if you ever have to make changes.
Hi Marc, How can i extract or separate the ROI based on the coordinates of that same ROI. I want to use those coordinates to crop the ROI of many images of same scene. Can you help me in that?

Sign in to comment.

More Answers (0)

Categories

Find more on Convert Image Type in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!