FDPDEInpainter

PURPOSE ^

SYNOPSIS ^

This is a script file.

DESCRIPTION ^

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 classdef (Abstract) FDPDEInpainter
0002     %FDPDEINPAINTER Finite-Differences Partial Differential Equation (FDPDE) Inpainter
0003     %   Common interphase for PDE-based inpainting methods. Solves the
0004     %   problem using finite differences
0005     
0006     properties
0007         relChangeTolerance = 1e-8; % Relative tolerance, stop the gradient descent when the energy descent between iterations is less than this value
0008         maxIters = 100000; % Maximum number of gradient descent iterations to perform
0009         dt = 1e-2; % Gradient descent step size
0010         relax = 1; % Over-relaxation parameter
0011         hx = 1; % Grid step size in X
0012         hy = 1; % Grid step size in Y
0013         % Debug options
0014         debugShowStep = false;
0015         debugCreateVideo = false;
0016         debugVideoFile = '';
0017         debugItersPerFrame = 1000; % Show (or record) a frame every this number of iterations
0018     end
0019     
0020     methods
0021         function obj = FDPDEInpainter(varargin)
0022             %FDPDEINPAINTER Construct an instance of this class
0023             
0024             p = inputParser;
0025             p.KeepUnmatched=true; % WARNING: This results in the name of the parameters not being checked exactly!
0026             validGTZero = @(x) isscalar(x) && x >= 0;
0027             validGTZeroInt = @(x) isscalar(x) && x >= 0 && floor(x) == x;
0028             validScalarLogical = @(x) isscalar(x) && islogical(x);
0029             validRelaxation = @(x) isscalar(x) && x >= 1 && x <= 2;
0030             addParameter(p, 'UpdateStepSize', 1e-2, validGTZero); 
0031             addParameter(p, 'RelChangeTolerance', 1e-8, validGTZero);            
0032             addParameter(p, 'MaxIters', 1e8, validGTZeroInt);
0033             addParameter(p, 'Relaxation', 1, validRelaxation);
0034             addParameter(p, 'DebugShowStep', false, validScalarLogical);
0035             addParameter(p, 'DebugVideoFile', '', @ischar);
0036             addParameter(p, 'DebugItersPerFrame', 1000, validGTZeroInt);
0037             addParameter(p, 'GridStepX', 1, @isscalar);
0038             addParameter(p, 'GridStepY', 1, @isscalar);
0039             parse(p, varargin{:});
0040             
0041             obj.relChangeTolerance = p.Results.RelChangeTolerance;              
0042             obj.maxIters = p.Results.MaxIters;  
0043             obj.dt = p.Results.UpdateStepSize;                        
0044             obj.hx = p.Results.GridStepX;
0045             obj.hy = p.Results.GridStepY;
0046             
0047             obj.debugShowStep = p.Results.DebugShowStep;
0048             obj.debugItersPerFrame = p.Results.DebugItersPerFrame;
0049             if ~isempty(p.Results.DebugVideoFile)
0050                 obj.debugVideoFile = p.Results.DebugVideoFile;
0051                 obj.debugCreateVideo = true;
0052             end            
0053         end
0054         
0055         function inpaitedImage = inpaint(obj, image, mask)
0056             %INPAINT Inpainting of an "image" by iterative minimization of
0057             %   a PDE functional
0058             %
0059             % Input:
0060             %   img: input image to be inpainted
0061             %   mask: logical mask of the same size as the input image. 1 == known pixels, 0 == unknown pixels to be
0062             %         inpainted
0063             % Output:
0064             %   f: inpainted image
0065             
0066             % Get the number of channels in the image
0067             [sy, sx, channels] = size(image);
0068             if size(mask, 1) ~= sy || size(mask, 2) ~= sx
0069                 error('The mask must have the first two dimensions equal to those of the image');
0070             end
0071             
0072             inpaitedImage = zeros(size(image));
0073             
0074             % Initialize the debug video?
0075             if obj.debugCreateVideo
0076                 % Create the output video
0077                video = VideoWriter(obj.debugOutputVideoFile, 'Motion JPEG AVI');
0078                video.Quality = 100;
0079                open(video);               
0080             end
0081             
0082             % Perform inpainting on each channel
0083             for c = 1:channels                     
0084                 % Slice the current channel
0085                 f = image(:, :, c);
0086                 Pi = @(f)f.*(1-mask) + image(:, :, c).*mask;
0087                 
0088 %                 % Perform pre-processing?
0089 %                 [img, mask, obj] = preProcess(obj, img, mask);
0090                 
0091                 % Gradient descent
0092                 for i=1:obj.maxIters
0093                     % Perform a step in the optimization
0094                     fnew = Pi(f - obj.dt*obj.stepFun(f)); % Minus because we assume stepFun to return the gradient, and we want to move against the gradient. Take it into account when defining a stepFun!
0095 
0096                     % Over-relaxation?
0097                     if obj.relax > 1
0098                         fnew = Pi(f*(1-obj.relax) + fnew*obj.relax);
0099                     end                    
0100                     
0101                     % Compute the difference with the previous step
0102                     diff = norm(fnew(:)-f(:))/norm(fnew(:));
0103 
0104                     % Update the function
0105                     f = fnew;
0106 
0107                     % Debug output (if required)
0108                     if (obj.debugShowStep || obj.debugCreateVideo) && mod(i-1, obj.debugItersPerFrame) == 0
0109                         imagesc(f'); axis xy; colorbar;
0110                         if obj.createDemoVideo
0111                             frame = getframe(gcf);        
0112                             writeVideo(video, frame);
0113                         end
0114                     end
0115 
0116                     % Stop if "almost" no change
0117                     if diff < obj.relChangeTolerance
0118                         break;
0119                     end
0120                 end
0121 
0122                 % Issue a warning if the maximum number of iterations has been
0123                 % reached (normally means that the solution will not be
0124                 % useful because it did not converge...)
0125                 if i == obj.maxIters
0126                     warning('Maximum number of iterations reached');
0127                 end
0128                 
0129                 inpaitedImage(:, :, c) = f;
0130             end
0131             
0132             % Close the debug video?
0133             if obj.debugCreateVideo, close(video); end
0134         end
0135                 
0136         function varargin = removeParentParametersFromVarargin(obj, varargin)
0137             paramsToDelete = {'UpdateStepSize', 'RelChangeTolerance', 'MaxIters', 'Relaxation', 'DebugShowStep', 'DebugVideoFile', 'DebugItersPerFrame', 'GridStepX', 'GridStepY'};
0138             varargin = deleteParamsFromVarargin(paramsToDelete, varargin);
0139         end
0140     end
0141     
0142     % The methods that need to be implemented by subclasses
0143     methods (Abstract) 
0144         f = stepFun(obj, f, mask);
0145     end
0146     
0147     % Optional methods that can be redefined, if some method needs them
0148     methods (Access = protected)
0149         function preProcess(obj, img, mask)
0150             % Pre-processing to be executed prior to the gradient descent
0151         end
0152         function stepRegularization(obj, img, mask)
0153              % Regularization to be executed after a gradient descent step
0154         end
0155         function postProcessing(obj, img, mask)
0156             % Post-processing to be executed after the gradient descent
0157         end
0158    end
0159 end
0160

Generated on Thu 10-Dec-2020 17:34:27 by m2html © 2005