function FindCirclesFigHndl = FindCirclesGUI(inputImage,radiusRange)
% Detect and mark circles in an image
%
% SYNTAX:
%
% FindCirclesGUI
% Launches the GUI environment with the default image
% ('coins.png') pre-loaded.
%
% FindCirclesGUI(inputImage)
% Allows user to specify input image, or the name of an
% input image.
%
% FindCirclesGUI(...,radiusRange)
% Allows user to specify radius range as [minRadius maxRadius]
%
% (Note that OUTPUTS are supported via an "EXPORT" button.)
%
% CLASS SUPPORT:
% inputImage can be any valid image format readable by
% IMREAD. Color (RGB) images are supported, but circle
% detection is performed on the RGB2GRAY representation.
% (See help for IMFINDCIRCLES for details.)
%
% Note: This version _does not use_ the helper function
% VISCIRCLES, which can be very slow when a lot of
% circles are detected. Instead, it uses a custom plot
% function for visualization.
%
% Copyright The MathWorks, Inc. 2011.
% Written by Brett Shoelson, PhD
% brett.shoelson@mathworks.com
% Comments and suggestions welcome!
% V 1.0; 12/15/2011
% V 1.1; 2/4/2012
% Added Default-Reset and Acknowledgements buttons
% V 1.2; 2/7/2013
% Now defaults to "process immediately" = false;
% Also, takes optional input argument specifying initial radius range
% Copyright 2011-2012 MathWorks, Inc.
%
% See Also: IMFINDCIRCLES, VISCIRCLES
if verLessThan('images','8.0')
beep
disp('SORRY! FindCirclesGUI requires Image Processing Toolbox Ver. 8.0 (MATLAB R2012a) or later!');
%return
end
if nargin < 1 || isempty(inputImage)
fname = 'coins.png';
inputImage = imread('coins.png');
elseif ischar(inputImage)
fname = inputImage;
inputImage = imread(inputImage);
else
fname = 'Original';
end
if nargin < 2
minRadius = 20;
maxRadius = 30;
else
minRadius = radiusRange(1);
maxRadius = radiusRange(2);
end
bgc = [0.55 0.65 0.65];
tbc = 240/255; %toolbar color, approximately
FindCirclesFig = figure(...
'numbertitle','off',...
'windowstyle','normal',...
'name','Find Circles GUI',...
'units','Normalized',...
'Position',[0.1875 0.05 0.625 0.85],...
'color',bgc,...
'tag','FindCirclesFig',...
'menubar','none');
FindCirclesFigHndl = FindCirclesFig;
ht = uitoolbar(FindCirclesFig);
% tmp = ones(14,13);
% tmp(6:9,[1:3,6:8,11:13]) = 0;
% tmp = label2rgb(tmp,tbc*ones(3),[0 0 0]);
tmp = im2double(imread('file_open.png'));
tmp(tmp==0) = NaN;
loadImageTool = uitoggletool(ht,...
'CData', tmp,...
'oncallback', @GetNewFile,...
'offcallback', '',...
'Tooltipstring', 'Load new image',...
'Tag', 'loadImageTool'); %#ok<*NASGU>
tmp = im2double(imread('tool_zoom_in.png'));
tmp(tmp==0) = NaN;
zoomTool = uitoggletool(ht,...
'CData', tmp,...
'oncallback', 'zoom;set(gcbo,''state'',''off'')',...
'offcallback', '',...
'Tooltipstring', 'Toggle zoom state');
tmp = imread('distance_tool.gif');
tmp = label2rgb(tmp,tbc*ones(3),[0 0 0]);
distanceTool = uitoggletool(ht,...
'CData', tmp,...
'oncallback', 'imdistline;set(gcbo,''state'',''off'')',...
'offcallback', '',...
'Tooltipstring', 'Add IMDISTLINE Tool');
tmp = imcomplement(tmp);
delDistanceTool = uitoggletool(ht,...
'CData', tmp,...
'oncallback', @clearDistlineTools,...
'offcallback', '',...
'Tooltipstring', 'Clear IMDISTLINE Tool(s)');
tmp = ones(11);
tmp([1:3,9:13,21:23,33,89,99:101,109:113,119:121]) = 0;
tmp(6,:) = 0;tmp(:,6) = 0;
tmp2 = label2rgb(tmp,tbc*ones(3),[0 0 1]);
markObjectsTool = uitoggletool(ht,...
'CData', tmp2,...
'oncallback', @markPoints,...
'offcallback', '',...
'Tooltipstring', 'Manually count objects');
tmp2 = label2rgb(~tmp,tbc*ones(3),[0 0 1]);
markObjectsTool = uitoggletool(ht,...
'CData', tmp2,...
'oncallback', @clearMarkedPoints,...
'offcallback', '',...
'Tooltipstring', 'Clear counting marks');
tmp = imread('DefaultD.png');
defaultButton = uitoggletool(ht,...
'CData', tmp,...
'separator', 'on',...
'oncallback', @resetDefaults,...
'Tooltipstring', 'Resets all uicontrols/parameters to defaults.');
tmp = imread('logo.png');
infoButton = uitoggletool(ht,...
'CData', tmp,...
'separator', 'on',...
'oncallback', @acknowledge,...
'Tooltipstring', 'Acknowledgements');
set(FindCirclesFig,...
'defaultuicontrolunits','Normalized',...
'defaultuicontrolbackgroundcolor',bgc,...
'defaultuicontrolfontsize',9);
ImageAxis = axes(...
'Parent',FindCirclesFig,...
'Units','Normalized',...
'Position',[0.05 0.35 0.9 0.6 ],...
'Color',bgc,...
'Tag','ImageAxis',...
'Handlevisibility','Callback',...
'XLimMode','auto',...
'YLimMode','auto',...
'Visible','off');
ImgObj = imshow(inputImage,'parent',ImageAxis);
ImgTitle = title(fname);
expandAxes(ImageAxis);
%[objpos,objdim] = distributeObjects(4,0.05,0.95,0.025);
objpos = [0.05 0.28125 0.5125 0.74375];
objdim = 0.20625;
CommentsPanel = uipanel(...
'Parent',FindCirclesFig,...
'Title','Comments/Status',...
'Tag','CommentsPanel',...
'Units','Normalized',...
'Position',[objpos(1) 0.03 0.9 0.05]);
CommentsBox = uicontrol(...
'Parent',CommentsPanel,...
'Style','Edit',...
'String','Welcome to FindCirclesGUI! 2012 The MathWorks, Inc.',...
'Tag','CommentsBox',...
'Units','Normalized',...
'Fontsize',12,...
'Position',[0 -0.01 1 1.06],...
'Enable','Inactive');
SensitivityPanel = uipanel(...
'Parent',FindCirclesFig,...
'Title','Sensitivity',...
'Tag','SensitivityPanel',...
'Units','Normalized',...
'Position',[objpos(1) 0.0925 objdim 0.125]);
[SensitivitySlider, ~, SensitivityEdt] = sliderPanel(...
'Parent' , SensitivityPanel, ...
'Title' , '', ...
'Position', [0.05 0.05 0.9 0.9], ...
'Backgroundcolor', bgc,...
'Min' , 0, ...
'Max' , 1, ...
'Value' , 0.85, ...
'NumFormat','%0.2f',...
'Callback', @processFindCircles);
set(findobj(SensitivityPanel,'style','slider'),...
'TooltipString',...
sprintf('A high sensitivity value leads to detecting more\ncircles, including weak or partially obscured ones at\nthe risk of a higher false detection rate.\nDefault value: 0.85.'));
EdgeThresholdPanel = uipanel(...
'Parent',FindCirclesFig,...
'Title','Edge Threshold',...
'Tag','EdgeThresholdPanel',...
'Units','Normalized',...
'Position',[objpos(2) 0.0925 objdim 0.125]);
[EdgeThresholdSlider,~,EdgeThresholdEdt] = sliderPanel(...
'Parent' , EdgeThresholdPanel, ...
'Title' , '', ...
'Position', [0.05 0.25 0.9 0.7], ...
'Backgroundcolor', bgc,...
'Min' , 0, ...
'Max' , 1, ...
'Value' , 0.3, ...
'NumFormat','%0.2f',...
'Callback', @processFindCircles);
EdgeSlider = findobj(EdgeThresholdSlider,'style','slider');
set(EdgeSlider,...
'Enable','Off',...
'TooltipString',...
sprintf('Specifies the gradient threshold for determining edge pixels.\nA high EdgeThreshold value leads to detecting only those circles\nthat have relatively strong edges. A low EdgeThreshold value will,\nin addition, lead to detecting circles with relatively faint edges.\n'));
UseDefaultEdgeThresh = uicontrol(...
'Parent',EdgeThresholdPanel,...
'Callback',@toggleEdgeThreshSlider,...
'Units','Normalized',...
'Position',[0.05 0.025 0.45 0.2],...
'String','Use Default',...
'Style','checkbox',...
'Value',1,...
'Tag','UseDefaultEdgeThresh',...
'TooltipString','When checked, edge threshold will be automatically determined using Graythresh.');
VisualizationPanel = uipanel(...
'Parent',FindCirclesFig,...
'Title','Visualization Options',...
'Tag','VisualizationPanel',...
'Position',[objpos(3) 0.0925 objdim*1.3 0.125]);
LineWidthText = uicontrol(...
'Parent',VisualizationPanel,...
'Callback','',...
'Units','Normalized',...
'Position',[0.05 0.525 0.35 0.4],...
'String','Line Width',...
'Style','text',...
'HorizontalAlignment','Left',...
'Tag','LineWidthText');
lineWidthVal = 2;
LineWidthValBox = uicontrol(...
'Parent',VisualizationPanel,...
'Callback',@processFindCircles,...
'Units','Normalized',...
'Position',[0.4 0.55 0.2 0.4],...
'String',[0.5;1.0;1.5;2.0;3.0;4.0;8.0],...
'Style','popupmenu',...
'Value',lineWidthVal,...
'Fontsize',10,...
'Tag','LineWidthValBox');
LineStyleText = uicontrol(...
'Parent',VisualizationPanel,...
'Callback','',...
'Units','Normalized',...
'Position',[0.05 0.225 0.35 0.4],...
'String','Line Style',...
'Style','text',...
'HorizontalAlignment','Left',...
'Tag','LineStyleText');
LineStyleValBox = uicontrol(...
'Parent',VisualizationPanel,...
'Callback',@processFindCircles,...
'Units','Normalized',...
'Position',[0.4 0.25 0.2 0.4],...
'String',{'-','--','-.',':'},...
'Style','popupmenu',...
'Value',2,...
'Fontsize',10,...
'Tag','LineStyleValBox');
circleColor = [0 1 1];
circleColorButton = uicontrol(...
'Parent',VisualizationPanel,...
'style','pushbutton',...
'Position',[0.7 0.45 0.15 0.35],...
'cdata',reshape(kron(circleColor,ones(25,25)),25,25,3),...
'callback',@changeCircleColor,...
'tag','circleColorButton');
setappdata(circleColorButton,'circleColor',circleColor);
ClearPrevious = uicontrol(...
'Parent',VisualizationPanel,...
'Callback','',...
'Units','Normalized',...
'Position',[0.05 0.025 0.45 0.2],...
'String','Clear previous circles',...
'Style','checkbox',...
'Value',1,...
'Tag','ClearPrevious');
UseWhiteBG = uicontrol(...
'Parent',VisualizationPanel,...
'Callback',@processFindCircles,...
'Units','Normalized',...
'Position',[0.55 0.025 0.45 0.2],...
'String','White Background',...
'Style','checkbox',...
'Value',0,...
'Tag','UseWhiteBG');
ObjectPolarityPanel = uibuttongroup(...
'Parent',FindCirclesFig,...
'Title','Object Polarity',...
'Tag','ObjectPolarityPanel',...
'Units','Normalized',...
'Position',[objpos(1) 0.2275 objdim 0.0625],...
'SelectedObject',[],...
'SelectionChangeFcn',@processFindCircles,...
'OldSelectedObject',[]);
BrightButton = uicontrol(...
'Parent',ObjectPolarityPanel,...
'Units','Normalized',...
'Position',[0.05 0.25 0.425 0.5],...
'String','Bright',...
'Style','radiobutton',...
'TooltipString','Circles are brighter than the background.',...
'Value',1,...
'Tag','Bright');
DarkButton = uicontrol(...
'Parent',ObjectPolarityPanel,...
'Units','Normalized',...
'Position',[0.50 0.25 0.425 0.5],...
'String','Dark',...
'Style','radiobutton',...
'TooltipString','Circles are darker than the background.',...
'Tag','Dark');
MethodPanel = uibuttongroup(...
'Parent',FindCirclesFig,...
'Title','Method',...
'Tag','MethodPanel',...
'Units','Normalized',...
'Position',[objpos(2) 0.2275 objdim 0.0625],...
'SelectedObject',[],...
'SelectionChangeFcn',@processFindCircles,...
'OldSelectedObject',[]);
PhaseCodeButton = uicontrol(...
'Parent',MethodPanel,...
'Units','Normalized',...
'Position',[0.05 0.25 0.425 0.5],...
'String','Phase Code',...
'Style','radiobutton',...
'Value',1,...
'Tag','PhaseCode',...
'Tooltipstring',...
sprintf('Specifies use of Atherton and Kerbyson''s Phase Coding method\nfor computing the accumulator array. (This is the Default.)'));
TwoStageButton = uicontrol(...
'Parent',MethodPanel,...
'Units','Normalized',...
'Position',[0.5 0.25 0.425 0.5],...
'String','Two-Stage',...
'Style','radiobutton',...
'Tag','TwoStage',...
'Tooltipstring',...
sprintf('Specifies use of the Two-stage Circular Hough Transform method\nfor computing the accumulator array.'));
ProcessOptionsPanel = uibuttongroup(...
'Parent',FindCirclesFig,...
'Title','Process Options',...
'Tag','ProcessOptionsPanel',...
'Units','Normalized',...
'Position',[0.8 0.0925 0.15 0.125],...
'SelectedObject',[],...
'SelectionChangeFcn',@processFindCircles,...
'OldSelectedObject',[]);
ProcessButton = uicontrol(...
'Parent',ProcessOptionsPanel,...
'Callback',@processFindCircles,...
'FontSize',9,...
'Units','Normalized',...
'Position',[0.05 0.4 0.9 0.3],...
'String','Process Now',...
'Tag','ProcessButton');
ExportButton = uicontrol(...
'Parent',ProcessOptionsPanel,...
'Callback',@exportResults,...
'FontSize',9,...
'Units','Normalized',...
'Position',[0.05 0.05 0.9 0.3],...
'String','Export/Save Results',...
'Tag','ExportButton');
ProcessImmediatelyBox = uicontrol(...
'Parent',ProcessOptionsPanel,...
'Callback','',...
'Units','Normalized',...
'Position',[0.05 0.8 0.9 0.15],...
'String','Process Immediately',...
'Style','checkbox',...
'Value',0,...
'Tag','ProcessImmediatelyBox');
RadiusRangePanel = uipanel(...
'Parent',FindCirclesFig,...
'Title','Radius Range',...
'Tag','RadiusRangePanel',...
'Units','Normalized',...
'Position',[objpos(3) 0.2275 1-objpos(3)-objpos(1) 0.0625]);
MinRadiusText = uicontrol(...
'Parent',RadiusRangePanel,...
'Style','text',...
'Units','Normalized',...
'Position',[0.2 0.1 0.2 0.5],...
'String','Minimum Radius',...
'HorizontalAlignment','Left',...
'Tag','MinRadiusText');
MaximumRadiusText = uicontrol(...
'Parent',RadiusRangePanel,...
'Style','text',...
'Units','Normalized',...
'Position',[0.7 0.1 0.2 0.5],...
'String','Maximum Radius',...
'HorizontalAlignment','Left',...
'Tag','MaximumRadiusText');
MinRadiusBox = uicontrol(...
'Parent',RadiusRangePanel,...
'BackgroundColor',[1 1 1],...
'Callback',@processFindCircles,...
'FontSize',10,...
'Units','Normalized',...
'Position',[0.05 0.15 0.125 0.6],...
'String',minRadius,...%'20',...
'Style','edit',...
'Tag','MinRadiusBox');
MaxRadiusBox = uicontrol(...
'Parent',RadiusRangePanel,...
'Units','Normalized',...
'BackgroundColor',[1 1 1],...
'Callback',@processFindCircles,...
'FontSize',10,...
'Position',[0.55 0.15 0.125 0.6],...
'String',maxRadius,...%'30',...
'Style','edit',...
'Tag','MaxRadiusBox');
set(findobj(FindCirclesFig,'type','uipanel'),...
'Units','Normalized',...
'BorderType', 'etchedin',...
'FontSize',8,...
'ForegroundColor',[0 0 0],...
'TitlePosition','lefttop',...
'backgroundColor',bgc)
if ~nargout
clear FindCirclesFigHndl
end
%%% SUBFUNCTIONS
function acknowledge(varargin)
mssg = {'',...
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ',...
'',...
'I would like to acknowledge and thank the following for',...
'suggestions, reviews, and critiques of this tool:',...
'',...
'Jiro Doke',...
'Simone Haemmerle',...
'Steve Kuznicki',...
'Grant Martin',...
'Jeff Mather',...
'Alex Taylor',...
'Spandan Tiwari',...
'Ashish Uthama',...
'The Image Processing Toolbox Development Team',...
'',...
'Comments and suggestions are welcome,',...
'and should be addressed to me at:',...
'',...
'brett.shoelson@mathworks.com',...
'',...
' 2012 MathWorks, Inc.',...
'',...
'',...
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ ~',...
''};
h = msgbox(mssg,'ImageRegistrationGUI Acknowledgments','help','modal') ;
msghndl = findobj(h,'tag','MessageBox');
set(msghndl,'color',[0 0 0.7],'fontweight','b','fontname','helvetica')
set(gcbo,'state','off')
end
function changeCircleColor(varargin)%circleColor =
circleColor = getappdata(circleColorButton,'circleColor');
circleColor = uisetcolor(circleColor);
set(circleColorButton,'cdata',reshape(kron(circleColor,ones(25,25)),25,25,3));
setappdata(circleColorButton,'circleColor',circleColor);
processFindCircles(gcbo)
end
function myhandle = circles(radii,centers,lineWidthVal,lineStyleVal,circColor)
% Plots multiple circles as a single line object
% Written by Brett Shoelson, PhD
resolution = 2;
theta=0:resolution:360;
x_circle = bsxfun(@times,radii,cos(theta*pi/180));
x_circle = bsxfun(@plus,x_circle,centers(:,1));
x_circle = cat(2,x_circle,nan(size(x_circle,1),1));
x_circle = x_circle';
x_circle = x_circle(:);
y_circle = bsxfun(@times,radii,sin(theta*pi/180));
y_circle = bsxfun(@plus,y_circle,centers(:,2));
y_circle = cat(2,y_circle,nan(size(y_circle,1),1));
y_circle = y_circle';
y_circle = y_circle(:);
hold on;
myhandle = plot(ImageAxis,...
x_circle,y_circle);
set(myhandle,...
'linewidth',lineWidthVal,...
'linestyle',lineStyleVal,...
'color',circColor,...
'tag','mycircles');
% try
% mycircs = findall(gcf,'tag','mycircles');
% if ~isempty(mycircs)
% while true
% pause(1)
% if strcmp(get(mycircs(1),'visible'),'on')
% set(mycircs(1),'visible','off');
% else
% set(mycircs(1),'visible','on');
% end
% end
% end
% catch
% disp('no flicker')
% end
end
function clearDistlineTools(varargin)
delete(findall(FindCirclesFig,'tag','imline'));
set(gcbo,'state','off');
end
function clearMarkedPoints(varargin)
delete(findall(FindCirclesFig,'tag','impoint'));
set(gcbo,'state','off');
end
function exportResults(varargin)
radii = getappdata(FindCirclesFig,'radii');
if isempty(radii)
set(CommentsBox,'string','No circles detected!');
return
end
hasCVST = exist('vision.ShapeInserter','class')==8;
if hasCVST
prompt={'Export/save CENTERS as:',...
'Export/save RADII as:',...
'Export/save METRIC as:',...
'Export/save IMAGE as:'};
defaultanswer={'centers','radii','metric','ImgOut'};
else
prompt={'Export/save CENTERS as:',...
'Export/save RADII as:',...
'Export/save METRIC as:'};
defaultanswer={'centers','radii','metric'};
end
name='Export/save Options (Variable Names)';
answer=inputdlg(prompt,name,1,defaultanswer);
if isempty(answer)
return
end
centers = getappdata(FindCirclesFig,'centers');
assignin('base',answer{1},centers);
assignin('base',answer{2},radii);
assignin('base',answer{3},getappdata(FindCirclesFig,'metric'));
if hasCVST
if size(inputImage,3) == 1
tmpImage = cat(3,inputImage,inputImage,inputImage);
else
tmpImage = inputImage;
end
tmpImage = im2double(tmpImage);
h = vision.ShapeInserter;
h.Shape = 'Circles';
h.Fill = false;
h.BorderColor = 'Custom';
%h.CustomBorderColor = intmax(class(inputImage))*cast(circleColor,class(inputImage));%im2uint16(circleColor);
h.CustomBorderColor = im2uint8(circleColor);
h.Antialiasing = true;
tmp = step(h,tmpImage,uint16([centers radii]));
for ii = 2:round(lineWidthVal)
tmp = step(h,tmp,uint16([centers radii+ii-1]));
end
assignin('base',answer{4},tmp);
end
MinRadius = str2double(get(MinRadiusBox,'string'));
MaxRadius = str2double(get(MaxRadiusBox,'string'));
Sensitivity = get(SensitivitySlider,'value');
UseDefaultEdge = get(UseDefaultEdgeThresh,'value');
Method = get(get(MethodPanel,'SelectedObject'),'Tag');
ObjectPolarity = get(get(ObjectPolarityPanel,'SelectedObject'),'Tag');
if UseDefaultEdge == 1
EdgeThreshold = '[]';
fprintf('[%s,%s,%s] = imfindcircles(imread(''%s''),[%d %d],...\n ''Sensitivity'',%0.2f,...\n ''EdgeThreshold'',%s,...\n ''Method'',''%s'',...\n ''ObjectPolarity'',''%s'');\n\n',...
answer{1},answer{2},answer{3},fname,MinRadius,MaxRadius,Sensitivity,EdgeThreshold,Method,ObjectPolarity)
else
EdgeThreshold = get(EdgeThresholdSlider,'value');
fprintf('[%s,%s,%s] = imfindcircles(imread(''%s''),[%d %d],...\n ''Sensitivity'',%0.2f,...\n ''EdgeThreshold'',%0.2f,...\n ''Method'',''%s'',...\n ''ObjectPolarity'',''%s'');\n\n',...
answer{1},answer{2},answer{3},fname,MinRadius,MaxRadius,Sensitivity,EdgeThreshold,Method,ObjectPolarity)
end
disp('Variables written to base workspace');
set(CommentsBox,'string',sprintf('%d circles detected. Variables written (with requested names) to base workspace.',numel(radii)));
end
function GetNewFile(varargin)
set(gcbo,'state','off');
[img,cmap,fname,fpath,userCanceled] = getNewImage(false);
if userCanceled
return
end
if ~isempty(cmap)
inputImage = ind2rgb(img,cmap);
else
inputImage = img;
end
cla(ImageAxis);
ImgObj = imshow(inputImage,'parent',ImageAxis); %#ok
originalImg = imshow(img,'parent',ImageAxis);
expandAxes(ImageAxis);
ImgTitle = title(fname,'interpreter','none'); %#ok
set(ImageAxis,'XLim',0.5+[0 size(img,2)],'YLim',0.5+[0 size(img,1)]);
processFindCircles(gcbo)
end
function markPoints(varargin)
markImagePoints(ImageAxis,'markedPoints',[0 110 110]/255);
% waitfor(FindCirclesFig,'currentcharacter')
% drawnow;
set(gcbo,'state','off');
set(FindCirclesFig,'currentcharacter','1') % double('1') = 49
while double(get(FindCirclesFig,'currentcharacter')) == 49
pause(0.5);
end
markedPoints = evalin('base','markedPoints');
set(CommentsBox,'string',sprintf('%d points marked. (Locations written to "markedPoints" in base workspace.)', size(markedPoints,1)));
end
function processFindCircles(varargin)
drawnow
cboTag = '';
try %If processing is from Default-Reset, there is no input argument
cboTag = get(varargin{1},'tag');
end
processImmediately = get(ProcessImmediatelyBox,'value');
if processImmediately || strcmp(cboTag,'ProcessButton');
set(CommentsBox,'string','Processing...please wait.');
clearPrev = get(ClearPrevious,'value');
if clearPrev
delete(findobj(FindCirclesFig,'tag','FindCirclesVis'));
end
MinRadius = str2double(get(MinRadiusBox,'string'));
MaxRadius = str2double(get(MaxRadiusBox,'string'));
if MinRadius > MaxRadius
set(CommentsBox,'string','MinRadius must not be bigger than MaxRadius!');
return
end
Sensitivity = get(SensitivitySlider,'value');
UseDefaultEdge = get(UseDefaultEdgeThresh,'value');
if UseDefaultEdge == 1
EdgeThreshold = [];
else
EdgeThreshold = get(EdgeThresholdSlider,'value');
end
Method = get(get(MethodPanel,'SelectedObject'),'Tag');
ObjectPolarity = get(get(ObjectPolarityPanel,'SelectedObject'),'Tag');
[centers,radii,metric] = imfindcircles(inputImage,[MinRadius MaxRadius],...
'Sensitivity',Sensitivity,...
'EdgeThreshold',EdgeThreshold,...
'Method',Method,...
'ObjectPolarity',ObjectPolarity);
setappdata(FindCirclesFig,'centers',centers);
setappdata(FindCirclesFig,'radii',radii);
setappdata(FindCirclesFig,'metric',metric);
if numel(radii)>0
useWhiteBGVal = get(UseWhiteBG,'value');
%For visualization
lineWidthVal = get(LineWidthValBox,'string');
tmp = get(LineWidthValBox,'value');
lineWidthVal = str2double(lineWidthVal(tmp,:));
lineStyleVal = get(LineStyleValBox,'string');
tmp = get(LineStyleValBox,'value');
lineStyleVal = lineStyleVal{tmp};
circleColor = getappdata(circleColorButton,'circleColor');
if useWhiteBGVal
hndls = circles(radii,centers,...
lineWidthVal+1,'-',[1 1 1]);
set(hndls,'tag','FindCirclesVis');
end
hndls = circles(radii,centers,...
lineWidthVal,lineStyleVal,circleColor);
set(hndls,'tag','FindCirclesVis');
set(CommentsBox,'string',sprintf('%d circles detected.',numel(radii)));
else
set(CommentsBox,'string','No circles detected with these settings!');
end
else
return
end
end
function resetDefaults(varargin)
set(gcbo,'state','off');
%Defaults
set(SensitivitySlider,'value',0.85);
set(SensitivityEdt,'string',0.85);
%
set(EdgeThresholdSlider,'value',0.3);
set(EdgeThresholdEdt,'string',0.3);
%
set(BrightButton,'Value',1);
set(DarkButton,'value',0);
%
set(PhaseCodeButton,'Value',1)
set(TwoStageButton,'Value',0);
%
set(MinRadiusBox,'String','20');
set(MaxRadiusBox,'String','30');
%
processFindCircles
set(CommentsBox,'string','Parameters reset to default values. (Visualization options not changed)');
end
function toggleEdgeThreshSlider(varargin)
if get(varargin{1},'value') == 1
set(EdgeSlider,'enable','off');
else
set(EdgeSlider,'enable','on');
end
end
end