Code covered by the BSD License  

Highlights from
Image Registration GUI

image thumbnail
from Image Registration GUI by Brett Shoelson
GUI environment for registering a Moving image to a Fixed image

ImageRegistrationGUI.m
function ImageRegistrationGUI(movingInputImage,fixedInputImage)
% GUI 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:
% ImageRegistrationGUI
%   Launches a GUI with default images.
%   (New images can be loaded from the menu.)
%
% ImageRegistrationGUI(moving_image,fixed_image);
%   Launches a GUI with user-specified Moving and Fixed
%   images. Images can be specified by name, or provided
%   directly.
%
% CLASS SUPPORT/NOTE: ImageRegistrationGUI 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). Direct output of the transformation matrix
%    ("TFORM") is not currently supported. But if you enable
%    the "DisplayOptimizations" checkbox, syntax is provided
%    for generation of the TFORM. You can apply that TFORM
%    directly to any image class supported by IMTRANSFORM
%    (including RGB and logical).
%
%
% EXAMPLES:
%
%    % Example 1
%    fixedInputImage = imread('pout.tif');
%    movingInputImage = [[ones(291,10)*110 fixedInputImage]; ones(10,250)*110];
%    movingInputImage = imrotate(movingInputImage,5,'bicubic','crop');
%    ImageRegistrationGUI(movingInputImage,fixedInputImage)
%
%    % Example 2
%    fixed = 'peppers.png';
%    moving = imrotate(imread(fixed),5,'bicubic');
%    ImageRegistrationGUI(moving,fixed)
%    % (Registration is facilitated on grayscale
%    %  representations of these images. With
%    %  "DisplayOptimizations" enabled, the TFORM struct, t,
%    %  is displayed. You can then create an appropriate
%    %  TFORM using TFORM = maketform(t,'afine'), and then
%    %  register the COLOR image using:
%    IMTRANSFORM(moving,TFORM)
%
% Written by Brett Shoelson, PhD
% brett.shoelson@mathworks.com
% Comments and suggestions welcome!
%
% Version:
%   1.0;     12/28/2011 (Original)
%   1.0.1;   8/8/2012: Better management of path when
%            selecting new images.
%
% Copyright 2012 MathWorks, Inc.
%
% See Also: IMREGISTER, IMREGCONFIG, IMTRANSFORM, MAKETFORM


 if verLessThan('images','8.0')
     beep
     disp('SORRY! ImageRegistrationGUI requires Image Processing Toolbox Ver. 8.0 (MATLAB R2012a) or later!');
     return
 end

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('ImageRegistrationGUI: 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;
ttStringLength = 50; %Tooltip string length (for autowrapping)
defaultFlickerFreq = 1; %Hz

ImageRegFig = figure(...
    'numbertitle','off',...
    'windowstyle','normal',...
    'name','Image Registration GUI',...
    '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;
loadImageTool              = 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;
zoomTool                 = 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]);
distanceTool             = uitoggletool(ht,...
    'CData',               tmp,...
    'separator',           'on',...
    '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,...
    'separator',           'on',...
    '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 optimizer/metric parameters to defaults. Also resets flicker frequency to 1 Hz.');

tmp = imread('logo.png');
infoButton = 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');

FixedImageObj = imshow(fixedInputImage,[]);
FixedImageTitle = 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');

MovingImageObj = imshow(movingInputImage,[]);
%MovingImageTitle = title(mname);
MovingImageTitle = 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(5,0.05,0.95,0.025);
FalseColorOpt = uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.05 Vobjpos(5) 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');
BlendOpt = uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.05 Vobjpos(4) 0.9 Vobjdim],...
    'String','Blend',...
    'Style','radiobutton',...
    'TooltipString','Overlays A and B using alpha blending.',...
    'Value',0,...
    'Tag','Blend');
DiffOpt = uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.05 Vobjpos(3) 0.9 Vobjdim],...
    'String','Diff',...
    'Style','radiobutton',...
    'TooltipString','Creates a difference image from A and B.',...
    'Value',0,...
    'Tag','Diff');
MontageOpt = uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.05 Vobjpos(2) 0.9 Vobjdim],...
    'String','Montage',...
    'Style','radiobutton',...
    'TooltipString','Places A and B next to each other in the same image.',...
    'Value',1,...
    'Tag','Montage');
FlickerOpt = uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.05 Vobjpos(1) 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');
PauseButton = uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.5 Vobjpos(1) 0.15 Vobjdim],...
    'Fontname','Symbol',...
    'Fontsize',12,...
    'Fontweight','bold',...
    'String','',...
    'Style','pushbutton',...
    'TooltipString','Stop/Start Flicker',...
    'Enable','off',...
    'Callback',@toggleTimerPause,...%closetimer
    'Tag','PauseRestartFlicker');
FasterButton = uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.65 Vobjpos(1) 0.15 Vobjdim],...
    'Fontname','Symbol',...
    'Fontweight','bold',...
    'String','',...
    'Style','pushbutton',...
    'TooltipString','Increase flicker frequency',...
    'Enable','off',...
    'Callback',@flickerFaster,...
    'Tag','FlickerFaster');
SlowerButton = uicontrol(...
    'Parent',VisualizationOptsButtonGroup,...
    'Position',[0.8 Vobjpos(1) 0.15 Vobjdim],...
    'Fontname','Symbol',...
    'Fontweight','bold',...
    'String','',...
    'Style','pushbutton',...
    'TooltipString','Decrease flicker frequency',...
    'Enable','off',...
    'Callback',@flickerSlower,...
    'Tag','FlickerSlower');

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);
TranslationOpt = 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');
RigidOpt = 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');
SimilarityOpt = 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');
AffineOpt = 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',[]);
MonomodalOpt = 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');
MultimodalOpt = 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 tofaster 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','DisplayOptimizations',...
    '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.');

optimizeIt = uicontrol(...
    'Parent',ImageRegFig,...
    'Callback',@optimizeResults,...
    'string','Optimize It!',...
    'Position',[0.835 0.275 0.115 0.05]);

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 ImageRegistrationGUI!  2012 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, 2012.',...
            '',...
            '',...
            '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~        ~          ~',...
            ''};
        h = msgbox(mssg,'ImageRegistrationGUI 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')
        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')
            % registered = imregister(movingInputImage,...
            %      fixedInputImage,transformType,...
            %      optimizer,metric,...
            %      'DisplayOptimization',displayOpt,...
            %      'PyramidLevels',nPyramids);
            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
        fprintf('\nregistered = imregister(%s,%s,''%s'',optimizer,metric,''DisplayOptimization'',%d,''PyramidLevels'',%d);\n',...
            mname,fname,transformType,displayOpt,nPyramids);
        fprintf('%%(For visualization, uncomment the following line):\n%%imshowpair(fixed,registered);\n');
        fprintf('\n**************************\n\n')
        varname = evalin('base','genvarname(''Registered'',who)');
        assignin('base',varname,registered);
        set(CommentsBox,'string',sprintf('Calling syntax written to Command Window; registered image saved as ''%s'' in base workspace!',varname));
    end

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

    function flickerSlower(varargin)
        t = timerfindall('TimerFcn',@flickerResults);
        if ~isempty(t)
            stop(t);
            newFreq = get(t,'Period')*1.2;
            setappdata(ImageRegFig,'FlickerFreq',newFreq);
            set(CommentsBox,'string',sprintf('Setting flicker frequency to %0.3f.',newFreq));
            set(t,'Period',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 [metricVal,registered] = getMetric(parameters, transformType, regType, fid)%, optimizer, metric, nPyramids
        tic;
        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 = parameters(1);
            optimizer.Epsilon = parameters(2);
            optimizer.InitialRadius = parameters(3);
            metric.NumberOfHistogramBins = round(parameters(4))
            nPyramids = round(parameters(5));
        end
        clc;
        % parameters
        registered = imregister(movingInputImage,...
            fixedInputImage,transformType,...
            optimizer,metric,...
            'DisplayOptimization',1,...
            'PyramidLevels',nPyramids);
        %UNDOCUMENTED approach to recovering the METRIC (see Yair Altman's "Undocumented Secrets...", pp 484-5).
        jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance;
        cmdWin = jDesktop.getClient('Command Window');
        jTextArea = cmdWin.getComponent(0).getViewport.getView;
        cwText = char(get(jTextArea,'Text'));
        maxIter = round(get(MultimodalMaxIterationsSlider,'value'));
        target = strfind(cwText,[num2str(maxIter) '      ']);
        target = max(target);
        metricVal = str2double(cwText(target+10:target+25));
        if isnan(metricVal)
            metricVal = -1;
        end
        if strcmp(regType,'Multimodal')
            mult = -1;
        else
            mult = 1;
        end
        %metricVal = mult*str2double(regexp(metricVal, '(0.\d+)', 'match'));
        metricVal = mult*metricVal;
        tIter = toc;
        fprintf(fid,'\t%g\t%g\t%g\t%g\t%g\t\t%g\t\t%g\n',parameters(1),parameters(2),parameters(3),parameters(4),parameters(5),metricVal,tIter);
    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;
        FixedImageObj = imshow(fixedInputImage,[],'parent',FixedImageAxes);
        FixedImageTitle = title('__ FIXED IMAGE __',...
            'color',fgc,'fontsize',12,...
            'Interpreter','none','parent',FixedImageAxes);
        MovingImageObj = imshow(movingInputImage,[],'parent',MovingImageAxes);
        MovingImageTitle = title('__ MOVING IMAGE __',...
            'color',fgc,'fontsize',12,...
            'Interpreter','none','parent',MovingImageAxes);
        registered = movingInputImage;
        visualizeResults;
        %movingInputImage = fullfile(pathname,mname);
        %ImageRegistrationGUI(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 optimizeResults(varargin)
        tic;
        regType = getButtonGroupVal(RegistrationConfigButtonGroup,'tag');
        [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')
%             if matlabpool('size')==0
%                 matlabpool open 4
%             end
            optimizer.GrowthFactor = get(GrowthFactorSlider,'value');
            optimizer.Epsilon = get(EpsilonSlider,'value');
            optimizer.InitialRadius = get(InitialRadiusSlider,'value');
            optimizer.MaximumIterations = round(get(MultimodalMaxIterationsSlider,'value'));
%             optimizer.UseParallel = 'always';
%             optimizer.Vectorized = 'off';
            metric.NumberOfSpatialSamples = round(get(NumSpatialSamplesSlider,'value'));
            metric.NumberOfHistogramBins = round(get(NumHistogramBinsSlider,'value'));
            metric.UseAllPixels = get(UseAllPixels,'value');
        end
        
        requiredPixelsPerDim = 4.^([1:10]-1);
        maxPyramidsLevel = min([...
            find(size(fixedInputImage,1)  < requiredPixelsPerDim,1,'first'),...
            find(size(fixedInputImage,2)  < requiredPixelsPerDim,1,'first'),...
            find(size(movingInputImage,1) < requiredPixelsPerDim,1,'first'),...
            find(size(movingInputImage,2) < requiredPixelsPerDim,1,'first')])-1;
        upperBounds = [10,   1,  0.1,  100,  maxPyramidsLevel];
        lowerBounds = [1.001, 1e-8, 1e-4, 5, 1];
        tolerance = 1e-3;
        generations = 20;
        nPyramids = get(PyramidLevelsValBox,'value');
        
        initialParameters = [...
            optimizer.GrowthFactor,...
            optimizer.Epsilon,...
            optimizer.InitialRadius,...
            metric.NumberOfHistogramBins,...
            min(nPyramids, maxPyramidsLevel)];
        options = gaoptimset('Display','iter',...
            'Generations',generations,...
            'TolFun',tolerance,...
            'MigrationInterval',5,...
            'MigrationFraction',0.8,...
            'MigrationDirection','both',...
            'PlotFcns',@gaplotbestf,...
            'InitialPopulation',initialParameters,...
            'UseParallel','never');%,...
            %'HybridFcn',{@fmincon,optimset('Display','iter','FunValCheck','on','UseParallel','never')});

        transformType = getButtonGroupVal(TransformTypeButtonGroup,'tag');
        fid = fopen('ImRegLog.txt','w+');
        fprintf(fid,'Image Registration Log\n');
        fprintf(fid,'Date: %s\n\n',datestr(now));
        fprintf(fid,'\tGF\t\tEPS\t\tIR\t\tNHB\t\tNPyr\t\t\tMETRIC\t\tTIME\n\n');
        [parameters, metricVal] = ga(@(parameters) getMetric(parameters, transformType, regType, fid),5,[],[],[],[],lowerBounds,upperBounds,[],options);%, optimizer, metric, nPyramids
        %Run again, with a narrowed scope
        generations = 10;
        tolerance = 1e-4;
        upperBounds = parameters*1.1;%[parameters(1)*1.1, parameters(2)  1,  0.1,  100,  maxPyramidsLevel];
        lowerBounds = parameters*0.9;%[parameters(1)*0.9, 1e-8, 1e-4, 5, 1];
        options = gaoptimset('Display','iter',...
            'Generations',generations,...
            'TolFun',tolerance,...
            'MigrationInterval',5,...
            'MigrationFraction',0.8,...
            'MigrationDirection','both',...
            'PlotFcns',@gaplotbestf,...
            'InitialPopulation',parameters,...
            'UseParallel','never');%,...
        [parameters, metricVal] = ga(@(parameters) getMetric(parameters, transformType, regType, fid),5,[],[],[],[],lowerBounds,upperBounds,[],options);%, optimizer, metric, nPyramids

        parameters(4) = round(parameters(4));
        parameters(5) = round(parameters(5));
        tOptim = toc;
        parameters,metricVal
        pause
        set(GrowthFactorSlider,'value',parameters(1));
        set(GrowthFactorEdt,'string',parameters(1));
        set(EpsilonSlider,'value',parameters(2));
        set(EpsilonEdt,'string',parameters(2));
        set(InitialRadiusSlider,'value',parameters(3));
        set(InitialRadiusEdt,'string',parameters(3));
        set(NumHistogramBinsSlider,'value',parameters(4));
        set(NumHistogramBinsEdt,'string',parameters(4));
        set(PyramidLevelsValBox,'value',parameters(5));
        drawnow
        [metricVal,registered] = getMetric(parameters,transformType, regType, fid);%, optimizer, metric, nPyramids
        visualizeResults
        fprintf('\nThis optimization took %g seconds.\n',tOptim);
        fprintf(fid,'\n\nThis optimization took %g seconds.\n',tOptim);
        fclose(fid);
    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;
        registered = imregister(movingInputImage,...
            fixedInputImage,transformType,...
            optimizer,metric,...
            'DisplayOptimization',displayOpt,...
            'PyramidLevels',nPyramids);
        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)
            else
                start(t)
            end
        end
    end

    function visualizeResults(varargin)
        visType = getButtonGroupVal(VisualizationOptsButtonGroup,'tag');
        closetimer;
        axes(ShowAlignmentAxes);
        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);
        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