-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathLFUtilCalLensletCam.m
163 lines (149 loc) · 8.28 KB
/
LFUtilCalLensletCam.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
% LFUtilCalLensletCam - calibrate a lenslet-based light field camera
%
% Usage:
%
% LFUtilCalLensletCam
% LFUtilCalLensletCam( Inputpath )
% LFUtilCalLensletCam( InputPath, CalOptions )
% LFUtilProcessCalibrations( [], CalOptions )
%
% All parameters are optional and take on default values as set in the "Defaults" section at the top
% of the implementation. As such, this can be called as a function or run directly by editing the
% code. When calling as a function, pass an empty array "[]" to omit a parameter.
%
% This function recursively crawls through a folder identifying decoded light field images and
% performing a calibration based on those images. It follows the calibration procedure described in:
%
% D. G. Dansereau, O. Pizarro, and S. B. Williams, "Decoding, calibration and rectification for
% lenslet-based plenoptic cameras," in Computer Vision and Pattern Recognition (CVPR), IEEE
% Conference on. IEEE, Jun 2013.
%
% Minor differences from the paper: camera parameters are automatically initialized, so no prior
% knowledge of the camera's parameters is required; the free intrinsic parameters have been reduced
% by two: H(3:4,5) were previously redundant with the camera's extrinsics, and are now automatically
% centered; and the light field indices [i,j,k,l] are 1-based in this implementation, and not
% 0-based as described in the paper.
%
% The calibration produced by this process is saved in a JSON file, by default named 'CalInfo.json',
% in the top-level folder of the calibration images. The calibration includes a 5x5 homogeneous
% intrinsic matrix EstCamIntrinsicsH, a 5-element vector EstCamDistortionV describing its distortion
% parameters, and the lenslet grid model formed from the white image used to decode the
% checkerboard images. Taken together, these relate light field indices [i,j,k,l] to spatial rays
% [s,t,u,v], and can be utilized to rectify light fields, as demonstrated in LFUtilDecodeLytroFolder
% / LFCalRectifyLF.
%
% The input light fields are ideally of a small checkerboard (order mm per square), taken at close
% range, and over a diverse set of poses to maximize the quality of the calibration. The
% checkerboard light field images should be decoded without rectification, and colour correction is
% not required.
%
% Calibration is described in more detail in LFToolbox.pdf, including links to example datasets and
% a walkthrough of a calibration process.
%
% Inputs -- all are optional, see code below for default values :
%
% InputPath : Path to folder containing decoded checkerboard images -- note the function
% operates recursively, i.e. it will search sub-folders.
%
% CalOptions : struct controlling calibration parameters
% .ExpectedCheckerSize : Number of checkerboard corners, as recognized by the automatic
% corner detector; edge corners are not recognized, so a standard
% 8x8-square chess board yields 7x7 corners
% .ExpectedCheckerSpacing_m : Physical extents of the checkerboard, in meters
% .LensletBorderSize : Number of pixels to skip around the edges of lenslets; a low
% value of 1 or 0 is generally appropriate, as invalid pixels are
% automatically skipped
% .SaveResult : Set to false to perform a "dry run"
% .ShowDisplay : Enables various displays throughout the calibration process
% .ForceRedoCornerFinding : Forces the corner finding procedure to run, overwriting existing
% results
% .ForceRedoInit : Forces the parameter initialization step to run, overwriting
% existing results
% .OptTolX : Determines when the optimization process terminates. When the
% estimted parameter values change by less than this amount, the
% optimization terminates. See the Matlab documentation on lsqnonlin,
% option `TolX' for more information. The default value of 5e-5 is set
% within the LFCalRefine function; a value of 0 means the optimization
% never terminates based on this criterion.
% .OptTolFun : Similar to OptTolX, except this tolerance deals with the error value.
% This corresponds to Matlab's lsqnonlin option `TolFun'. The default
% value of 0 is set within the LFCalRefine function, and means the
% optimization never terminates based on this criterion.
%
% Output takes the form of saved checkerboard info and calibration files.
%
% Example :
%
% LFUtilCalLensletCam('.', ...
% struct('ExpectedCheckerSize', [8,6], 'ExpectedCheckerSpacing_m', 1e-3*[35.1, 35.0]))
%
% Run from within the top-level path of a set of decoded calibration images of an 8x6 checkerboard
% of dimensions 35.1x35.0 mm, will carry out all the stages of a calibration. See the toolbox
% documentation for a more complete example.
%
% User guide: <a href="matlab:which LFToolbox.pdf; open('LFToolbox.pdf')">LFToolbox.pdf</a>
% See also: LFCalFindCheckerCorners, LFCalInit, LFCalRefine, LFUtilDecodeLytroFolder, LFSelectFromDatabase
% Copyright (c) 2013-2020 Donald G. Dansereau
function LFUtilCalLensletCam( InputPath, CalOptions )
%---Tweakables---
InputPath = LFDefaultVal('InputPath', '.');
CalOptions = LFDefaultField( 'CalOptions', 'ExpectedCheckerSize', [19, 19] );
CalOptions = LFDefaultField( 'CalOptions', 'ExpectedCheckerSpacing_m', [3.61, 3.61] * 1e-3 );
CalOptions = LFDefaultField( 'CalOptions', 'LensletBorderSize', 1 );
CalOptions = LFDefaultField( 'CalOptions', 'SaveResult', true );
CalOptions = LFDefaultField( 'CalOptions', 'ForceRedoCornerFinding', false );
CalOptions = LFDefaultField( 'CalOptions', 'ForceRedoInit', false );
CalOptions = LFDefaultField( 'CalOptions', 'ShowDisplay', true );
CalOptions = LFDefaultField( 'CalOptions', 'CalInfoFname', 'CalInfo.json' );
%---Check for previously started calibration---
CalInfoFname = fullfile(InputPath, CalOptions.CalInfoFname);
if( ~CalOptions.ForceRedoInit && exist(CalInfoFname, 'file') )
fprintf('---File %s already exists\n Loading calibration state and options\n', CalInfoFname);
CalOptions = LFStruct2Var( LFReadMetadata(CalInfoFname), 'CalOptions' );
else
CalOptions.Phase = 'Start';
end
RefineComplete = false; % always at least refine once
%---Step through the calibration phases---
while( ~strcmp(CalOptions.Phase, 'Refine') || ~RefineComplete )
switch( CalOptions.Phase )
case 'Start'
%---Find checkerboard corners---
CalOptions.Phase = 'Corners';
CalOptions = LFCalFindCheckerCorners( InputPath, CalOptions );
case 'Corners'
%---Initialize calibration process---
CalOptions.Phase = 'Init';
CalOptions = LFCalInit( InputPath, CalOptions );
if( CalOptions.ShowDisplay )
LFFigure(2);
clf
LFCalDispEstPoses( InputPath, CalOptions, [], [0.7,0.7,0.7] );
end
case 'Init'
%---First step of optimization process will exclude distortion---
CalOptions.Phase = 'NoDistort';
CalOptions = LFCalRefine( InputPath, CalOptions );
if( CalOptions.ShowDisplay )
LFFigure(2);
LFCalDispEstPoses( InputPath, CalOptions, [], [0,0.7,0] );
end
case 'NoDistort'
%---Next step of optimization process adds distortion---
CalOptions.Phase = 'WithDistort';
CalOptions = LFCalRefine( InputPath, CalOptions );
if( CalOptions.ShowDisplay )
LFFigure(2);
LFCalDispEstPoses( InputPath, CalOptions, [], [0,0,1] );
end
otherwise
%---Subsequent calls refine the estimate---
CalOptions.Phase = 'Refine';
CalOptions = LFCalRefine( InputPath, CalOptions );
RefineComplete = true;
if( CalOptions.ShowDisplay )
LFFigure(2);
LFCalDispEstPoses( InputPath, CalOptions, [], [1,0,0] );
end
end
end