Code covered by the BSD License  

Highlights from
Image Registration App

image thumbnail

Image Registration App

by

 

09 Jan 2012 (Updated )

UI environment for registering a Moving image to a Fixed image

ImageRegistrationApp.m
function ImageRegistrationApp(movingInputImage,fixedInputImage)
% UI environment for registering a Moving image to a Fixed image
%
% Provided interactive access to ALL parameters and
% components used by the IMREGISTER tool chain.
%
% REQUIRES the Image Processing Toolbox and MATLAB R2012a or
% later!
%
% SYNTAX:
% ImageRegistrationApp
%   Launches a UI with default images.
%   (New images can be loaded from the menu.)
%
% ImageRegistrationApp(moving_image,fixed_image);
%   Launches a UI with user-specified Moving and Fixed
%   images. Images can be specified by name, or provided
%   directly.
%
% CLASS SUPPORT/NOTE: ImageRegistrationApp supports the same
%    (2D grayscale) image classes supported by IMREGISTER.
%    However, it will also work on RGB images (using RGB2GRAY
%    under the hood), and on logical images (using
%    IM2DOUBLE).
%
%
% EXAMPLES:
%
%    % Example 1
%    fixedInputImage = imread('pout.tif');
%    movingInputImage = [[ones(291,10)*110 fixedInputImage]; ones(10,250)*110];
%    movingInputImage = imrotate(movingInputImage,5,'bicubic','crop');
%    ImageRegistrationApp(movingInputImage,fixedInputImage)
%
%    % Example 2
%    fixed = 'peppers.png';
%    moving = imrotate(imread(fixed),5,'bicubic');
%    ImageRegistrationApp(moving,fixed)
%
% Written by Brett Shoelson, PhD
% brett.shoelson@mathworks.com
% Comments and suggestions welcome!
%
% Version:
%   12/28/2011 (Original)
%   8/8/2012:  Better management of path when selecting new images.
%   9/28/2012: Added support for outputting TFORM for R2013a and beyond.
%              Now supports calls to IMREGTFORM and IMWARP directly (rather
%              than to IMREGISTER), for efficiency.
%   10/24/13:  Fixed a problem with display axes (I had neglected to turn
%              'hold' 'off' after calling checkerboard.
%
% Copyright 2013 MathWorks, Inc.
%
% See Also: IMREGISTER, IMREGCONFIG,  IMREGTFORM, IMWARP, IMTRANSFORM, MAKETFORM


if verLessThan('images','8.0')
    beep
    disp('SORRY! ImageRegistrationApp requires Image Processing Toolbox Ver. 8.0 (MATLAB R2012a) or later!');
    return
end
iptver = ver('images');
iptver = str2double(iptver.Version);

singleton = true;
%Note: we can make this non-singleton, but will need to
%address a few things (like the timer object)
if singleton
    close(findall(0,'tag','ImageRegFig'));
end
if nargin ~= 2 && nargin ~= 0
    error('ImageRegistrationApp: Requires zero or two input arguments.')
end
mname = 'Moving';
fname = 'Fixed';
if nargin == 0
    fixedInputImage = iptImread('pout.tif');
    movingInputImage = [[ones(291,10)*110 fixedInputImage]; ones(10,250)*110];
    movingInputImage = imrotate(movingInputImage,10,'bicubic','crop');
end
if ischar(fixedInputImage)
    fname = fixedInputImage;
    fixedInputImage = iptImread(fname);
end
if ischar(movingInputImage)
    mname = movingInputImage;
    movingInputImage = iptImread(mname);
end
preprocessImages;

bgc = [0.75 0.85 0.85]; %background color
tbc = 240/255; %toolbar color, approximately
fgc = [59 113 86]/255; %foreground color
registered = movingInputImage;
tform = [];
ttStringLength = 50; %Tooltip string length (for autowrapping)
defaultFlickerFreq = 1; %Hz

ImageRegFig = figure(...
    'numbertitle','off',...
    'windowstyle','normal',...
    'name','Image Registration App',...
    'units','Normalized',...
    'pos',[0.1875 0.05 0.625 0.85],...
    'color',bgc,...
    'closerequestfcn',@closetimer,...
    'tag','ImageRegFig',...
    'menubar','none');
set(ImageRegFig,...
    'defaultuicontrolunits','Normalized',...
    'defaultuicontrolbackgroundcolor',bgc,...
    'defaultuicontrolfontsize',9,...
    'defaultuipanelbordertype','etchedin',...
    'defaultuipanelunits','Normalized',...
    'defaultuipanelfontsize',8,...
    'defaultuipanelbackgroundcolor',bgc,...
    'defaultaxescolor',bgc,...
    'defaultaxesunits','Normalized');

setappdata(ImageRegFig,'CurrDisp','Fixed');
setappdata(ImageRegFig,'FlickerFreq',defaultFlickerFreq);
warning('off','MATLAB:TIMER:RATEPRECISION')

ht                       = uitoolbar(ImageRegFig);

tmp                      = im2double(imread('file_open.png'));
tmp(tmp==0)              = NaN;
uitoggletool(ht,...
    'CData',               tmp,...
    'oncallback',          @GetNewFile,...
    'offcallback',         '',...
    'Tooltipstring',       'Load new image(s)',...
    'Tag',                 'loadImageTool');

tmp                      = im2double(imread('tool_zoom_in.png'));
tmp(tmp==0)              = NaN;
uitoggletool(ht,...
    'CData',               tmp,...
    'separator',           'on',...
    '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]);
uitoggletool(ht,...
    'CData',               tmp,...
    'separator',           'on',...
    'oncallback',          'imdistline;set(gcbo,''state'',''off'')',...
    'offcallback',         '',...
    'Tooltipstring',       'Add IMDISTLINE Tool');

tmp = imcomplement(tmp);
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]);
uitoggletool(ht,...
    'CData',               tmp2,...
    'separator',           'on',...
    'oncallback',          @markPoints,...
    'offcallback',         '',...
    'Tooltipstring',       'Manually count objects');

tmp2                      = label2rgb(~tmp,tbc*ones(3),[0 0 1]);
uitoggletool(ht,...
    'CData',               tmp2,...
    'oncallback',          @clearMarkedPoints,...
    'offcallback',         '',...
    'Tooltipstring',       'Clear counting marks');

tmp = imread('DefaultD.png');
uitoggletool(ht,...
    'CData',               tmp,...
    'separator',           'on',...
    'oncallback',          @resetDefaults,...
    'Tooltipstring',       'Resets all optimizer/metric parameters to defaults. Also resets flicker frequency to 1 Hz.');

tmp = imread('logo.png');
uitoggletool(ht,...
    'CData',               tmp,...
    'separator',           'on',...
    'oncallback',          @acknowledge,...
    'Tooltipstring',       'Acknowledgements');

gap = 0.0375;
[objpos,objdim] = distributeObjects(4,0.105,0.95,gap);

FixedImageAxes = axes(...
    'Parent',ImageRegFig,...
    'Position',[0.05 objpos(4) 0.15 objdim ],...
    'Tag','ImageAxis',...
    'XLimMode','auto',...
    'YLimMode','auto',...
    'Visible','off');

imshow(fixedInputImage,[]);
title('__ FIXED IMAGE __',...
    'color',fgc,'fontsize',12,...
    'Interpreter','none');

MovingImageAxes = axes(...
    'Parent',ImageRegFig,...
    'Position',[0.05 objpos(3) 0.15 objdim ],...
    'Tag','ImageAxis',...
    'XLimMode','auto',...
    'YLimMode','auto',...
    'Visible','off');

imshow(movingInputImage,[]);
%MovingImageTitle = title(mname);
title('__ MOVING IMAGE __',...
    'color',fgc,'fontsize',12,...
    'Interpreter','none');
AlignmentPanel = uipanel(...
    'Parent',ImageRegFig,...
    'Title','ALIGNMENT',...
    'Tag','ap',...
    'Fontsize',14,...
    'Foregroundcolor',fgc,...
    'Position',[0.235 0.35 0.715 0.625]);
ShowAlignmentAxes = axes(...
    'Parent',AlignmentPanel,...
    'Position',[0.025 0.025 0.95 0.925 ],...
    'Tag','ImageAxis',...
    'XLimMode','auto',...
    'YLimMode','auto',...
    'Visible','off');

AlignedImageObj = imshowpair(fixedInputImage,movingInputImage,'montage');%

expandAxes([ShowAlignmentAxes,FixedImageAxes,MovingImageAxes]);

del = 0.025;
VisualizationOptsButtonGroup = uibuttongroup(...
    'Parent',ImageRegFig,...
    'Title',' Visualization Options ',...
    'Tag','VisualizationOptsPanel',...
    'Position',[0.05 objpos(2)-del*1.5 0.15 objdim+del*2],...
    'SelectedObject',[],...
    'SelectionChangeFcn',@changeVisualizationOption,...
    'OldSelectedObject',[]);

[Vobjpos,Vobjdim] = distributeObjects(6,0.05,0.95,0.025);
uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.05 Vobjpos(6) 0.9 Vobjdim],...
    'String','False Color',...
    'Style','radiobutton',...
    'TooltipString','Creates a composite RGB image showing A and B overlayed in different color bands.',...
    'Value',0,...
    'Tag','FalseColor');
uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.05 Vobjpos(5) 0.9 Vobjdim],...
    'String','Blend',...
    'Style','radiobutton',...
    'TooltipString','Overlays A and B using alpha blending.',...
    'Value',0,...
    'Tag','Blend');
uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.05 Vobjpos(4) 0.9 Vobjdim],...
    'String','Diff',...
    'Style','radiobutton',...
    'TooltipString','Creates a difference image from A and B.',...
    'Value',0,...
    'Tag','Diff');
uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.05 Vobjpos(3) 0.9 Vobjdim],...
    'String','Montage',...
    'Style','radiobutton',...
    'TooltipString','Places A and B next to each other in the same image.',...
    'Value',1,...
    'Tag','Montage');
uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.05 Vobjpos(2) 0.9 Vobjdim],...
    'String','Flicker',...
    'Style','radiobutton',...
    'TooltipString',sprintf('Toggles (flickers) between A and B.\n(Default flicker frequency is 1 Hz; adjust frequency with buttons at right.)'),...
    'Value',0,...
    'Enable','on',...
    'Tag','Flicker');
pauseIcon = im2double(imread(fullfile(matlabroot,'toolbox','shared','dastudio','resources','glue','Toolbars','16px','Pause_16.png')));
pauseIcon(pauseIcon==0) = nan;
startIcon = im2double(imread(fullfile(matlabroot,'toolbox','shared','controllib','general','resources','toolstrip_icons','Play_16.png')));
startIcon(startIcon==0) = nan;
PauseButton = uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.5 Vobjpos(2) 0.15 Vobjdim],...
    'Fontname','Symbol',...
    'Fontsize',12,...
    'Fontweight','bold',...
    'String','',...%
    'Cdata',startIcon,...
    'Style','pushbutton',...
    'TooltipString','Stop/Start Flicker',...
    'Enable','off',...
    'Callback',@toggleTimerPause,...
    'Tag','PauseRestartFlicker');
ico = im2double(imread(fullfile(matlabroot,'toolbox','shared','dastudio','resources','glue','Toolbars','16px','Up_16.png')));
ico(ico==0) = nan;
FasterButton = uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.65 Vobjpos(2) 0.15 Vobjdim],...
    'Fontname','Symbol',...
    'Fontweight','bold',...
    'String','',...%''
    'Cdata',ico,...
    'Style','pushbutton',...
    'TooltipString','Increase flicker frequency',...
    'Enable','off',...
    'Callback',@flickerFaster,...
    'Tag','FlickerFaster');
ico = cat(3,flipud(ico(:,:,1)),flipud(ico(:,:,2)),flipud(ico(:,:,3)));%imread(fullfile(matlabroot,'toolbox','shared','controllib','general','resources','ShowHide_Minus.png'));
SlowerButton = uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.8 Vobjpos(2) 0.15 Vobjdim],...
    'Fontname','Symbol',...
    'Fontweight','bold',...
    'String','',...%
    'Cdata',ico,...
    'Style','pushbutton',...
    'TooltipString','Decrease flicker frequency',...
    'Enable','off',...
    'Callback',@flickerSlower,...
    'Tag','FlickerSlower');
uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.05 Vobjpos(1) 0.9 Vobjdim],...
    'String','Checkerboard',...
    'Style','radiobutton',...
    'TooltipString','Overlay images with checkerboard transparency.',...
    'Value',0,...
    'enable','on',...
    'Tag','Checkerboard');
TransformTypeButtonGroup = uibuttongroup(...
    'Parent',ImageRegFig,...
    'Title',' Transform Type Options ',...
    'Tag','TransformTypeButtonGroup',...
    'Position',[0.05 objpos(1) 0.15 objdim-del],...
    'SelectedObject',[],...
    'SelectionChangeFcn',@changeTformType,...
    'OldSelectedObject',[]);

[Vobjpos,Vobjdim] = distributeObjects(4,0.05,0.95,0.025);
uicontrol(...
    'Parent',TransformTypeButtonGroup,...
    'Position',[0.05 Vobjpos(4) 0.9 Vobjdim],...
    'String','Translation',...
    'Style','radiobutton',...
    'TooltipString','Specifies (x,y) translation to register the images.',...
    'Value',0,...
    'Tag','Translation');
uicontrol(...
    'Parent',TransformTypeButtonGroup,...
    'Position',[0.05 Vobjpos(3) 0.9 Vobjdim],...
    'String','Rigid',...
    'Style','radiobutton',...
    'TooltipString','Specifies rigid transformation consisting of translation and rotation.',...
    'Value',1,...
    'Tag','Rigid');
uicontrol(...
    'Parent',TransformTypeButtonGroup,...
    'Position',[0.05 Vobjpos(2) 0.9 Vobjdim],...
    'String','Similarity',...
    'Style','radiobutton',...
    'TooltipString','Specifies non-reflective similarity transformation consisting of translation, rotation, and scale.',...
    'Value',0,...
    'Tag','Similarity');
uicontrol(...
    'Parent',TransformTypeButtonGroup,...
    'Position',[0.05 Vobjpos(1) 0.9 Vobjdim],...
    'String','Affine',...
    'Style','radiobutton',...
    'TooltipString','Specifies affine transformation consisting of translation, rotation, scale, and shear.',...
    'Value',0,...
    'Tag','Affine');

PyramidLevelsPanel = uipanel(...
    'Parent',ImageRegFig,...
    'Title','Pyramid Levels',...
    'Tag','PyramidLevelsPanel',...
    'Position',[0.225 objpos(1) 0.105 0.075]);

PyramidLevels = 3;
PyramidLevelsValBox =  uicontrol(...
    'Parent',PyramidLevelsPanel,...
    'Callback','',...
    'Position',[0.05 0.2 0.9 0.5],...
    'String',1:10,...
    'Style','popupmenu',...
    'Value',PyramidLevels,...
    'Fontsize',10,...
    'TooltipString','The number of multi-level image pyramid levels to use.',...
    'Tag','PyramidLevelsValBox');

RegistrationConfigButtonGroup = uibuttongroup(...
    'Parent',ImageRegFig,...
    'Title',' Registration Type ',...
    'Tag','RegistrationConfigButtonGroup',...
    'Position',[0.225 0.205 0.105 0.125],...
    'SelectedObject',[],...
    'SelectionChangeFcn',@changeTformType,...
    'OldSelectedObject',[]);
uicontrol(...
    'Parent',RegistrationConfigButtonGroup,...
    'Position',[0.05 0.5 0.9 0.45],...
    'String','Monomodal',...
    'Style','radiobutton',...
    'TooltipString','For images that have similar brightness ranges. Typically, these images are captured on the same device.',...
    'Value',1,...
    'Tag','Monomodal');
uicontrol(...
    'Parent',RegistrationConfigButtonGroup,...
    'Position',[0.05 0.05 0.9 0.45],...
    'String','Multimodal',...
    'Style','radiobutton',...
    'TooltipString',sprintf(wrapString('For images that have different brightness ranges. Typically, these images are captured on different devices.',30)),...
    'Value',0,...
    'Tag','Multimodal');

RegistrationOptsPanel = uipanel(...
    'Parent',ImageRegFig,...
    'Title','Optimizer / Metric Parameters',...
    'Tag','RegistrationOptsPanel',...
    'Position',[0.355 objpos(1) 0.46 0.175+del*2]);

MonomodalOptsPanel = uipanel(...
    'Parent',RegistrationOptsPanel,...
    'Title','',...
    'Tag','MonomodalOptsPanel',...
    'Visible','on',...
    'Bordertype','none',...
    'Position',[0 0.025 0.95 0.95]);
%MONOMODAL OPTIONS
uicontrol(...
    'Parent',MonomodalOptsPanel,...
    'Callback','',...
    'Position',[0.0125 0.9 0.475 0.1],...
    'String','OPTIMIZER: Regular-Step Gradient Descent',...
    'Fontweight','bold',...
    'Foregroundcolor',fgc,...
    'Style','text',...
    'HorizontalAlignment','Left');
uicontrol(...
    'Parent',MonomodalOptsPanel,...
    'Callback','',...
    'Position',[0.55 0.9 0.375 0.1],...
    'String','METRIC: Mean Squares',...
    'Fontweight','bold',...
    'Foregroundcolor',fgc,...
    'Style','text',...
    'HorizontalAlignment','Left');

[Hobjpos,Hobjdim] = distributeObjects(3,0,1,0.025);
Hobjpos = Hobjpos+0.025;
tts = 'A positive scalar value that controls the optimization process. When the value of the gradient is smaller than this tolerance, it is an indication that the cost function may have reached a plateau.\nDefault: 1e-4.';
tts = sprintf(wrapString(tts,ttStringLength));
[GradMagTolSlider,GradMagTolPanel,GradMagTolEdt] = sliderPanel(...
    'Parent'  , MonomodalOptsPanel, ...
    'Title'   , 'Gradient Magnitude Tolerance', ...
    'Position', [Hobjpos(1) 0.45 Hobjdim 0.4], ...
    'Min'     , 1e-6, ...
    'Max'     , 1, ...
    'Value'   , 1e-4, ...
    'NumFormat','%0.4f',...
    'Fontsize',8,...
    'Callback', '');
set(GradMagTolSlider,'TooltipString',tts);
set(GradMagTolPanel,'Bordertype','none');
% set([GradMagTolSlider,GradMagTolPanel,GradMagTolEdt],'hittest','off');
% set(GradMagTolSlider,'callback',@testing)

tts = 'A positive scalar value that controls the accuracy of convergence. The choice of smaller values may lead to more accurate optimization of the metric at the expense of slower convergence.\nDefault: 1e-5.';
tts = sprintf(wrapString(tts,ttStringLength));
[MinStepLengthSlider,MinStepLengthPanel,MinStepLengthEdt] = sliderPanel(...
    'Parent'  , MonomodalOptsPanel, ...
    'Title'   , 'Minimum Step Length', ...
    'Position', [Hobjpos(1) 0 Hobjdim 0.4], ...
    'Min'     , 1e-7, ...
    'Max'     , 1, ...
    'Value'   , 1e-5, ...
    'NumFormat','%0.4f',...
    'Fontsize',8,...
    'Callback', '');
set(MinStepLengthSlider,'TooltipString',tts);
set(MinStepLengthPanel,'Bordertype','none');

tts = 'A positive scalar value that controls the initial step length used in optimization. A larger values may lead to faster convergence. Overly large values may result in failure to converge.\nDefault: 6.25e-2.';
tts = sprintf(wrapString(tts,ttStringLength));
[MaxStepLengthSlider,MaxStepLengthPanel,MaxStepLengthEdt] = sliderPanel(...
    'Parent'  , MonomodalOptsPanel, ...
    'Title'   , 'Maximum Step Length', ...
    'Position', [Hobjpos(2) 0 Hobjdim 0.4], ...
    'Min'     , 1e-7, ...
    'Max'     , 1, ...
    'Value'   , 6.25e-2, ...
    'NumFormat','%0.4f',...
    'Fontsize',8,...
    'Callback', '');
set(MaxStepLengthSlider,'TooltipString',tts);
set(MaxStepLengthPanel,'Bordertype','none');

tts = 'A positive scalar value that controls the maximum number of iterations per pyramid level that may be performed by the optimizer during registration. The registration may converge before the maximum number of iterations is reached.\nDefault: 100.';
tts = sprintf(wrapString(tts,ttStringLength));
[MonomodalMaxIterationsSlider,MonomodalMaxIterationsPanel,MonomodalMaxIterationsEdt] = sliderPanel(...
    'Parent'  , MonomodalOptsPanel, ...
    'Title'   , 'Maximum Iterations', ...
    'Position', [Hobjpos(2) 0.45 Hobjdim 0.4], ...
    'Min'     , 1, ...
    'Max'     , 1e3, ...
    'Value'   , 100, ...
    'NumFormat','%0.0f',...
    'Fontsize',8,...
    'Callback', '');
set(MonomodalMaxIterationsSlider,'TooltipString',tts);
set(MonomodalMaxIterationsPanel,'Bordertype','none');

tts = 'A scalar value in the range (0,1) that defines the rate at which the optimizer step size is reduced during convergence. Whenever the optimizer encounters that the direction of movement has changed in parameter space, it reduces the size of the step length. For noisy metrics, larger relaxation factors will lead to more stable convergence at the expense of increased computation time.\nDefault: 0.5.';
tts = sprintf(wrapString(tts,ttStringLength));
[RelaxationFactorSlider,RelaxationFactorPanel,RelaxationFactorEdt] = sliderPanel(...
    'Parent'  , MonomodalOptsPanel, ...
    'Title'   , 'Relaxation Factor', ...
    'Position', [Hobjpos(3) 0.45 Hobjdim 0.4], ...
    'Min'     , 1e-3, ...
    'Max'     , 1-1e-3, ...
    'Value'   , 0.5, ...
    'NumFormat','%0.3f',...
    'Fontsize',8,...
    'Callback', '');
set(RelaxationFactorSlider,'TooltipString',tts);
set(RelaxationFactorPanel,'Bordertype','none');

MultimodalOptsPanel = uipanel(...
    'Parent',RegistrationOptsPanel,...
    'Title','',...
    'Tag','MonomodalOptsPanel',...
    'Visible','off',...
    'Bordertype','none',...
    'Position',[0 0.025 0.95 0.95]);
%MULTIMODAL OPTIONS
uicontrol(...
    'Parent',MultimodalOptsPanel,...
    'Callback','',...
    'Position',[0.0125 0.9 0.475 0.1],...
    'String','OPTIMIZER: One-Plus-One Evolutionary',...
    'Fontweight','bold',...
    'Foregroundcolor',fgc,...
    'Style','text',...
    'HorizontalAlignment','Left');
uicontrol(...
    'Parent',MultimodalOptsPanel,...
    'Callback','',...
    'Position',[0.55 0.9 0.45 0.1],...
    'String','METRIC: Mattes Mutual Information',...
    'Fontweight','bold',...
    'Foregroundcolor',fgc,...
    'Style','text',...
    'HorizontalAlignment','Left');

[Hobjpos,Hobjdim] = distributeObjects(3,0,0.85,0.025);
Hobjpos = Hobjpos+0.025;

tts = 'A positive scalar value that controls the rate at which the search radius grows in parameter space. For a big GrowthFactor, the optimization is fast, but more likely to end in a local minimum. The choice of smaller values of GrowthFactor leads to slower optimization.\nDefault: 1.05.';
tts = sprintf(wrapString(tts,ttStringLength));
[GrowthFactorSlider,GrowthFactorPanel,GrowthFactorEdt] = sliderPanel(...
    'Parent'  , MultimodalOptsPanel, ...
    'Title'   , 'Growth Factor', ...
    'Position', [Hobjpos(1) 0.45 Hobjdim 0.4], ...
    'Min'     , 1.0001, ...
    'Max'     , 10, ...
    'Value'   , 1.05, ...
    'NumFormat','%0.5f',...
    'Fontsize',8,...
    'Callback', '');
set(GrowthFactorSlider,'TooltipString',tts);
set(GrowthFactorPanel,'Bordertype','none');

tts = 'A positive scalar value that controls the accuracy of convergence by adjusting the minimal size of the search radius. The choice of smaller values of Epsilon may lead to more accurate optimization of the metric at the expense of slower convergence.\nDefault: 1.5e-6.';
tts = sprintf(wrapString(tts,ttStringLength));
[EpsilonSlider,EpsilonPanel,EpsilonEdt] = sliderPanel(...
    'Parent'  , MultimodalOptsPanel, ...
    'Title'   , 'Epsilon', ...
    'Position', [Hobjpos(1) 0 Hobjdim 0.4], ...
    'Min'     , 1e-8, ...
    'Max'     , 1, ...
    'Value'   , 1.5e-6, ...
    'NumFormat','%0.6f',...
    'Fontsize',8,...
    'Callback', '');
set(EpsilonSlider,'TooltipString',tts);
set(EpsilonPanel,'Bordertype','none');

tts = 'A positive scalar value that controls the initial search radius of the optimizer. Increasing InitialRadius can lead to faster convergence. Overly large values of InitialRadius may fail to converge.\nDefault: 0.00625';
tts = sprintf(wrapString(tts,ttStringLength));
[InitialRadiusSlider,InitialRadiusPanel,InitialRadiusEdt] = sliderPanel(...
    'Parent'  , MultimodalOptsPanel, ...
    'Title'   , 'Initial Radius', ...
    'Position', [Hobjpos(2) 0 Hobjdim 0.4], ...
    'Min'     , 1e-4, ...
    'Max'     , 1e-1, ...
    'Value'   , 6.25e-3, ...
    'NumFormat','%0.4f',...
    'Fontsize',8,...
    'Callback', '');
set(InitialRadiusSlider,'TooltipString',tts);
set(InitialRadiusPanel,'Bordertype','none');
tmp = get(InitialRadiusEdt,'pos');
%Tweak because the display of many digits requires a bigger
%edit box:
set(InitialRadiusEdt,'pos',[tmp(1) tmp(2) tmp(3)+0.02 tmp(4)]);

tts = 'A positive scalar value that controls the maximum number of iterations per pyramid level that may be performed by the optimizer during registration. The registration may converge before the maximum number of iterations is reached.\nDefault: 100.';
tts = sprintf(wrapString(tts,ttStringLength));
[MultimodalMaxIterationsSlider,MultimodalMaxIterationsPanel,MultimodalMaxIterationsEdt] = sliderPanel(...
    'Parent'  , MultimodalOptsPanel, ...
    'Title'   , 'Maximum Iterations', ...
    'Position', [Hobjpos(2) 0.45 Hobjdim 0.4], ...
    'Min'     , 1, ...
    'Max'     , 1e3, ...
    'Value'   , 100, ...
    'NumFormat','%0.0f',...
    'Fontsize',8,...
    'Callback', '');
set(MultimodalMaxIterationsSlider,'TooltipString',tts);
set(MultimodalMaxIterationsPanel,'Bordertype','none');

tts = 'A positive scalar integer value that defines the number of random pixels used to compute the metric. This property is only used when UseAllPixels is false. More samples means longer computation time with improved run to run reproducibility of registration results.\nDefault: 500.';
tts = sprintf(wrapString(tts,ttStringLength));
[NumSpatialSamplesSlider,NumSpatialSamplesPanel,NumSpatialSamplesEdt] = sliderPanel(...
    'Parent'  , MultimodalOptsPanel, ...
    'Title'   , 'Number Spatial Samples', ...
    'Position', [Hobjpos(3) 0.45 Hobjdim 0.4], ...
    'Min'     , 1, ...
    'Max'     , 1000, ...
    'Value'   , 500, ...
    'NumFormat','%0.0f',...
    'Fontsize',8,...
    'Callback', '');
set(NumSpatialSamplesSlider,'TooltipString',tts);
set(NumSpatialSamplesPanel,'Bordertype','none');

tts = 'A positive scalar integer value that defines the number of bins used in the joint histogram computation. The minimum value is 5.\nDefault: 50';
tts = sprintf(wrapString(tts,ttStringLength));
[NumHistogramBinsSlider,NumHistogramBinsPanel,NumHistogramBinsEdt] = sliderPanel(...
    'Parent'  , MultimodalOptsPanel, ...
    'Title'   , 'Number Histogram Bins', ...
    'Position', [Hobjpos(3) 0 Hobjdim 0.4], ...
    'Min'     , 5, ...
    'Max'     , 1000, ...
    'Value'   , 50, ...
    'NumFormat','%0.0f',...
    'Fontsize',8,...
    'Callback', '');
set(NumHistogramBinsSlider,'TooltipString',tts);
set(NumHistogramBinsPanel,'Bordertype','none');

tts = 'A logical value that controls whether all of the pixels in the overlapping region of the fixed and moving images are used to compute the metric. You can achieve significantly better performance by setting this property to false. When UseAllPixels is false, the NumberOfSpatialSamples property controls the number of random pixel locations that are used to compute the metric. When UseAllPixels is false, results from imregister may not be reproducible due to the use of a random subsetting of pixels in the fixed and moving images to compute the metric.\nDefault: true';
tts = sprintf(wrapString(tts,ttStringLength));
UseAllPixels = uicontrol(...
    'Parent',MultimodalOptsPanel,...
    'Callback','',...
    'Position',[0.9 0.15 0.05 0.1],...
    'String','',...
    'Style','checkbox',...
    'Value',1,...
    'Tag','UseAllPixels',...
    'TooltipString',tts);
uicontrol(...
    'Parent',MultimodalOptsPanel,...
    'Position',[0.935 0 0.1 0.3],...
    'String',sprintf('Use All\nPixels'),...
    'Style','text',...
    'HorizontalAlignment','left',...
    'TooltipString',tts)
%

DisplayOptimizations = uicontrol(...
    'Parent',ImageRegFig,...
    'Callback','',...
    'Position',[0.835 0.235 0.115 0.05],...
    'String','Display Optimizations',...
    'Style','checkbox',...
    'Value',1,...
    'Tag','DisplayOptimizations',...
    'TooltipString','Specifies whether to display optimization information to the MATLAB command window.');

ProcessButton = uicontrol(...
    'Parent',ImageRegFig,...
    'Callback',@registerImages,...
    'FontSize',12,...
    'Fontweight','b',...
    'Position',[0.835 0.175 0.115 0.055],...
    'String','Process Now',...
    'Tooltipstring','Caveat: Registration processes can be long, and cannot readily be escaped from.',...
    'Tag','ProcessButton');

ExportButton = uicontrol(...
    'Parent',ImageRegFig,...
    'Callback',@exportResults,...
    'FontSize',9,...
    'Fontweight','b',...
    'Position',[0.835 objpos(1) 0.115 0.055],...
    'String','Export/Save Results',...
    'Enable','off',...
    'Tag','ProcessButton');

CommentsPanel = uipanel(...
    'Parent',ImageRegFig,...
    'Title','Comments/Status',...
    'Tag','CommentsPanel',...
    'Position',[0.05 0.03 0.9 0.0625]);
CommentsBox = uicontrol(...
    'Parent',CommentsPanel,...
    'Style','Edit',...
    'String','Welcome to ImageRegistrationApp!  2013 The MathWorks, Inc.',...
    'Tag','CommentsBox',...
    'Fontsize',12,...
    'Position',[-0.001 -0.01 1.001 1.07],...
    'Enable','Inactive');

optimizer = [];
metric = [];

% -----------------SUBFUNCTIONS-------------------------------------

    function acknowledge(varargin)
        mssg = {'',...
            '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ',...
            '',...
            'I would like to acknowledge and thank the following for',...
            'suggestions, reviews, and critiques of this tool:',...
            '',...
            'Jeff Mather',...
            'Alex Taylor',...
            'Ashish Uthama',...
            'The Image Processing Toolbox Development Team',...
            '',...
            'Comments and suggestions are welcome,',...
            'and should be addressed to me at:',...
            '',...
            'brett.shoelson@mathworks.com',...
            '',...
            ' The MathWorks, 2013.',...
            '',...
            '',...
            '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~        ~          ~',...
            ''};
        h = msgbox(mssg,'ImageRegistrationApp Acknowledgments','help','modal') ;
        msghndl = findobj(h,'tag','MessageBox');
        set(msghndl,'color',[0 0 0.7],'fontweight','b')
        set(gcbo,'state','off')
    end

    function changeTformType(varargin)
        if strcmp(get(gcbo,'tag'),'Monomodal')
            set(MultimodalOptsPanel,'visible','off')
            set(MonomodalOptsPanel,'visible','on')
            [optimizer, metric] = imregconfig('Monomodal');
        elseif strcmp(get(gcbo,'tag'),'Multimodal')
            set(MonomodalOptsPanel,'visible','off')
            set(MultimodalOptsPanel,'visible','on')
            [optimizer, metric] = imregconfig('Multimodal');
        end
    end

    function changeVisualizationOption(varargin)
        if strcmp(get(gcbo,'tag'),'Flicker')
            set([FasterButton,SlowerButton,PauseButton],'enable','on')
            set(PauseButton,'cdata',pauseIcon);
        else
            set([FasterButton,SlowerButton,PauseButton],'enable','off')
        end
        visualizeResults;
    end

    function clearDistlineTools(varargin)
        delete(findall(ImageRegFig,'tag','imline'));
        set(gcbo,'state','off');
    end

    function clearMarkedPoints(varargin)
        delete(findall(ImageRegFig,'tag','impoint'));
        set(gcbo,'state','off');
    end

    function closetimer(varargin)
        t = timerfindall('TimerFcn',@flickerResults);
        if ~isempty(t)
            stop(t);
            delete(t);
        end
        if strcmp(get(gcbo,'type'),'figure')
            delete(ImageRegFig)
        end
    end

    function exportResults(varargin)
        nPyramids = get(PyramidLevelsValBox,'value');
        transformType = getButtonGroupVal(TransformTypeButtonGroup,'tag');
        regType = getButtonGroupVal(RegistrationConfigButtonGroup,'tag');
        displayOpt = get(DisplayOptimizations,'value');
        %
        fprintf('\n\nCALLING SYTNAX:\n**************************\n\n');
        fprintf('[optimizer,metric] = imregconfig(''%s'');\n%%\n',regType);
        fprintf('%% Modifications to optimizer/metric\n')
        if strcmp(regType,'Monomodal')
            fprintf('optimizer.GradientMagnitudeTolerance = %f;\n',get(GradMagTolSlider,'value'));
            fprintf('optimizer.MinimumStepLength = %f;\n',get(MinStepLengthSlider,'value'));
            fprintf('optimizer.MaximumStepLength = %f;\n',get(MaxStepLengthSlider,'value'));
            fprintf('optimizer.MaximumIterations = %d;\n',round(get(MonomodalMaxIterationsSlider,'value')));
            fprintf('optimizer.RelaxationFactor = %f;\n',get(RelaxationFactorSlider,'value'));
        elseif strcmp(regType,'Multimodal')
            fprintf('optimizer.GrowthFactor = %g;\n',get(GrowthFactorSlider,'value'));
            fprintf('optimizer.Epsilon = %g;\n',get(EpsilonSlider,'value'));
            fprintf('optimizer.InitialRadius = %g;\n',get(InitialRadiusSlider,'value'));
            fprintf('optimizer.MaximumIterations = %d;\n',round(get(MultimodalMaxIterationsSlider,'value')));
            fprintf('metric.NumberOfSpatialSamples = %d;\n',round(get(NumSpatialSamplesSlider,'value')));
            fprintf('metric.NumberOfHistogramBins = %d;\n',round(get(NumHistogramBinsSlider,'value')));
            fprintf('metric.UseAllPixels = %d;\n',get(UseAllPixels,'value'));
        end
        if iptver < 8.2
            fprintf('\n%%\n[registered,SRI] = imregister(%s,%s,''%s'',optimizer,metric,''DisplayOptimization'',%d,''PyramidLevels'',%d);\n',...
                mname,fname,transformType,displayOpt,nPyramids);
        else
            fprintf('%%\nTForm = imregtform(%s,%s,''%s'',optimizer,metric,''DisplayOptimization'',%d,''PyramidLevels'',%d);\n',...
                mname,fname,transformType,displayOpt,nPyramids);
            fprintf('if size(%s,3)==1\n\tRfixed = imref2d(size(%s));\nelse\n\tRfixed = imref3d(size(%s));\nend\n',fname,fname,fname);
            fprintf('[registered,SRI] = imwarp(%s,TForm,''OutputView'',Rfixed);\n%%',mname);
            fprintf('\n%%OR:%%\n[registered,SRI] = imregister(%s,%s,''%s'',optimizer,metric,''DisplayOptimization'',%d,''PyramidLevels'',%d);\n',...
                mname,fname,transformType,displayOpt,nPyramids);
        end
        
        fprintf('\n%%imshowpair(fixed,registered);\n');
        fprintf('\n**************************\n')
        fprintf('\n\nNOTES:\n\n1)SRI returns the "spatial referencing information" associated with the registration.\n(DOC: imregister)\n\n')
        if iptver >= 8.2
            fprintf('2) You can specify additional options for the |IMWARP| command.\n(DOC: imwarp)\n')
        end
        varname1 = evalin('base','genvarname(''Registered'',who)');
        varname2 = evalin('base','genvarname(''TForm'',who)');
        set(CommentsBox,'string',sprintf('Calling syntax written to Command Window; registered image saved as ''%s'' in base workspace; transform matrix written as ''%s''.',varname1,varname2));
        assignin('base',varname2,tform);
        assignin('base',varname1,registered);
    end

    function flickerFaster(varargin)
        t = timerfindall('TimerFcn',@flickerResults);
        if ~isempty(t)
            stop(t);
            newFreq = 1/(get(t,'Period')*0.8);
            setappdata(ImageRegFig,'FlickerFreq',newFreq);
            set(PauseButton,'cdata',pauseIcon);
            set(CommentsBox,'string',sprintf('Setting flicker frequency to %0.3f Hz.',newFreq));
            set(t,'Period',1/newFreq)
            start(t);
        end
    end

    function flickerSlower(varargin)
        t = timerfindall('TimerFcn',@flickerResults);
        if ~isempty(t)
            stop(t);
            newFreq = 1/(get(t,'Period')*1.2);
            setappdata(ImageRegFig,'FlickerFreq',newFreq);
            set(PauseButton,'cdata',pauseIcon);
            set(CommentsBox,'string',sprintf('Setting flicker frequency to %0.3f Hz.',newFreq));
            set(t,'Period',1/newFreq)
            start(t);
        end
    end


    function flickerResults(varargin)
        try
            currDisp = getappdata(ImageRegFig,'CurrDisp');
            if strcmp(currDisp,'Fixed')
                setappdata(ImageRegFig,'CurrDisp','Registered');
                AlignedImageObj = imshow(registered,[]);
                
            else
                setappdata(ImageRegFig,'CurrDisp','Fixed');
                AlignedImageObj = imshow(fixedInputImage,[]);
            end
        catch
            disp('Failed!')
            closetimer
        end
    end

    function val = getButtonGroupVal(bg,loc)
        tmpVal = find(cell2mat(get(get(bg,'children'),'value')));
        tmpStrings = get(get(bg,'children'),loc);
        val = tmpStrings{tmpVal};%#ok
    end

    function GetNewFile(varargin)
        set(gcbo,'state','off');
        filterspec = imgformats(1);
        oldMname = mname;
        oldFname = fname;
        [fname,pathname] = uigetfile(filterspec, 'Select new FIXED image. (Cancel to keep unchanged.)');
        if ischar(fname)
            fixedInputImage = iptImread(fullfile(pathname,fname));
        else
            fname = oldFname;
        end
        currpath = pwd;
        if pathname ~= 0
            cd(pathname)
        end
        [mname,pathname] = uigetfile(filterspec, 'Select new MOVING image. (Cancel to keep unchanged.)');
        cd(currpath);
        if ischar(mname)
            movingInputImage = iptImread(fullfile(pathname,mname));
        else
            mname = oldMname;
        end
        if strcmp(fname, oldFname) && strcmp(mname, oldMname)
            % Nothing new selected!
            set(CommentsBox,'string','It appears that you haven''t selected any new images!');
            return
        end
        preprocessImages;
        imshow(fixedInputImage,[],'parent',FixedImageAxes);
        title('__ FIXED IMAGE __',...
            'color',fgc,'fontsize',12,...
            'Interpreter','none','parent',FixedImageAxes);
        imshow(movingInputImage,[],'parent',MovingImageAxes);
        title('__ MOVING IMAGE __',...
            'color',fgc,'fontsize',12,...
            'Interpreter','none','parent',MovingImageAxes);
        registered = movingInputImage;
        visualizeResults;
        %movingInputImage = fullfile(pathname,mname);
        %ImageRegistrationApp(fixedInputImage,movingInputImage)
    end

    function imout = iptImread(imname,varargin)
        [~,~,ext] = fileparts(imname);
        switch ext
            case '.dcm'
                imout = dicomread(imname);
            case {'.fits','.fts'}
                imout = fitsread(imname);
            case '.img'
                try
                    imout = analyze75read(imname);
                catch
                    try
                        imout = interfilered(imname);
                    catch
                        error('Unknown image format.');
                    end
                end
            case '.nitf'
                imout = nitfread(imname);
            case '.hdr'
                imout = hdrread(imname);
            otherwise
                imout = imread(imname);
        end
    end

    function markPoints(varargin)
        markImagePoints(gca,'markedPoints',[0 110 110]/255);
        set(gcbo,'state','off');
        set(ImageRegFig,'currentcharacter','1') % double('1') = 49
        while double(get(ImageRegFig,'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 preprocessImages(varargin)
        %convertedFromRGB = false;
        if size(fixedInputImage,3)==3
            %originalFixed = fixedInputImage;
            fixedInputImage = rgb2gray(fixedInputImage);
        end
        if size(movingInputImage,3)==3
            %convertedFromRGB = true;
            %originalMovingImage = movingInputImage;
            movingInputImage = rgb2gray(movingInputImage);
        end
        if islogical(fixedInputImage)
            fixedInputImage = im2double(fixedInputImage);
        end
        if islogical(movingInputImage)
            movingInputImage = im2double(movingInputImage);
        end
    end

    function registerImages(varargin)
        set(ProcessButton,'enable','off');
        set(CommentsBox,'string','Registration in process...please wait. (This process cannot be canceled.)');
        drawnow;
        closetimer;
        %
        nPyramids = get(PyramidLevelsValBox,'value');
        requiredPixelsPerDim = 4.^(nPyramids-1);%caret
        fixedTooSmallToPyramid  = any(size(fixedInputImage) < requiredPixelsPerDim);
        movingTooSmallToPyramid = any(size(movingInputImage) < requiredPixelsPerDim);
        if fixedTooSmallToPyramid || movingTooSmallToPyramid
            beep
            set(CommentsBox,'string','Your fixed or moving images are too small for the selected number of pyramids! (Please select a smaller number of pyramids.)');
            set(ProcessButton,'enable','on');
            return
        end
        %
        tic;
        transformType = getButtonGroupVal(TransformTypeButtonGroup,'tag');
        %
        regType = getButtonGroupVal(RegistrationConfigButtonGroup,'tag');
        %
        displayOpt = get(DisplayOptimizations,'value');
        %
        [optimizer,metric] = imregconfig(regType);
        if strcmp(regType,'Monomodal')
            optimizer.GradientMagnitudeTolerance = get(GradMagTolSlider,'value');
            optimizer.MinimumStepLength = get(MinStepLengthSlider,'value');
            optimizer.MaximumStepLength = get(MaxStepLengthSlider,'value');
            optimizer.MaximumIterations = round(get(MonomodalMaxIterationsSlider,'value'));
            optimizer.RelaxationFactor = get(RelaxationFactorSlider,'value');
        elseif strcmp(regType,'Multimodal')
            optimizer.GrowthFactor = get(GrowthFactorSlider,'value');
            optimizer.Epsilon = get(EpsilonSlider,'value');
            optimizer.InitialRadius = get(InitialRadiusSlider,'value');
            optimizer.MaximumIterations = round(get(MultimodalMaxIterationsSlider,'value'));
            metric.NumberOfSpatialSamples = round(get(NumSpatialSamplesSlider,'value'));
            metric.NumberOfHistogramBins = round(get(NumHistogramBinsSlider,'value'));
            metric.UseAllPixels = get(UseAllPixels,'value');
        end
        %optimizer
        %metric
        %         [registered,tform] = imregister(movingInputImage,...
        %             fixedInputImage,transformType,...
        %             optimizer,metric,...
        %             'DisplayOptimization',displayOpt,...
        %             'PyramidLevels',nPyramids);
        %         if convertedFromRGB
        %             registered = imtransform(originalMovingImage,tform);
        %         end
        
        %clc;
        if iptver < 8.2
            registered = imregister(movingInputImage,...
                fixedInputImage,transformType,...
                optimizer,metric,...
                'DisplayOptimization',displayOpt,...
                'PyramidLevels',nPyramids);
        else
            tform = imregtform(movingInputImage,...
                fixedInputImage,transformType,...
                optimizer,metric,...
                'DisplayOptimization',displayOpt,...
                'PyramidLevels',nPyramids);
            if size(fixedInputImage,3)==1
                Rfixed = imref2d(size(fixedInputImage));
            else
                Rfixed = imref3d(size(fixedInputImage));
            end
            [registered,~] = imwarp(movingInputImage,tform,...
                'OutputView',Rfixed);
        end
        set(ExportButton,'enable','on')
        visualizeResults;
        t = toc;
        set(ProcessButton,'enable','on');
        set(CommentsBox,'string',sprintf('Registration complete. (Elapsed time = %0.2f seconds.)',t));
    end

    function resetDefaults(varargin)
        set(gcbo,'state','off');
        %Defaults
        %GradMagTolSlider,GradMagPanelEdt: 1e-4
        set(GradMagTolSlider,'value',1e-4);
        set(GradMagTolEdt,'string',1e-4);
        %MinStepLengthSlider,MinStepLengthEdt:1e-5
        set(MinStepLengthSlider,'value',1e-5);
        set(MinStepLengthEdt,'string',1e-5);
        %MaxStepLengthSlider,MaxStepLengthEdt:6.25e-2
        set(MaxStepLengthSlider,'value',6.25e-2);
        set(MaxStepLengthEdt,'string',6.25e-2);
        %MonomodalMaxIterationsSlider,MonomodalMaxIterationsEdt: 100
        set(MonomodalMaxIterationsSlider,'value',100);
        set(MonomodalMaxIterationsEdt,'string',100);
        %RelaxationFactorSlider,RelaxationFactorEdt: 0.5
        set(RelaxationFactorSlider,'value',0.5);
        set(RelaxationFactorEdt,'string',0.5);
        %GrowthFactorSlider,,GrowthFactorEdt: 1.05
        set(GrowthFactorSlider,'value',1.05);
        set(GrowthFactorEdt,'string',1.05);
        %EpsilonSlider,,EpsilonEdt: 1.5e-6
        set(EpsilonSlider,'value',1.5e-6);
        set(EpsilonEdt,'string',1.5e-6);
        %InitialRadiusSlider,,InitialRadiusEdt: 6.25e-3
        set(InitialRadiusSlider,'value',6.25e-3);
        set(InitialRadiusEdt,'string',6.25e-3);
        %MultimodalMaxIterationsSlider,MultimodalMaxIterationsEdt: 100
        set(MultimodalMaxIterationsSlider,'value',100);
        set(MultimodalMaxIterationsEdt,'string',100);
        %NumSpatialSamplesSlider,NumSpatialSamplesEdt: 500
        set(NumSpatialSamplesSlider,'value',500);
        set(NumSpatialSamplesEdt,'string',500);
        %NumHistogramBinsSlider,NumHistogramBinsEdt: 50
        set(NumHistogramBinsSlider,'value',50);
        set(NumHistogramBinsEdt,'string',50);
        %UseAllPixels: true
        set(UseAllPixels,'value',1);
        %Reset flicker frequency to 1 Hz
        setappdata(ImageRegFig,'FlickerFreq',1);
        visualizeResults;
    end


    function toggleTimerPause(varargin)
        t = timerfindall('TimerFcn',@flickerResults);
        if ~isempty(t)
            if strcmp(get(t,'Running'),'on')
                stop(t)
                set(varargin{1},'cdata',startIcon)
            else
                start(t)
                set(varargin{1},'cdata',pauseIcon)
            end
        end
    end

    function visualizeResults(varargin)
        visType = getButtonGroupVal(VisualizationOptsButtonGroup,'tag');
        closetimer;
        axes(ShowAlignmentAxes);
        cla;
        %set(gca,'NextPlot','replace')
        drawnow
        if strcmp(visType,'Flicker')
            % CREATE AND START TIMER OBJECT, with 1-second (fixed) period
            timerobj = timer('timerfcn',@flickerResults,'period',getappdata(ImageRegFig,'FlickerFreq'),...
                'executionmode','fixedrate');
            start(timerobj);
        elseif strcmp(visType,'Checkerboard')
            chkrbd = checkerboard(max(ceil(size(registered)/8)));
            chkrbd = chkrbd > 0.5;%Convert to binary
            chkrbd = chkrbd(1:size(registered,1),1:size(registered,2));
            imshow(fixedInputImage,[]);
            hold on
            AlignedImageObj = imshow(registered,[]);
            set(AlignedImageObj,'alphadata',chkrbd);
            hold off;
        else
            %closetimer;
            tmp = imshowpair(fixedInputImage,registered,visType);
        end
    end

    function newString = wrapString(longString,numChars)
        % Returns an sprintf-formattable string of
        % (approximately) length numChars
        tmpx = uicontrol('style', 'text', 'units','characters','position', [0 0 numChars 10],'visible','off');
        tmpString = textwrap(tmpx,{longString});
        delete(tmpx)
        newString = '';
        for ii = 1:size(tmpString,1)
            newString = [newString,tmpString{ii},'\n'];%#ok
        end
    end

end

Contact us