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