
%% Cross-Validation Trials of Lens Distortion Correction Methods (Script)
%
% Runs cross-validation tests on lens distortion methods: proposed (blind),
% standard (inverse-transform), and Alvarez et al.
%
% The lens distortion correction parameters are learnt on a single
% calibration harp image, the correcting capability of the learnt
% parameters is applied to all images in set. 
%


%% Script Setup 

addpath('./common/');

close all;
clc;

rng(0);


%% Find Support Line-Point Files 

testPath  = '../test_environment/';
linePath  = './line_points/';
imgPath   = './images/';
errPath   = './error_analysis/';
coefsPath = './coefs/';
suppFiles = {'mat'};

% Find all supported files within directory
fprintf('\tSearching directory %s...\n', linePath);
[matNames, nMats] = find_supported_files(linePath, suppFiles);
fprintf('\t\tFound %d line-point .mat files\n', nMats);


%% Select Files for Cross-Validation

% Decide whether to manually specify line point .mat files used, or to
%have program automatically segment files into 'camera-model' groups and
%have user choose specific camera model ('single-only-selection')

selectMatNames = select_files(matNames, '^manip_(?<group>[a-zA-Z0-9-]+)');
    

%% Compute Lens Distortion Model Parameters/Coefficients 

fprintf('Computing lens distortion coefficients...\n');

methodPaths = {'../standard_lens_calibration_c/', '../alvarez_image_lens_correction_c/', '../blind_lens_calibration_c/' };
methods = {'std','alvarez','blind'};
models = {'std', 'rad', 'std'};
nMethods = length(methods);

tol = 1e-6;
nMaxIter = 5000;

for m = 1:nMethods,
    
    method = methods{m};    
    
    nMatFiles = length(selectMatNames);
    for i = 1:nMatFiles,
        
        imgName = regexprep(selectMatNames{i}, {'manip_','.mat'}, '');
        saveFileName = sprintf('%s_%s.mat', method, imgName);
        load(fullfile(linePath, selectMatNames{i}), 'pts', 'lineSizeMat', 'scale', 'offset');                
        
        switch(method)                        
            
            case 'std'
                
                cd(methodPaths{m});
                [coefs, corrPts, err] = standard_lens_calibration_c(pts, lineSizeMat, [], tol, nMaxIter);                                
                
            case 'blind'
                
                cd(methodPaths{m});
                [corrPts, coefs, err] = blind_lens_calibration(pts, lineSizeMat, 'maxIter', nMaxIter);
                if any(isnan(err))
                    cd ../test_environment/;
                    warning('CrossValidation:BlindDiverge', '\tProposed (blind) method diverged: %s\n', selectMatNames{i});
                end
                    
            case 'alvarez'
    
                cd(methodPaths{m});
                [coefs, err] = alvarez_image_lens_correction('seqName', imgName, 'dirPath', fullfile(testPath, imgPath), ...
                                                             'pts', pts, 'lineSizeMat', lineSizeMat, 'optimizeCenter', 1);                                                               
                coefs = coefs{1};
                
            otherwise
                error('CrossValidation:InvalidMethod', 'Unknown method specified');
                
        end                
        
        cd ../test_environment/;
        save(fullfile(coefsPath, saveFileName), 'coefs', 'scale', 'offset');
        
    end    
    
end


%% Compute Cross-Validation Error Tables

for m = 1:nMethods,
       
   errTable = nan(1, nMatFiles);  
       
   for c = 1:nMatFiles,
       
       method = methods{m};
       loadFileName = sprintf('%s_%s', method, regexprep(selectMatNames{c}, 'manip_', ''));
       load(fullfile(coefsPath, loadFileName), 'coefs', 'scale', 'offset'); 
       
       coefsScale = scale;
       coefsOffset = offset;
              
       for p = 1:nMatFiles,                                        
           
           load(fullfile(linePath, selectMatNames{p}), 'pts', 'lineSizeMat', 'scale', 'offset'); 
           
           if ~isequal(scale, coefsScale)
               error('CrossValidation:IncompatibleNorm', 'Line points were normalized differently then coefficient-learning');
           end
               
           if ~isequal(offset, coefsOffset)
               nPts = size(pts, 1);
               pts(:,1) = pts(:,1) - (coefsOffset(1) - offset(1))*ones(nPts, 1);
               pts(:,2) = pts(:,2) - (coefsOffset(2) - offset(2))*ones(nPts, 1);    
           end
           
           [err, res] = plumb_line_cost_function(pts, lineSizeMat, coefs, 'methodType', method, 'modelType', models{m});
           errTable(p) = err/sqrt(length(res));
           
       end
       
       saveErrFileName = sprintf('rmse_%s_%s', method, regexprep(selectMatNames{c}, 'manip_', ''));
       save(fullfile(errPath, saveErrFileName), 'errTable');
       
   end      
    
end






















