├── LFToolbox0.4 ├── LFBuild2DFreqFan.m ├── LFBuild2DFreqLine.m ├── LFBuild4DFreqDualFan.m ├── LFBuild4DFreqHypercone.m ├── LFBuild4DFreqHyperfan.m ├── LFBuild4DFreqPlane.m ├── LFCalDispEstPoses.m ├── LFCalDispRectIntrinsics.m ├── LFCalRectifyLF.m ├── LFColourCorrect.m ├── LFDemoBasicFiltGantry.m ├── LFDemoBasicFiltIllum.m ├── LFDemoBasicFiltLytroF01.m ├── LFDisp.m ├── LFDispMousePan.m ├── LFDispVidCirc.m ├── LFFigure.m ├── LFFilt2DFFT.m ├── LFFilt4DFFT.m ├── LFFiltShiftSum.m ├── LFFindFilesRecursive.m ├── LFHistEqualize.m ├── LFLytroDecodeImage.m ├── LFMatlabPathSetup.m ├── LFReadGantryArray.m ├── LFReadLFP.m ├── LFReadMetadata.m ├── LFReadRaw.m ├── LFRecenterIntrinsics.m ├── LFToolbox.pdf ├── LFUtilCalLensletCam.m ├── LFUtilDecodeLytroFolder.m ├── LFUtilExtractLFPThumbs.m ├── LFUtilProcessCalibrations.m ├── LFUtilProcessWhiteImages.m ├── LFUtilUnpackLytroArchive.m ├── LFWriteMetadata.m ├── README └── SupportFunctions │ ├── CameraCal │ ├── compute_extrinsic_init.m │ ├── compute_extrinsic_refine.m │ ├── compute_homography.m │ ├── normalize_pixel.m │ ├── project_points2.m │ ├── rigid_motion.m │ ├── rodrigues.m │ └── source.txt │ ├── LFBuildLensletGridModel.m │ ├── LFCalFindCheckerCorners.m │ ├── LFCalInit.m │ ├── LFCalRefine.m │ ├── LFConvertToFloat.m │ ├── LFDecodeLensletImageSimple.m │ ├── LFDefaultField.m │ ├── LFDefaultIntrinsics.m │ ├── LFDefaultVal.m │ ├── LFDispSetup.m │ ├── LFFindCalInfo.m │ ├── LFFindLytroPartnerFile.m │ ├── LFGatherCamInfo.m │ ├── LFHelperBuild2DFreq.m │ ├── LFHelperBuild4DFreq.m │ ├── LFMapRectifiedToMeasured.m │ ├── LFNormalizedFreqAxis.m │ ├── LFRotz.m │ ├── LFSelectFromDatabase.m │ ├── LFSign.m │ ├── LFStruct2Var.m │ ├── LFToolboxVersion.m │ ├── LFUnpackRawBuffer.m │ └── LFVar2Struct.m ├── README.md └── license.txt /LFToolbox0.4/LFBuild2DFreqFan.m: -------------------------------------------------------------------------------- 1 | % LFBuild2DFreqFan - construct a 2D fan passband filter in the frequency domain 2 | % 3 | % Usage: 4 | % 5 | % [H, FiltOptions] = LFBuild2DFreqFan( LFSize, Slope1, Slope2, BW, FiltOptions ) 6 | % H = LFBuild2DFreqFan( LFSize, Slope, BW ) 7 | % 8 | % This file constructs a real-valued magnitude response in 2D, for which the passband is a fan. 9 | % 10 | % Once constructed the filter must be applied to a light field, e.g. using LFFilt2DFFT. The 11 | % LFDemoBasicFilt* files demonstrate how to contruct and apply frequency-domain filters. 12 | % 13 | % A more technical discussion, including the use of filters for denoising and volumetric focus, and 14 | % the inclusion of aliases components, is included in: 15 | % 16 | % [2] D.G. Dansereau, O. Pizarro, and S. B. Williams, "Linear Volumetric Focus for Light Field 17 | % Cameras," to appear in ACM Transactions on Graphics (TOG), vol. 34, no. 2, 2015. 18 | % 19 | % Inputs: 20 | % 21 | % LFSize : Size of the frequency-domain filter. This should match or exceed the size of the 22 | % light field to be filtered. If it's larger than the input light field, the input is 23 | % zero-padded to match the filter's size by LFFilt2DFFT. 24 | % 25 | % Slope1, Slope2 : Slopes at the extents of the fan passband. 26 | % 27 | % BW : 3-db Bandwidth of the planar passband. 28 | % 29 | % [optional] FiltOptions : struct controlling filter construction 30 | % SlopeMethod : only 'Skew' is supported for now 31 | % Precision : 'single' or 'double', default 'single' 32 | % Rolloff : 'Gaussian' or 'Butter', default 'Gaussian' 33 | % Order : controls the order of the filter when Rolloff is 'Butter', default 3 34 | % Aspect2D : aspect ratio of the light field, default [1 1] 35 | % Window : Default false. By default the edges of the passband are sharp; this adds 36 | % a smooth rolloff at the edges when used in conjunction with Extent2D or 37 | % IncludeAliased. 38 | % Extent2D : controls where the edge of the passband occurs, the default [1 1] 39 | % is the edge of the Nyquist box. When less than 1, enabling windowing 40 | % introduces a rolloff after the edge of the passband. Can be greater 41 | % than 1 when using IncludeAliased. 42 | % IncludeAliased : default false; allows the passband to wrap around off the edge of the 43 | % Nyquist box; used in conjunction with Window and/or Extent2D. This can 44 | % increase processing time dramatically, e.g. Extent2D = [2,2] 45 | % requires a 2^2 = 4-fold increase in time to construct the filter. 46 | % Useful when passband content is aliased, see [2]. 47 | % 48 | % Outputs: 49 | % 50 | % H : real-valued frequency magnitude response 51 | % FiltOptions : The filter options including defaults, with an added PassbandInfo field 52 | % detailing the function and time of construction of the filter 53 | % 54 | % See also: LFDemoBasicFiltGantry, LFDemoBasicFiltIllum, LFDemoBasicFiltLytroF01, LFBuild2DFreqFan, LFBuild2DFreqLine, 55 | % LFBuild4DFreqDualFan, LFBuild4DFreqHypercone, LFBuild4DFreqHyperfan, LFBuild4DFreqPlane, LFFilt2DFFT, LFFilt4DFFT, 56 | % LFFiltShiftSum 57 | 58 | % Part of LF Toolbox v0.4 released 12-Feb-2015 59 | % Copyright (c) 2013-2015 Donald G. Dansereau 60 | 61 | function [H, FiltOptions] = LFBuild2DFreqFan( LFSize, Slope1, Slope2, BW, FiltOptions ) 62 | 63 | FiltOptions = LFDefaultField('FiltOptions', 'SlopeMethod', 'Skew'); % 'Skew' only for now 64 | 65 | DistFunc = @(P, FiltOptions) DistFunc_2DFan( P, Slope1, Slope2, FiltOptions ); 66 | [H, FiltOptions] = LFHelperBuild2DFreq( LFSize, BW, FiltOptions, DistFunc ); 67 | 68 | TimeStamp = datestr(now,'ddmmmyyyy_HHMMSS'); 69 | FiltOptions.PassbandInfo = struct('mfilename', mfilename, 'time', TimeStamp, 'VersionStr', LFToolboxVersion); 70 | 71 | end 72 | 73 | %----------------------------------------------------------------------------------------------------------------------- 74 | function Dist = DistFunc_2DFan( P, Slope1, Slope2, FiltOptions ) 75 | switch( lower(FiltOptions.SlopeMethod) ) 76 | case 'skew' 77 | if( Slope2 < Slope1 ) 78 | t = Slope1; 79 | Slope1 = Slope2; 80 | Slope2 = t; 81 | end 82 | R1 = eye(2); 83 | R2 = R1; 84 | R1(1,2) = Slope1; 85 | R2(1,2) = Slope2; 86 | 87 | otherwise 88 | error('Unrecognized slope method'); 89 | end 90 | P1 = R1 * P; 91 | P2 = R2 * P; 92 | TransitionPt = LFSign(P1(2,:)); 93 | 94 | CurDist1 = max(0, TransitionPt .* P1(1,:)); 95 | CurDist2 = max(0,-TransitionPt .* P2(1,:)); 96 | 97 | Dist = max(CurDist1, CurDist2).^2; 98 | end 99 | 100 | 101 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFBuild2DFreqLine.m: -------------------------------------------------------------------------------- 1 | % LFBuild2DFreqLine - construct a 2D line passband filter in the frequency domain 2 | % 3 | % Usage: 4 | % 5 | % [H, FiltOptions] = LFBuild2DFreqLine( LFSize, Slope, BW, FiltOptions ) 6 | % H = LFBuild2DFreqLine( LFSize, Slope, BW ) 7 | % 8 | % This file constructs a real-valued magnitude response in 2D, for which the passband is a line. The cascade of two line 9 | % filters, applied in s,u and in t,v, is identical to a 4D planar filter, e.g. that constructed by LFBuild4DFreqPlane. 10 | % 11 | % Once constructed the filter must be applied to a light field, e.g. using LFFilt2DFFT. The 12 | % LFDemoBasicFilt* files demonstrate how to contruct and apply frequency-domain filters. 13 | % 14 | % A more technical discussion, including the use of filters for denoising and volumetric focus, and 15 | % the inclusion of aliases components, is included in: 16 | % 17 | % [2] D.G. Dansereau, O. Pizarro, and S. B. Williams, "Linear Volumetric Focus for Light Field 18 | % Cameras," to appear in ACM Transactions on Graphics (TOG), vol. 34, no. 2, 2015. 19 | % 20 | % Inputs: 21 | % 22 | % LFSize : Size of the frequency-domain filter. This should match or exceed the size of the 23 | % light field to be filtered. If it's larger than the input light field, the input is 24 | % zero-padded to match the filter's size by LFFilt2DFFT. 25 | % 26 | % Slope : Slopes at the extents of the fan passband. 27 | % 28 | % BW : 3-db Bandwidth of the planar passband. 29 | % 30 | % [optional] FiltOptions : struct controlling filter construction 31 | % SlopeMethod : only 'Skew' is supported for now 32 | % Precision : 'single' or 'double', default 'single' 33 | % Rolloff : 'Gaussian' or 'Butter', default 'Gaussian' 34 | % Order : controls the order of the filter when Rolloff is 'Butter', default 3 35 | % Aspect2D : aspect ratio of the light field, default [1 1] 36 | % Window : Default false. By default the edges of the passband are sharp; this adds 37 | % a smooth rolloff at the edges when used in conjunction with Extent2D or 38 | % IncludeAliased. 39 | % Extent2D : controls where the edge of the passband occurs, the default [1 1] 40 | % is the edge of the Nyquist box. When less than 1, enabling windowing 41 | % introduces a rolloff after the edge of the passband. Can be greater 42 | % than 1 when using IncludeAliased. 43 | % IncludeAliased : default false; allows the passband to wrap around off the edge of the 44 | % Nyquist box; used in conjunction with Window and/or Extent2D. This can 45 | % increase processing time dramatically, e.g. Extent2D = [2,2] 46 | % requires a 2^2 = 4-fold increase in time to construct the filter. 47 | % Useful when passband content is aliased, see [2]. 48 | % 49 | % Outputs: 50 | % 51 | % H : real-valued frequency magnitude response 52 | % FiltOptions : The filter options including defaults, with an added PassbandInfo field 53 | % detailing the function and time of construction of the filter 54 | % 55 | % See also: LFDemoBasicFiltGantry, LFDemoBasicFiltIllum, LFDemoBasicFiltLytroF01, 56 | % LFBuild2DFreqFan, LFBuild2DFreqLine, LFBuild4DFreqDualFan, LFBuild4DFreqHypercone, 57 | % LFBuild4DFreqHyperfan, LFBuild4DFreqPlane, LFFilt2DFFT, LFFilt4DFFT, LFFiltShiftSum 58 | 59 | % Part of LF Toolbox v0.4 released 12-Feb-2015 60 | % Copyright (c) 2013-2015 Donald G. Dansereau 61 | 62 | function [H, FiltOptions] = LFBuild2DFreqLine( LFSize, Slope, BW, FiltOptions ) 63 | 64 | FiltOptions = LFDefaultField('FiltOptions', 'SlopeMethod', 'Skew'); % 'Skew', 'Rotate' 65 | 66 | DistFunc = @(P, FiltOptions) DistFunc_2DLine( P, Slope, FiltOptions ); 67 | [H, FiltOptions] = LFHelperBuild2DFreq( LFSize, BW, FiltOptions, DistFunc ); 68 | 69 | TimeStamp = datestr(now,'ddmmmyyyy_HHMMSS'); 70 | FiltOptions.PassbandInfo = struct('mfilename', mfilename, 'time', TimeStamp, 'VersionStr', LFToolboxVersion); 71 | 72 | end 73 | 74 | %----------------------------------------------------------------------------------------------------------------------- 75 | function Dist = DistFunc_2DLine( P, Slope, FiltOptions ) 76 | switch( lower(FiltOptions.SlopeMethod) ) 77 | case 'skew' 78 | R = eye(2); 79 | R(1,2) = Slope; 80 | 81 | case 'rotate' 82 | Angle = -atan2(Slope,1); 83 | R = LFRotz( Angle ); 84 | R = R(1:2,1:2); 85 | 86 | otherwise 87 | error('Unrecognized slope method'); 88 | end 89 | P = R * P; 90 | Dist = P(1,:).^2; 91 | end 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFBuild4DFreqDualFan.m: -------------------------------------------------------------------------------- 1 | % LFBuild4DFreqDualFan - construct a 4D dual-fan passband filter in the frequency domain 2 | % 3 | % Usage: 4 | % 5 | % [H, FiltOptions] = LFBuild4DFreqDualFan( LFSize, Slope, BW, FiltOptions ) 6 | % H = LFBuild4DFreqDualFan( LFSize, Slope, BW ) 7 | % 8 | % This file constructs a real-valued magnitude response in 4D, for which the passband is a dual-fan, 9 | % the intersection of 2 2D fans. 10 | % 11 | % Once constructed the filter must be applied to a light field, e.g. using LFFilt4DFFT. The 12 | % LFDemoBasicFilt* files demonstrate how to contruct and apply frequency-domain filters. 13 | % 14 | % A more technical discussion, including the use of filters for denoising and volumetric focus, and 15 | % the inclusion of aliases components, is included in: 16 | % 17 | % [2] D.G. Dansereau, O. Pizarro, and S. B. Williams, "Linear Volumetric Focus for Light Field 18 | % Cameras," to appear in ACM Transactions on Graphics (TOG), vol. 34, no. 2, 2015. 19 | % 20 | % Inputs: 21 | % 22 | % LFSize : Size of the frequency-domain filter. This should match or exceed the size of the 23 | % light field to be filtered. If it's larger than the input light field, the input is 24 | % zero-padded to match the filter's size by LFFilt4DFFT. 25 | % 26 | % Slope : The slope of the planar passband. If different slopes are desired in s,t and u,v, 27 | % the optional aspect parameter should be used. 28 | % 29 | % BW : 3-db Bandwidth of the planar passband. 30 | % 31 | % [optional] FiltOptions : struct controlling filter construction 32 | % SlopeMethod : 'Skew' or 'Rotate' default 'skew' 33 | % Precision : 'single' or 'double', default 'single' 34 | % Rolloff : 'Gaussian' or 'Butter', default 'Gaussian' 35 | % Order : controls the order of the filter when Rolloff is 'Butter', default 3 36 | % Aspect4D : aspect ratio of the light field, default [1 1 1 1] 37 | % Window : Default false. By default the edges of the passband are sharp; this adds 38 | % a smooth rolloff at the edges when used in conjunction with Extent4D or 39 | % IncludeAliased. 40 | % Extent4D : controls where the edge of the passband occurs, the default [1 1 1 1] 41 | % is the edge of the Nyquist box. When less than 1, enabling windowing 42 | % introduces a rolloff after the edge of the passband. Can be greater 43 | % than 1 when using IncludeAliased. 44 | % IncludeAliased : default false; allows the passband to wrap around off the edge of the 45 | % Nyquist box; used in conjunction with Window and/or Extent4D. This can 46 | % increase processing time dramatically, e.g. Extent4D = [2,2,2,2] 47 | % requires a 2^4 = 16-fold increase in time to construct the filter. 48 | % Useful when passband content is aliased, see [2]. 49 | % 50 | % Outputs: 51 | % 52 | % H : real-valued frequency magnitude response 53 | % FiltOptions : The filter options including defaults, with an added PassbandInfo field 54 | % detailing the function and time of construction of the filter 55 | % 56 | % See also: LFDemoBasicFiltGantry, LFDemoBasicFiltIllum, LFDemoBasicFiltLytroF01, 57 | % LFBuild2DFreqFan, LFBuild2DFreqLine, LFBuild4DFreqDualFan, LFBuild4DFreqHypercone, 58 | % LFBuild4DFreqHyperfan, LFBuild4DFreqPlane, LFFilt2DFFT, LFFilt4DFFT, LFFiltShiftSum 59 | 60 | % Part of LF Toolbox v0.4 released 12-Feb-2015 61 | % Copyright (c) 2013-2015 Donald G. Dansereau 62 | 63 | function [H, FiltOptions] = LFBuild4DFreqDualFan( LFSize, Slope1, Slope2, BW, FiltOptions ) 64 | 65 | FiltOptions = LFDefaultField('FiltOptions', 'Aspect4D', 1); 66 | FiltOptions = LFDefaultField('FiltOptions', 'Extent4D', 1); 67 | 68 | if( length(LFSize) == 1 ) 69 | LFSize = LFSize .* [1,1,1,1]; 70 | end 71 | if( length(FiltOptions.Extent4D) == 1 ) 72 | FiltOptions.Extent4D = FiltOptions.Extent4D .* [1,1,1,1]; 73 | end 74 | if( length(FiltOptions.Aspect4D) == 1 ) 75 | FiltOptions.Aspect4D = FiltOptions.Aspect4D .* [1,1,1,1]; 76 | end 77 | 78 | FiltOptionsSU = FiltOptions; 79 | FiltOptionsSU.Aspect2D = FiltOptionsSU.Aspect4D([2,4]); 80 | FiltOptionsSU.Extent2D = FiltOptionsSU.Extent4D([2,4]); 81 | Hsu = LFBuild2DFreqFan( LFSize([2,4]), Slope1, Slope2, BW, FiltOptionsSU ); 82 | 83 | FiltOptionsTV = FiltOptions; 84 | FiltOptionsTV.Aspect2D = FiltOptionsSU.Aspect4D([1,3]); 85 | FiltOptionsTV.Extent2D = FiltOptionsSU.Extent4D([1,3]); 86 | [Htv, FiltOptionsTV] = LFBuild2DFreqFan( LFSize([1,3]), Slope1, Slope2, BW, FiltOptionsTV ); 87 | 88 | FiltOptions = FiltOptionsTV; 89 | FiltOptions = rmfield(FiltOptions, 'Aspect2D'); 90 | FiltOptions = rmfield(FiltOptions, 'Extent2D'); 91 | 92 | Hsu = reshape(Hsu, [1, size(Hsu,1), 1, size(Hsu,2)]); 93 | Hsu = repmat(Hsu, [LFSize(1),1,LFSize(3),1]); 94 | 95 | Htv = reshape(Htv, [size(Htv,1), 1, size(Htv,2), 1]); 96 | Htv = repmat(Htv, [1,LFSize(2),1,LFSize(4)]); 97 | 98 | H = Hsu .* Htv; 99 | 100 | TimeStamp = datestr(now,'ddmmmyyyy_HHMMSS'); 101 | FiltOptions.PassbandInfo = struct('mfilename', mfilename, 'time', TimeStamp, 'VersionStr', LFToolboxVersion); -------------------------------------------------------------------------------- /LFToolbox0.4/LFBuild4DFreqHypercone.m: -------------------------------------------------------------------------------- 1 | % LFBuild4DFreqHypercone - construct a 4D hypercone passband filter in the frequency domain 2 | % 3 | % Usage: 4 | % 5 | % [H, FiltOptions] = LFBuild4DFreqHypercone( LFSize, Slope, BW, FiltOptions ) 6 | % H = LFBuild4DFreqHypercone( LFSize, Slope, BW ) 7 | % 8 | % This file constructs a real-valued magnitude response in 4D, for which the passband is a hypercone. 9 | % 10 | % Once constructed the filter must be applied to a light field, e.g. using LFFilt4DFFT. The 11 | % LFDemoBasicFilt* files demonstrate how to contruct and apply frequency-domain filters. 12 | % 13 | % A more technical discussion, including the use of filters for denoising and volumetric focus, and 14 | % the inclusion of aliases components, is included in: 15 | % 16 | % [2] D.G. Dansereau, O. Pizarro, and S. B. Williams, "Linear Volumetric Focus for Light Field 17 | % Cameras," to appear in ACM Transactions on Graphics (TOG), vol. 34, no. 2, 2015. 18 | % 19 | % Inputs: 20 | % 21 | % LFSize : Size of the frequency-domain filter. This should match or exceed the size of the 22 | % light field to be filtered. If it's larger than the input light field, the input is 23 | % zero-padded to match the filter's size by LFFilt4DFFT. 24 | % 25 | % Slope : The slope of the planar passband. If different slopes are desired in s,t and u,v, 26 | % the optional aspect parameter should be used. 27 | % 28 | % BW : 3-db Bandwidth of the planar passband. 29 | % 30 | % [optional] FiltOptions : struct controlling filter construction 31 | % SlopeMethod : 'Skew' or 'Rotate' default 'skew' 32 | % Precision : 'single' or 'double', default 'single' 33 | % Rolloff : 'Gaussian' or 'Butter', default 'Gaussian' 34 | % Order : controls the order of the filter when Rolloff is 'Butter', default 3 35 | % Aspect4D : aspect ratio of the light field, default [1 1 1 1] 36 | % Window : Default false. By default the edges of the passband are sharp; this adds 37 | % a smooth rolloff at the edges when used in conjunction with Extent4D or 38 | % IncludeAliased. 39 | % Extent4D : controls where the edge of the passband occurs, the default [1 1 1 1] 40 | % is the edge of the Nyquist box. When less than 1, enabling windowing 41 | % introduces a rolloff after the edge of the passband. Can be greater 42 | % than 1 when using IncludeAliased. 43 | % IncludeAliased : default false; allows the passband to wrap around off the edge of the 44 | % Nyquist box; used in conjunction with Window and/or Extent4D. This can 45 | % increase processing time dramatically, e.g. Extent4D = [2,2,2,2] 46 | % requires a 2^4 = 16-fold increase in time to construct the filter. 47 | % Useful when passband content is aliased, see [2]. 48 | % 49 | % Outputs: 50 | % 51 | % H : real-valued frequency magnitude response 52 | % FiltOptions : The filter options including defaults, with an added PassbandInfo field 53 | % detailing the function and time of construction of the filter 54 | % 55 | % See also: LFDemoBasicFiltGantry, LFDemoBasicFiltIllum, LFDemoBasicFiltLytroF01, 56 | % LFBuild2DFreqFan, LFBuild2DFreqLine, LFBuild4DFreqDualFan, LFBuild4DFreqHypercone, 57 | % LFBuild4DFreqHyperfan, LFBuild4DFreqPlane, LFFilt2DFFT, LFFilt4DFFT, LFFiltShiftSum 58 | 59 | % Part of LF Toolbox v0.4 released 12-Feb-2015 60 | % Copyright (c) 2013-2015 Donald G. Dansereau 61 | 62 | function [H, FiltOptions] = LFBuild4DFreqHypercone( LFSize, BW, FiltOptions ) 63 | 64 | FiltOptions = LFDefaultField('FiltOptions', 'HyperconeMethod', 'Rotated'); % 'Direct', 'Rotated' 65 | 66 | DistFunc = @(P, FiltOptions) DistFunc_4DCone( P, FiltOptions ); 67 | [H, FiltOptions] = LFHelperBuild4DFreq( LFSize, BW, FiltOptions, DistFunc ); 68 | 69 | TimeStamp = datestr(now,'ddmmmyyyy_HHMMSS'); 70 | FiltOptions.PassbandInfo = struct('mfilename', mfilename, 'time', TimeStamp, 'VersionStr', LFToolboxVersion); 71 | 72 | end 73 | 74 | %----------------------------------------------------------------------------------------------------------------------- 75 | function Dist = DistFunc_4DCone( P, FiltOptions ) 76 | switch( lower(FiltOptions.HyperconeMethod )) 77 | case 'direct' 78 | Dist = (P(1,:).*P(4,:) - P(2,:).*P(3,:)).^2 * 4; 79 | 80 | case 'rotated' 81 | R = 1/sqrt(2) .* [1,0,0,1; 0,1,1,0; 0,1,-1,0; 1,0,0,-1]; 82 | P=R*P; 83 | Dist = (sqrt(P(1,:).^2 + P(3,:).^2) - sqrt(P(2,:).^2 + P(4,:).^2)).^2 /2; 84 | 85 | otherwise 86 | error('Unrecognized hypercone construction method'); 87 | end 88 | end 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFBuild4DFreqHyperfan.m: -------------------------------------------------------------------------------- 1 | % LFBuild4DFreqHyperfan - construct a 4D hyperfan passband filter in the frequency domain 2 | % 3 | % Usage: 4 | % 5 | % [H, FiltOptions] = LFBuild4DFreqHyperfan( LFSize, Slope, BW, FiltOptions ) 6 | % H = LFBuild4DFreqHyperfan( LFSize, Slope, BW ) 7 | % 8 | % This file constructs a real-valued magnitude response in 4D, for which the passband is a hyperfan. 9 | % This is useful for selecting objects over a range of depths from a lightfield, i.e. volumetric 10 | % focus. 11 | % 12 | % Once constructed the filter must be applied to a light field, e.g. using LFFilt4DFFT. The 13 | % LFDemoBasicFilt* files demonstrate how to contruct and apply frequency-domain filters. 14 | % 15 | % A more technical discussion, including the use of filters for denoising and volumetric focus, and 16 | % the inclusion of aliases components, is included in: 17 | % 18 | % [2] D.G. Dansereau, O. Pizarro, and S. B. Williams, "Linear Volumetric Focus for Light Field 19 | % Cameras," to appear in ACM Transactions on Graphics (TOG), vol. 34, no. 2, 2015. 20 | % 21 | % Inputs: 22 | % 23 | % LFSize : Size of the frequency-domain filter. This should match or exceed the size of the 24 | % light field to be filtered. If it's larger than the input light field, the input is 25 | % zero-padded to match the filter's size by LFFilt4DFFT. 26 | % 27 | % Slope : The slope of the planar passband. If different slopes are desired in s,t and u,v, 28 | % the optional aspect parameter should be used. 29 | % 30 | % BW : 3-db Bandwidth of the planar passband. 31 | % 32 | % [optional] FiltOptions : struct controlling filter construction 33 | % SlopeMethod : 'Skew' or 'Rotate' default 'skew' 34 | % Precision : 'single' or 'double', default 'single' 35 | % Rolloff : 'Gaussian' or 'Butter', default 'Gaussian' 36 | % Order : controls the order of the filter when Rolloff is 'Butter', default 3 37 | % Aspect4D : aspect ratio of the light field, default [1 1 1 1] 38 | % Window : Default false. By default the edges of the passband are sharp; this adds 39 | % a smooth rolloff at the edges when used in conjunction with Extent4D or 40 | % IncludeAliased. 41 | % Extent4D : controls where the edge of the passband occurs, the default [1 1 1 1] 42 | % is the edge of the Nyquist box. When less than 1, enabling windowing 43 | % introduces a rolloff after the edge of the passband. Can be greater 44 | % than 1 when using IncludeAliased. 45 | % IncludeAliased : default false; allows the passband to wrap around off the edge of the 46 | % Nyquist box; used in conjunction with Window and/or Extent4D. This can 47 | % increase processing time dramatically, e.g. Extent4D = [2,2,2,2] 48 | % requires a 2^4 = 16-fold increase in time to construct the filter. 49 | % Useful when passband content is aliased, see [2]. 50 | % 51 | % Outputs: 52 | % 53 | % H : real-valued frequency magnitude response 54 | % FiltOptions : The filter options including defaults, with an added PassbandInfo field 55 | % detailing the function and time of construction of the filter 56 | % 57 | % See also: LFDemoBasicFiltGantry, LFDemoBasicFiltIllum, LFDemoBasicFiltLytroF01, 58 | % LFBuild2DFreqFan, LFBuild2DFreqLine, LFBuild4DFreqDualFan, LFBuild4DFreqHypercone, 59 | % LFBuild4DFreqHyperfan, LFBuild4DFreqPlane, LFFilt2DFFT, LFFilt4DFFT, LFFiltShiftSum 60 | 61 | % Part of LF Toolbox v0.4 released 12-Feb-2015 62 | % Copyright (c) 2013-2015 Donald G. Dansereau 63 | 64 | function [H, FiltOptions] = LFBuild4DFreqHyperfan( LFSize, Slope1, Slope2, BW, FiltOptions ) 65 | 66 | FiltOptions = LFDefaultField('FiltOptions', 'HyperfanMethod', 'Direct'); % 'Direct', 'Sweep' 67 | 68 | switch( lower(FiltOptions.HyperfanMethod )) 69 | case 'sweep' 70 | FiltOptions = LFDefaultField('FiltOptions', 'SweepSteps', 5); 71 | SweepVec = linspace(Slope1, Slope2, FiltOptions.SweepSteps); 72 | [H, FiltOptions] = LFBuild4DFreqPlane( LFSize, SweepVec(1), BW, FiltOptions ); 73 | for( CurSlope = SweepVec(2:end) ) 74 | H = max(H, LFBuild4DFreqPlane( LFSize, CurSlope, BW, FiltOptions )); 75 | end 76 | 77 | case 'direct' 78 | FiltOptions = LFDefaultField('FiltOptions', 'HyperconeBW', BW); 79 | [H, FiltOptions] = LFBuild4DFreqHypercone( LFSize, FiltOptions.HyperconeBW, FiltOptions ); 80 | [Hdf, FiltOptions] = LFBuild4DFreqDualFan( LFSize, Slope1, Slope2, BW, FiltOptions ); 81 | H = H .* Hdf; 82 | 83 | otherwise 84 | error('Unrecognized hyperfan construction method'); 85 | end 86 | 87 | TimeStamp = datestr(now,'ddmmmyyyy_HHMMSS'); 88 | FiltOptions.PassbandInfo = struct('mfilename', mfilename, 'time', TimeStamp, 'VersionStr', LFToolboxVersion); 89 | 90 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFBuild4DFreqPlane.m: -------------------------------------------------------------------------------- 1 | % LFBuild4DFreqPlane - construct a 4D planar passband filter in the frequency domain 2 | % 3 | % Usage: 4 | % 5 | % [H, FiltOptions] = LFBuild4DFreqPlane( LFSize, Slope, BW, FiltOptions ) 6 | % H = LFBuild4DFreqPlane( LFSize, Slope, BW ) 7 | % 8 | % This file constructs a real-valued magnitude response in 4D, for which the passband is a plane. 9 | % This is useful for selecting objects at a single depth from a lightfield, and is similar in effect 10 | % to refocus using, for example, the shift sum filter LFFiltShiftSum. 11 | % 12 | % Once constructed the filter must be applied to a light field, e.g. using LFFilt4DFFT. The 13 | % LFDemoBasicFilt* files demonstrate how to contruct and apply frequency-domain filters. 14 | % 15 | % A more technical discussion, including the use of filters for denoising and volumetric focus, and 16 | % the inclusion of aliases components, is included in: 17 | % 18 | % [2] D.G. Dansereau, O. Pizarro, and S. B. Williams, "Linear Volumetric Focus for Light Field 19 | % Cameras," to appear in ACM Transactions on Graphics (TOG), vol. 34, no. 2, 2015. 20 | % 21 | % Inputs: 22 | % 23 | % LFSize : Size of the frequency-domain filter. This should match or exceed the size of the 24 | % light field to be filtered. If it's larger than the input light field, the input is 25 | % zero-padded to match the filter's size by LFFilt4DFFT. 26 | % 27 | % Slope : The slope of the planar passband. If different slopes are desired in s,t and u,v, 28 | % the optional aspect parameter should be used. 29 | % 30 | % BW : 3-db Bandwidth of the planar passband. 31 | % 32 | % [optional] FiltOptions : struct controlling filter construction 33 | % SlopeMethod : 'Skew' or 'Rotate' default 'skew' 34 | % Precision : 'single' or 'double', default 'single' 35 | % Rolloff : 'Gaussian' or 'Butter', default 'Gaussian' 36 | % Order : controls the order of the filter when Rolloff is 'Butter', default 3 37 | % Aspect4D : aspect ratio of the light field, default [1 1 1 1] 38 | % Window : Default false. By default the edges of the passband are sharp; this adds 39 | % a smooth rolloff at the edges when used in conjunction with Extent4D or 40 | % IncludeAliased. 41 | % Extent4D : controls where the edge of the passband occurs, the default [1 1 1 1] 42 | % is the edge of the Nyquist box. When less than 1, enabling windowing 43 | % introduces a rolloff after the edge of the passband. Can be greater 44 | % than 1 when using IncludeAliased. 45 | % IncludeAliased : default false; allows the passband to wrap around off the edge of the 46 | % Nyquist box; used in conjunction with Window and/or Extent4D. This can 47 | % increase processing time dramatically, e.g. Extent4D = [2,2,2,2] 48 | % requires a 2^4 = 16-fold increase in time to construct the filter. 49 | % Useful when passband content is aliased, see [2]. 50 | % 51 | % Outputs: 52 | % 53 | % H : real-valued frequency magnitude response 54 | % FiltOptions : The filter options including defaults, with an added PassbandInfo field 55 | % detailing the function and time of construction of the filter 56 | % 57 | % See also: LFDemoBasicFiltGantry, LFDemoBasicFiltIllum, LFDemoBasicFiltLytroF01, 58 | % LFBuild2DFreqFan, LFBuild2DFreqLine, LFBuild4DFreqDualFan, LFBuild4DFreqHypercone, 59 | % LFBuild4DFreqHyperfan, LFBuild4DFreqPlane, LFFilt2DFFT, LFFilt4DFFT, LFFiltShiftSum 60 | 61 | % Part of LF Toolbox v0.4 released 12-Feb-2015 62 | % Copyright (c) 2013-2015 Donald G. Dansereau 63 | 64 | function [H, FiltOptions] = LFBuild4DFreqPlane( LFSize, Slope, BW, FiltOptions ) 65 | 66 | FiltOptions = LFDefaultField('FiltOptions', 'SlopeMethod', 'Skew'); % 'Skew', 'Rotate' 67 | 68 | DistFunc = @(P, FiltOptions) DistFunc_4DPlane( P, Slope, FiltOptions ); 69 | [H, FiltOptions] = LFHelperBuild4DFreq( LFSize, BW, FiltOptions, DistFunc ); 70 | 71 | TimeStamp = datestr(now,'ddmmmyyyy_HHMMSS'); 72 | FiltOptions.PassbandInfo = struct('mfilename', mfilename, 'time', TimeStamp, 'VersionStr', LFToolboxVersion); 73 | 74 | end 75 | 76 | %----------------------------------------------------------------------------------------------------------------------- 77 | function Dist = DistFunc_4DPlane( P, Slope, FiltOptions ) 78 | switch( lower(FiltOptions.SlopeMethod) ) 79 | case 'skew' 80 | R = eye(4); 81 | R(1,3) = Slope; 82 | R(2,4) = Slope; 83 | 84 | case 'rotate' 85 | Angle = -atan2(Slope,1); 86 | R2D = LFRotz( Angle ); 87 | R = eye(4); 88 | 89 | R(1,1) = R2D(1,1); 90 | R(1,3) = R2D(1,2); 91 | R(3,1) = R2D(2,1); 92 | R(3,3) = R2D(2,2); 93 | R(2,2) = R2D(1,1); 94 | R(2,4) = R2D(1,2); 95 | R(4,2) = R2D(2,1); 96 | R(4,4) = R2D(2,2); 97 | otherwise 98 | error('Unrecognized slope method'); 99 | end 100 | P = R * P; 101 | Dist = P(2,:).^2 + P(1,:).^2; 102 | end 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFCalDispEstPoses.m: -------------------------------------------------------------------------------- 1 | % LFCalDispEstPoses - Visualize pose estimates associated with a calibration info file 2 | % 3 | % Usage: 4 | % LFCalDispEstPoses( InputPath, CalOptions, DrawFrameSizeMult, BaseColour ) 5 | % 6 | % Draws a set of frames, one for each camera pose, in the colour defined by BaseColour. All inputs 7 | % except InputPath are optional. Pass an empty array "[]" to omit a parameter. See 8 | % LFUtilCalLensletCam for example usage. 9 | % 10 | % Inputs: 11 | % 12 | % InputPath : Path to folder containing CalInfo file. 13 | % 14 | % [optional] CalOptions : struct controlling calibration parameters 15 | % .CalInfoFname : Name of the file containing calibration estimate; note that this 16 | % parameter is automatically set in the CalOptions struct returned 17 | % by LFCalInit 18 | % 19 | % [optional] DrawFrameSizeMult : Multiplier on the displayed frame sizes 20 | % 21 | % [optional] BaseColour : RGB triplet defining a base drawing colour, RGB values are in the 22 | % range 0-1 23 | % 24 | % 25 | % See also: LFUtilCalLensletCam 26 | 27 | % Part of LF Toolbox v0.4 released 12-Feb-2015 28 | % Copyright (c) 2013-2015 Donald G. Dansereau 29 | 30 | function LFCalDispEstPoses( InputPath, CalOptions, DrawFrameSizeMult, BaseColour ) 31 | 32 | %---Defaults--- 33 | CalOptions = LFDefaultField( 'CalOptions', 'CalInfoFname', 'CalInfo.json' ); 34 | DrawFrameSizeMult = LFDefaultVal( 'DrawFrameSizeMult', 1 ); 35 | BaseColour = LFDefaultVal( 'BaseColour', [1,1,0] ); 36 | 37 | 38 | %--- 39 | Fname = fullfile(CalOptions.CalInfoFname); 40 | EstCamPosesV = LFStruct2Var( LFReadMetadata(fullfile(InputPath, Fname)), 'EstCamPosesV' ); 41 | 42 | % Establish an appropriate scale for the drawing 43 | AutoDrawScale = EstCamPosesV(:,1:3); 44 | AutoDrawScale = AutoDrawScale(:); 45 | AutoDrawScale = (max(AutoDrawScale) - min(AutoDrawScale))/10; 46 | 47 | %---Draw cameras--- 48 | BaseFrame = ([0 1 0 0 0 0; 0 0 0 1 0 0; 0 0 0 0 0 1]); 49 | DrawFrameMed = [AutoDrawScale * DrawFrameSizeMult * BaseFrame; ones(1,6)]; 50 | DrawFrameLong = [AutoDrawScale*3/2 * DrawFrameSizeMult * BaseFrame; ones(1,6)]; 51 | 52 | for( PoseIdx = 1:size(EstCamPosesV, 1) ) 53 | CurH = eye(4); 54 | CurH(1:3,1:3) = rodrigues( EstCamPosesV(PoseIdx,4:6) ); 55 | CurH(1:3,4) = EstCamPosesV(PoseIdx,1:3); 56 | 57 | CurH = CurH^-1; 58 | 59 | CamFrame = CurH * DrawFrameMed(:,1:4); 60 | plot3( CamFrame(1,:), CamFrame(2,:), CamFrame(3,:), '-', 'color', BaseColour.*0.5, 'LineWidth',2 ); 61 | hold on 62 | 63 | CamFrame = CurH * DrawFrameLong(:,5:6); 64 | plot3( CamFrame(1,:), CamFrame(2,:), CamFrame(3,:), '-', 'color', BaseColour, 'LineWidth',2 ); 65 | end 66 | 67 | axis equal 68 | grid on 69 | xlabel('x [m]'); 70 | ylabel('y [m]'); 71 | zlabel('z [m]'); 72 | title('Estimated camera poses'); -------------------------------------------------------------------------------- /LFToolbox0.4/LFCalDispRectIntrinsics.m: -------------------------------------------------------------------------------- 1 | % LFCalDispRectIntrinsics - Visualize sampling pattern resulting from a prescribed intrinsic matrix 2 | % 3 | % Usage: 4 | % RectOptions = LFCalDispRectIntrinsics( LF, LFMetadata, RectOptions, PaintColour ) 5 | % 6 | % During rectification, the matrix RectOptions.RectCamIntrinsicsH determines which subset of the light field gets 7 | % sampled into the rectified light field. LFCalDispRectIntrinsics visualizes the resulting sampling pattern. The 8 | % display is interactive, generated using LFDispMousePan, and can be explored by clicking and dragging the mouse. 9 | % 10 | % If no intrinsic matrix is provided, a default best-guess is constructed and returned in 11 | % RectOptions.RectCamIntrinsicsH. 12 | % 13 | % A typical usage pattern is to load a light field, call LFCalDispRectIntrinsics to set up the default intrinsic 14 | % matrix, manipulate the matrix, then visualize the manipulated sampling pattern prior to employing it in one or more 15 | % rectification calls. The function LFRecenterIntrinsics is useful in maintaining a centered sampling pattern. 16 | % 17 | % This function relies on the presence of a calibration file and associated database, see LFUtilCalLensletCam and 18 | % LFUtilDecodeLytroFolder. 19 | % 20 | % Inputs: 21 | % 22 | % LF : Light field to visualize 23 | % 24 | % LFMetadata : The light field's associated metadata - needed to locate the appropriate calibration file 25 | % 26 | % [optional] RectOptions : all fields are optional, see LFCalRectifyLF for all fields 27 | % .RectCamIntrinsicsH : The intrinsic matrix to visualize 28 | % 29 | % [optional] PaintColour : RGB triplet defining a base drawing colour, RGB values are in the range 0-1 30 | % 31 | % Outputs: 32 | % 33 | % RectOptions : RectOptions updated with any defaults that were applied 34 | % LF : The light field with visualized sample pattern 35 | % 36 | % See also: LFCalRectifyLF, LFRecenterIntrinsics, LFUtilCalLensletCam, LFUtilDecodeLytroFolder 37 | 38 | % Part of LF Toolbox v0.4 released 12-Feb-2015 39 | % Copyright (c) 2013-2015 Donald G. Dansereau 40 | 41 | function [RectOptions, LF] = LFCalDispRectIntrinsics( LF, LFMetadata, RectOptions, PaintColour ) 42 | 43 | PaintColour = LFDefaultVal( 'PaintColour', [0.5,1,1] ); 44 | [CalInfo, RectOptions] = LFFindCalInfo( LFMetadata, RectOptions ); 45 | 46 | %---Discard weight channel--- 47 | HasWeight = (size(LF,5) == 4); 48 | if( HasWeight ) 49 | LF = LF(:,:,:,:,1:3); 50 | end 51 | 52 | LFSize = size(LF); 53 | 54 | RectOptions = LFDefaultField( 'RectOptions', 'Precision', 'single' ); 55 | RectOptions = LFDefaultField( 'RectOptions', 'NInverse_Distortion_Iters', 2 ); 56 | RectOptions = LFDefaultField( 'RectOptions', 'RectCamIntrinsicsH', LFDefaultIntrinsics( LFSize, CalInfo ) ); 57 | 58 | if( isempty( CalInfo ) ) 59 | warning('No suitable calibration found, skipping'); 60 | return; 61 | end 62 | 63 | %--- visualize image utilization--- 64 | t_in=cast(1:LFSize(1), 'uint16'); 65 | s_in=cast(1:LFSize(2), 'uint16'); 66 | v_in=cast(1:10:LFSize(3), 'uint16'); 67 | u_in=cast(1:10:LFSize(4), 'uint16'); 68 | [tt,ss,vv,uu] = ndgrid(t_in,s_in,v_in,u_in); 69 | InterpIdx = [ss(:)'; tt(:)'; uu(:)'; vv(:)'; ones(size(ss(:)'))]; 70 | InterpIdx = LFMapRectifiedToMeasured( InterpIdx, CalInfo, RectOptions ); 71 | InterpIdx = round(double(InterpIdx)); 72 | 73 | PaintVal = cast(double(max(LF(:))).*PaintColour, 'like', LF); 74 | LF = 0.7*LF; 75 | 76 | %---Clamp indices--- 77 | STUVChan = [2,1,4,3]; 78 | for( Chan=1:4 ) 79 | InterpIdx(Chan,:) = min(LFSize(STUVChan(Chan)), max(1,InterpIdx(Chan,:))); 80 | end 81 | 82 | %---Paint onto LF--- 83 | RInterpIdx = sub2ind( LFSize, InterpIdx(2,:), InterpIdx(1,:), InterpIdx(4,:), InterpIdx(3,:), 1*ones(size(InterpIdx(1,:)))); 84 | LF(RInterpIdx) = PaintVal(1); 85 | RInterpIdx = sub2ind( LFSize, InterpIdx(2,:), InterpIdx(1,:), InterpIdx(4,:), InterpIdx(3,:), 2*ones(size(InterpIdx(1,:)))); 86 | LF(RInterpIdx) = PaintVal(2); 87 | RInterpIdx = sub2ind( LFSize, InterpIdx(2,:), InterpIdx(1,:), InterpIdx(4,:), InterpIdx(3,:), 3*ones(size(InterpIdx(1,:)))); 88 | LF(RInterpIdx) = PaintVal(3); 89 | 90 | %---Display LF--- 91 | LFDispMousePan( LF ); -------------------------------------------------------------------------------- /LFToolbox0.4/LFCalRectifyLF.m: -------------------------------------------------------------------------------- 1 | % LFCalRectifyLF - rectify a light field using a calibrated camera model, called as part of LFUtilDecodeLytroFolder 2 | % 3 | % Usage: 4 | % [LF, RectOptions] = LFCalRectifyLF( LF, CalInfo, RectOptions ) 5 | % [LF, RectOptions] = LFCalRectifyLF( LF, CalInfo ) 6 | % 7 | % This function is called by LFUtilDecodeLytroFolder to rectify a light field. It follows the 8 | % rectification procedure described in: 9 | % 10 | % D. G. Dansereau, O. Pizarro, and S. B. Williams, "Decoding, calibration and rectification for 11 | % lenslet-based plenoptic cameras," in Computer Vision and Pattern Recognition (CVPR), IEEE 12 | % Conference on. IEEE, Jun 2013. 13 | % 14 | % Minor differences from the paper: light field indices [i,j,k,l] are 1-based in this 15 | % implementation, and not 0-based as described in the paper. 16 | % 17 | % Note that a calibration should only be applied to a light field decoded using the same lenslet 18 | % grid model. This is because the lenslet grid model forms an implicit part of the calibration, 19 | % and changing it will invalidate the calibration. 20 | % 21 | % LFCalDispRectIntrinsics is useful for visualizing the sampling pattern associated with a requested 22 | % intrinsic matrix. 23 | % 24 | % Inputs: 25 | % 26 | % LF : The light field to rectify; should be floating point 27 | % 28 | % CalInfo struct contains a calibrated camera model, see LFUtilCalLensletCam: 29 | % .EstCamIntrinsicsH : 5x5 homogeneous matrix describing the lenslet camera intrinsics 30 | % .EstCamDistortionV : Estimated distortion parameters 31 | % 32 | % [optional] RectOptions struct (all fields are optional) : 33 | % .NInverse_Distortion_Iters : Number of iterations in inverse distortion estimation 34 | % .Precision : 'single' or 'double' 35 | % .RectCamIntrinsicsH : Requests a specific set of intrinsics for the rectified light 36 | % field. By default the rectified intrinsic matrix is 37 | % automatically constructed from the calibrated intrinsic 38 | % matrix, but this process can in some instances yield poor 39 | % results: excessive black space at the edges of the light field 40 | % sample space, or excessive loss of scene content off the edges 41 | % of the space. This parameters allows you to fine-tune the 42 | % desired rectified intrinsic matrix. 43 | % 44 | % Outputs : 45 | % 46 | % LF : The rectified light field 47 | % RectOptions : The rectification options as applied, including any default values employed. 48 | % 49 | % See also: LFCalDispRectIntrinsics, LFUtilCalLensletCam, LFUtilDecodeLytroFolder, LFUtilProcessWhiteImages 50 | 51 | % Part of LF Toolbox v0.4 released 12-Feb-2015 52 | % Copyright (c) 2013-2015 Donald G. Dansereau 53 | 54 | function [LF, RectOptions] = LFCalRectifyLF( LF, CalInfo, RectOptions ) 55 | 56 | %---Defaults--- 57 | RectOptions = LFDefaultField( 'RectOptions', 'Precision', 'single' ); 58 | RectOptions = LFDefaultField( 'RectOptions', 'NInverse_Distortion_Iters', 2 ); 59 | RectOptions = LFDefaultField( 'RectOptions', 'MaxUBlkSize', 32 ); 60 | LFSize = size(LF); 61 | RectOptions = LFDefaultField( 'RectOptions', 'RectCamIntrinsicsH', LFDefaultIntrinsics( LFSize, CalInfo ) ); 62 | 63 | %---Build interpolation indices--- 64 | fprintf('Generating interpolation indices...\n'); 65 | NChans = LFSize(5); 66 | LF = cast(LF, RectOptions.Precision); 67 | 68 | %---chop up the LF along u--- 69 | fprintf('Interpolating...'); 70 | UBlkSize = RectOptions.MaxUBlkSize; 71 | LFOut = LF; 72 | for( UStart = 1:UBlkSize:LFSize(4) ) 73 | UStop = UStart + UBlkSize - 1; 74 | UStop = min(UStop, LFSize(4)); 75 | 76 | t_in=cast(1:LFSize(1), 'uint16'); % saving some mem by using uint16 77 | s_in=cast(1:LFSize(2), 'uint16'); 78 | v_in=cast(1:LFSize(3), 'uint16'); 79 | u_in=cast(UStart:UStop, 'uint16'); 80 | [tt,ss,vv,uu] = ndgrid(t_in,s_in,v_in,u_in); 81 | 82 | % InterpIdx initially holds the index of the desired ray, and is evolved through the application 83 | % of the inverse distortion model to eventually hold the continuous-domain index of the undistorted 84 | % ray, and passed to the interpolation step. 85 | InterpIdx = [ss(:)'; tt(:)'; uu(:)'; vv(:)'; ones(size(ss(:)'))]; 86 | DestSize = size(tt); 87 | clear tt ss vv uu 88 | 89 | InterpIdx = LFMapRectifiedToMeasured( InterpIdx, CalInfo, RectOptions ); 90 | 91 | for( ColChan = 1:NChans ) 92 | % todo[optimization]: use a weighted interpolation scheme to exploit the weight channel 93 | InterpSlice = interpn(squeeze(LF(:,:,:,:,ColChan)), InterpIdx(2,:),InterpIdx(1,:), InterpIdx(4,:),InterpIdx(3,:), 'linear'); 94 | InterpSlice = reshape(InterpSlice, DestSize); 95 | LFOut(:,:,:,UStart:UStop,ColChan) = InterpSlice; 96 | end 97 | 98 | fprintf('.') 99 | end 100 | LF = LFOut; 101 | clear LFOut; 102 | 103 | %---Clip interpolation result, which sometimes rings slightly out of range--- 104 | LF(isnan(LF)) = 0; 105 | LF = max(0, min(1, LF)); 106 | 107 | fprintf('\nDone\n'); 108 | 109 | end 110 | 111 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFColourCorrect.m: -------------------------------------------------------------------------------- 1 | % LFColourCorrect - applies a colour correction matrix, balance vector, and gamma, called by LFUtilDecodeLytroFolder 2 | % 3 | % Usage: 4 | % LF = LFColourCorrect( LF, ColMatrix, ColBalance, Gamma ) 5 | % 6 | % This implementation deals with saturated input pixels by aggressively saturating output pixels. 7 | % 8 | % Inputs : 9 | % 10 | % LF : a light field or image to colour correct. It should be a floating point array, and 11 | % may be of any dimensinality so long as the last dimension has length 3. For example, a 2D 12 | % image of size [Nl,Nk,3], a 4D image of size [Nj,Ni,Nl,Nk,3], and a 1D list of size [N,3] 13 | % are all valid. 14 | % 15 | % ColMatrix : a 3x3 colour conversion matrix. This can be built from the metadata provided 16 | % with Lytro imagery using the command: 17 | % ColMatrix = reshape(cell2mat(LFMetadata.image.color.ccmRgbToSrgbArray), 3,3); 18 | % as demonstrated in LFUtilDecodeLytroFolder. 19 | % 20 | % ColBalance : 3-element vector containing a multiplicative colour balance. 21 | % 22 | % Gamma : rudimentary gamma correction is applied of the form LF = LF.^Gamma. 23 | % 24 | % Outputs : 25 | % 26 | % LF, of the same dimensionality as the input. 27 | % 28 | % 29 | % See also: LFHistEqualize, LFUtilDecodeLytroFolder 30 | 31 | % Part of LF Toolbox v0.4 released 12-Feb-2015 32 | % Copyright (c) 2013-2015 Donald G. Dansereau 33 | 34 | function LF = LFColourCorrect(LF, ColMatrix, ColBalance, Gamma) 35 | 36 | LFSize = size(LF); 37 | 38 | % Flatten input to a flat list of RGB triplets 39 | NDims = numel(LFSize); 40 | LF = reshape(LF, [prod(LFSize(1:NDims-1)), 3]); 41 | 42 | LF = bsxfun(@times, LF, ColBalance); 43 | LF = LF * ColMatrix; 44 | 45 | % Unflatten result 46 | LF = reshape(LF, [LFSize(1:NDims-1),3]); 47 | 48 | % Saturating eliminates some issues with clipped pixels, but is aggressive and loses information 49 | % todo[optimization]: find a better approach to dealing with saturated pixels 50 | SaturationLevel = ColBalance*ColMatrix; 51 | SaturationLevel = min(SaturationLevel); 52 | LF = min(SaturationLevel,max(0,LF)) ./ SaturationLevel; 53 | 54 | % Apply gamma 55 | LF = LF .^ Gamma; 56 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFDemoBasicFiltGantry.m: -------------------------------------------------------------------------------- 1 | % LFDemoBasicFiltGantry - demonstrate basic filters on stanford-style gantry light fields 2 | % 3 | % Generates and displays a set of filtered light field images as separate figures. Demonstrates 4 | % the shift sum filter and 4D planar and 4D hyperfan linear filters. 5 | % 6 | % Before running this you must download sample light fields from the stanford light field archive. 7 | % Run the demo from the top of the stanford light fields folder. Please see the accompanying documentation for 8 | % more information. 9 | % 10 | % To change input light fields, uncomment the appropriate line below. 11 | 12 | % Part of LF Toolbox v0.4 released 12-Feb-2015 13 | % Copyright (c) 2013-2015 Donald G. Dansereau 14 | 15 | clearvars 16 | 17 | %---Tweakables--- 18 | UVLimit = 300; % Light fields get scaled to this size in u,v 19 | InPathPattern = '%s/rectified'; % Pattern for where the light fields are unzipped 20 | 21 | % Select an input light field from the list below 22 | % InFile: Which of the Stanford lightfields to load 23 | % SFlip: Some of the light fields are of a different "handedness", and need to be flipped in s 24 | 25 | % InFile = 'Amethyst'; SFlip = true; 26 | % InFile = 'Bracelet'; SFlip = false; 27 | % InFile = 'Bulldozer'; SFlip = true; 28 | % InFile = 'Bunny'; SFlip = true; 29 | % InFile = 'Chess'; SFlip = true; 30 | % InFile = 'Eucalyptus'; SFlip = true; 31 | % InFile = 'JellyBeans'; SFlip = true; 32 | InFile = 'LegoKnights'; SFlip = false; 33 | % InFile = 'Tarot_Coarse'; SFlip = false; 34 | % InFile = 'Tarot_Fine'; SFlip = false; 35 | % InFile = 'Treasure'; SFlip = true; 36 | % InFile = 'Truck'; SFlip = true; 37 | 38 | %- Params for linear filters 39 | % These must be tuned to conform to the characteristics of the light field 40 | ShiftSumSlope1 = -0.6 * UVLimit/400; 41 | ShiftSumSlope2 = 0; 42 | PlanarSlope = 0; 43 | PlanarBW = 0.06; 44 | HyperfanSlope1 = 0; 45 | HyperfanSlope2 = 2; 46 | HyperfanBW = 0.035; 47 | FiltOptions = []; 48 | 49 | %---Load the light field--- 50 | FullPath = sprintf(InPathPattern, InFile); 51 | fprintf('%s : ', FullPath); 52 | LF = LFReadGantryArray(FullPath, struct('UVLimit', UVLimit) ); 53 | LFSize = size(LF); 54 | if( SFlip ) % Some of the light fields are of a different "handedness", and need to be flipped in s 55 | LF = LF(:,end:-1:1,:,:,:); 56 | end 57 | 58 | CurFigure = 1; 59 | LFFigure(CurFigure); 60 | CurFigure = CurFigure + 1; 61 | LFDisp(LF); 62 | axis image off 63 | truesize 64 | title('Input'); 65 | drawnow 66 | 67 | %---Demonstrate shift sum filter--- 68 | for( Slope = [ShiftSumSlope1, ShiftSumSlope2] ) 69 | fprintf('Applying shift sum filter'); 70 | [ShiftImg, FiltOptionsOut] = LFFiltShiftSum( LF, Slope ); 71 | fprintf(' Done\n'); 72 | FiltOptionsOut 73 | 74 | LFFigure(CurFigure); 75 | CurFigure = CurFigure + 1; 76 | LFDisp(ShiftImg); 77 | axis image off 78 | truesize 79 | title(sprintf('Shift sum filter, slope %.3g', Slope)); 80 | drawnow 81 | end 82 | 83 | %---Demonstrate 2D line filter--- 84 | fprintf('Building 2D frequency line... '); 85 | Htv = LFBuild2DFreqLine( LFSize([1,3]), PlanarSlope, PlanarBW, FiltOptions); 86 | fprintf('Applying filter in t,v'); 87 | [LFFilt, FiltOptionsOut] = LFFilt2DFFT( LF, Htv, [1,3], FiltOptions ); 88 | FiltOptionsOut 89 | LFFigure(CurFigure); 90 | CurFigure = CurFigure + 1; 91 | LFDisp(LFFilt); 92 | axis image off 93 | truesize 94 | title(sprintf('Freq. line filt. t,v; slope %.3g, BW %.3g', PlanarSlope, PlanarBW)); 95 | drawnow 96 | 97 | fprintf('Building 2D frequency line... '); 98 | Hsu = LFBuild2DFreqLine( LFSize([2,4]), PlanarSlope, PlanarBW, FiltOptions); 99 | fprintf('Applying filter in s,u'); 100 | [LFFilt, FiltOptionsOut] = LFFilt2DFFT( LFFilt, Hsu, [2,4], FiltOptions ); 101 | LFFigure(CurFigure); 102 | CurFigure = CurFigure + 1; 103 | LFDisp(LFFilt); 104 | axis image off 105 | truesize 106 | title(sprintf('Freq. line filt. t,v then s,u; slope %.3g, BW %.3g', PlanarSlope, PlanarBW)); 107 | drawnow 108 | 109 | %---Demonstrate 4D Planar filter--- 110 | fprintf('Building 4D frequency plane... '); 111 | [H, FiltOptionsOut] = LFBuild4DFreqPlane( LFSize, PlanarSlope, PlanarBW ); 112 | fprintf('Applying filter'); 113 | [LFFilt, FiltOptionsOut] = LFFilt4DFFT( LF, H, FiltOptionsOut ); 114 | FiltOptionsOut 115 | LFFigure(CurFigure); 116 | CurFigure = CurFigure + 1; 117 | LFDisp(LFFilt); 118 | axis image off 119 | truesize 120 | title(sprintf('Frequency planar filter, slope %.3g, HyperfanBW %.3g', PlanarSlope, PlanarBW)); 121 | drawnow 122 | 123 | %---Demonstrate 4D Hyperfan filter--- 124 | fprintf('Building 4D frequency hyperfan... '); 125 | [H, FiltOptionsOut] = LFBuild4DFreqHyperfan( LFSize, HyperfanSlope1, HyperfanSlope2, HyperfanBW ); 126 | fprintf('Applying filter'); 127 | [LFFilt, FiltOptionsOut] = LFFilt4DFFT( LF, H, FiltOptionsOut ); 128 | FiltOptionsOut 129 | LFFigure(CurFigure); 130 | CurFigure = CurFigure + 1; 131 | LFDisp(LFFilt); 132 | axis image off 133 | truesize 134 | title(sprintf('Frequency hyperfan filter, slopes %.3g, %.3g, HyperfanBW %.3g', HyperfanSlope1, HyperfanSlope2, HyperfanBW)); 135 | drawnow 136 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFDemoBasicFiltIllum.m: -------------------------------------------------------------------------------- 1 | % LFDemoBasicFiltIllum - demonstrate basic filters on illum-captured imagery 2 | % 3 | % Generates and displays a set of filtered light field images as separate figures. Demonstrates 4 | % the shift sum filter and 4D planar and 4D hyperfan linear filters. 5 | % 6 | % Before running this you must download and decode the sample light field pack. Run the demo from 7 | % the top of the samples folder. Please see the accompanying documentation for more information. 8 | 9 | % Part of LF Toolbox v0.4 released 12-Feb-2015 10 | % Copyright (c) 2013-2015 Donald G. Dansereau 11 | 12 | clearvars 13 | 14 | %---Tweakables--- 15 | InputFname = fullfile('Images','Illum','LorikeetHiding__Decoded'); 16 | 17 | %---Load up a light field--- 18 | fprintf('Loading %s...', InputFname); 19 | load(InputFname,'LF'); 20 | fprintf(' Done\n'); 21 | LFSize = size(LF); 22 | 23 | CurFigure = 1; 24 | LFFigure(CurFigure); 25 | CurFigure = CurFigure + 1; 26 | LFDisp(LF); 27 | axis image off 28 | truesize 29 | title('Input'); 30 | drawnow 31 | 32 | %---Demonstrate shift sum filter--- 33 | for( Slope = [-50/15, 9/15, -4/15] ) % Lorikeet: -4/15; Background: 9/15; Foreground: -50/15 34 | fprintf('Applying shift sum filter'); 35 | [ShiftImg, FiltOptionsOut] = LFFiltShiftSum( LF, Slope ); 36 | fprintf(' Done\n'); 37 | FiltOptionsOut 38 | 39 | LFFigure(CurFigure); 40 | CurFigure = CurFigure + 1; 41 | LFDisp(ShiftImg); 42 | axis image off 43 | truesize 44 | title(sprintf('Shift sum filter, slope %.3g', Slope)); 45 | drawnow 46 | end 47 | 48 | %---Setup for linear filters--- 49 | LFPaddedSize = LFSize; 50 | % For systems with more memory, consider using some padding to improve performance near s,t edges: 51 | % LFPaddedSize = [20,20, size(LF,3) + 16,size(LF,4) + 16]; 52 | BW = 0.04; 53 | FiltOptions = []; 54 | 55 | %---Demonstrate 2D line filter--- 56 | Slope = -4/15; % Lorikeet 57 | fprintf('Building 2D frequency line... '); 58 | Htv = LFBuild2DFreqLine( LFPaddedSize([1,3]), Slope, BW, FiltOptions); 59 | fprintf('Applying filter in t,v'); 60 | [LFFilt, FiltOptionsOut] = LFFilt2DFFT( LF, Htv, [1,3], FiltOptions ); 61 | FiltOptionsOut 62 | LFFigure(CurFigure); 63 | CurFigure = CurFigure + 1; 64 | LFDisp(LFFilt); 65 | axis image off 66 | truesize 67 | title(sprintf('Freq. line filt. t,v; slope %.3g, BW %.3g', Slope, BW)); 68 | drawnow 69 | 70 | fprintf('Building 2D frequency line... '); 71 | Hsu = LFBuild2DFreqLine( LFPaddedSize([2,4]), Slope, BW, FiltOptions); 72 | fprintf('Applying filter in s,u'); 73 | [LFFilt, FiltOptionsOut] = LFFilt2DFFT( LFFilt, Hsu, [2,4], FiltOptions ); 74 | LFFigure(CurFigure); 75 | CurFigure = CurFigure + 1; 76 | LFDisp(LFFilt); 77 | axis image off 78 | truesize 79 | title(sprintf('Freq. line filt. t,v then s,u; slope %.3g, BW %.3g', Slope, BW)); 80 | drawnow 81 | 82 | %---Demonstrate 4D Planar filter--- 83 | Slope = -4/15; % Lorikeet 84 | fprintf('Building 4D frequency plane... '); 85 | [H, FiltOptionsOut] = LFBuild4DFreqPlane( LFPaddedSize, Slope, BW, FiltOptions ); 86 | fprintf('Applying filter'); 87 | [LFFilt, FiltOptionsOut] = LFFilt4DFFT( LF, H, FiltOptionsOut ); 88 | FiltOptionsOut 89 | LFFigure(CurFigure); 90 | CurFigure = CurFigure + 1; 91 | LFDisp(LFFilt); 92 | axis image off 93 | truesize 94 | title(sprintf('Frequency planar filter, slope %.3g, BW %.3g', Slope, BW)); 95 | drawnow 96 | clear LFFilt 97 | 98 | %---Demonstrate 4D Hyperfan filter--- 99 | Slope1 = -4/15; % Lorikeet 100 | Slope2 = 15/15; % Far background 101 | fprintf('Building 4D frequency hyperfan... '); 102 | [H, FiltOptionsOut] = LFBuild4DFreqHyperfan( LFPaddedSize, Slope1, Slope2, BW, FiltOptions ); 103 | fprintf('Applying filter'); 104 | [LFFilt, FiltOptionsOut] = LFFilt4DFFT( LF, H, FiltOptionsOut ); 105 | FiltOptionsOut 106 | LFFigure(CurFigure); 107 | CurFigure = CurFigure + 1; 108 | LFDisp(LFFilt); 109 | axis image off 110 | truesize 111 | title(sprintf('Frequency hyperfan filter, slopes %.3g, %.3g, BW %.3g', Slope1, Slope2, BW)); 112 | drawnow -------------------------------------------------------------------------------- /LFToolbox0.4/LFDemoBasicFiltLytroF01.m: -------------------------------------------------------------------------------- 1 | % LFDemoBasicFiltLytroF01 - demonstrate basic filters on Lytro-F01-captured imagery 2 | % 3 | % Generates and displays a set of filtered light field images as separate figures. Demonstrates 4 | % the shift sum filter and 4D planar and 4D hyperfan linear filters. 5 | % 6 | % Before running this you must download and decode the sample light field pack. Run the demo from 7 | % the top of the samples folder. Please see the accompanying documentation for more information. 8 | 9 | % Part of LF Toolbox v0.4 released 12-Feb-2015 10 | % Copyright (c) 2013-2015 Donald G. Dansereau 11 | 12 | clearvars 13 | 14 | %---Tweakables--- 15 | InputFname = fullfile('Images','F01','IMG_0002__Decoded'); 16 | 17 | %---Load up a light field--- 18 | fprintf('Loading %s...', InputFname); 19 | load(InputFname,'LF'); 20 | fprintf(' Done\n'); 21 | LFSize = size(LF); 22 | 23 | CurFigure = 1; 24 | LFFigure(CurFigure); 25 | CurFigure = CurFigure + 1; 26 | LFDisp(LF); 27 | axis image off 28 | truesize 29 | title('Input'); 30 | drawnow 31 | 32 | %---Demonstrate shift sum filter--- 33 | for( Slope = [-11/9, 4/9, -3/9] ) % Lorikeet: -3/9; Building: 4/9; Grubby window: -11/9 34 | fprintf('Applying shift sum filter'); 35 | [ShiftImg, FiltOptionsOut] = LFFiltShiftSum( LF, Slope ); 36 | fprintf(' Done\n'); 37 | FiltOptionsOut 38 | 39 | LFFigure(CurFigure); 40 | CurFigure = CurFigure + 1; 41 | LFDisp(ShiftImg); 42 | axis image off 43 | truesize 44 | title(sprintf('Shift sum filter, slope %.3g', Slope)); 45 | drawnow 46 | end 47 | 48 | %---Setup for linear filters--- 49 | LFPaddedSize = [16, 16, 400, 400]; 50 | BW = 0.03; 51 | FiltOptions = []; 52 | FiltOptions.Rolloff = 'Butter'; 53 | 54 | %---Demonstrate 2D line filter--- 55 | Slope = -3/9; % Lorikeet 56 | fprintf('Building 2D frequency line... '); 57 | Htv = LFBuild2DFreqLine( LFPaddedSize([1,3]), Slope, BW, FiltOptions); 58 | fprintf('Applying filter in t,v'); 59 | [LFFilt, FiltOptionsOut] = LFFilt2DFFT( LF, Htv, [1,3], FiltOptions ); 60 | FiltOptionsOut 61 | LFFigure(CurFigure); 62 | CurFigure = CurFigure + 1; 63 | LFDisp(LFFilt); 64 | axis image off 65 | truesize 66 | title(sprintf('Freq. line filt. t,v; slope %.3g, BW %.3g', Slope, BW)); 67 | drawnow 68 | 69 | fprintf('Building 2D frequency line... '); 70 | Hsu = LFBuild2DFreqLine( LFPaddedSize([2,4]), Slope, BW, FiltOptions); 71 | fprintf('Applying filter in s,u'); 72 | [LFFilt, FiltOptionsOut] = LFFilt2DFFT( LFFilt, Hsu, [2,4], FiltOptions ); 73 | LFFigure(CurFigure); 74 | CurFigure = CurFigure + 1; 75 | LFDisp(LFFilt); 76 | axis image off 77 | truesize 78 | title(sprintf('Freq. line filt. t,v then s,u; slope %.3g, BW %.3g', Slope, BW)); 79 | drawnow 80 | 81 | %---Demonstrate 4D Planar filter--- 82 | Slope = -3/9; % Lorikeet 83 | fprintf('Building 4D frequency plane... '); 84 | [H, FiltOptionsOut] = LFBuild4DFreqPlane( LFPaddedSize, Slope, BW ); 85 | fprintf('Applying filter'); 86 | [LFFilt, FiltOptionsOut] = LFFilt4DFFT( LF, H, FiltOptionsOut ); 87 | FiltOptionsOut 88 | LFFigure(CurFigure); 89 | CurFigure = CurFigure + 1; 90 | LFDisp(LFFilt); 91 | axis image off 92 | truesize 93 | title(sprintf('Frequency planar filter, slope %.3g, BW %.3g', Slope, BW)); 94 | drawnow 95 | 96 | %---Demonstrate 4D Hyperfan filter--- 97 | Slope1 = -3/9; % Lorikeet 98 | Slope2 = 4/9; % Building 99 | fprintf('Building 4D frequency hyperfan... '); 100 | [H, FiltOptionsOut] = LFBuild4DFreqHyperfan( LFPaddedSize, Slope1, Slope2, BW, FiltOptions ); 101 | fprintf('Applying filter'); 102 | [LFFilt, FiltOptionsOut] = LFFilt4DFFT( LF, H, FiltOptionsOut ); 103 | FiltOptionsOut 104 | LFFigure(CurFigure); 105 | CurFigure = CurFigure + 1; 106 | LFDisp(LFFilt); 107 | axis image off 108 | truesize 109 | title(sprintf('Frequency hyperfan filter, slopes %.3g, %.3g, BW %.3g', Slope1, Slope2, BW)); 110 | drawnow 111 | 112 | %---Demonstrate 4D Hyperfan filter--- 113 | Slope1 = -3/9; % Lorikeet 114 | Slope2 = -11/9; % Grubby window 115 | fprintf('Building 4D frequency hyperfan... '); 116 | [H, FiltOptionsOut] = LFBuild4DFreqHyperfan( LFPaddedSize, Slope1, Slope2, BW, FiltOptions ); 117 | fprintf('Applying filter'); 118 | [LFFilt, FiltOptionsOut] = LFFilt4DFFT( LF, H, FiltOptionsOut ); 119 | FiltOptionsOut 120 | LFFigure(CurFigure); 121 | CurFigure = CurFigure + 1; 122 | LFDisp(LFFilt); 123 | axis image off 124 | truesize 125 | title(sprintf('Frequency hyperfan filter, slopes %.3g, %.3g, BW %.3g', Slope1, Slope2, BW)); 126 | drawnow 127 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFDisp.m: -------------------------------------------------------------------------------- 1 | % LFDisp - Convenience function to display a 2D slice of a light field 2 | % 3 | % Usage: 4 | % LFSlice = LFDispMousePan( LF ) 5 | % LFDispMousePan( LF ) 6 | % 7 | % 8 | % The centermost image is taken in s and t. Also works with 3D arrays of images. If an output argument is included, no 9 | % display is generated, but the extracted slice is returned instead. 10 | % 11 | % Inputs: 12 | % 13 | % LF : a colour or single-channel light field, and can a floating point or integer format. For 14 | % display, it is scaled as in imagesc. If LF contains more than three colour 15 | % channels, as is the case when a weight channel is present, only the first three are used. 16 | % 17 | % 18 | % Outputs: 19 | % 20 | % LFSlice : if an output argument is used, no display is generated, but the extracted slice is returned. 21 | % 22 | % 23 | % See also: LFDispVidCirc, LFDispMousePan 24 | 25 | % Part of LF Toolbox v0.4 released 12-Feb-2015 26 | % Copyright (c) 2013-2015 Donald G. Dansereau 27 | 28 | function ImgOut = LFDisp( LF ) 29 | 30 | LF = squeeze(LF); 31 | LFSize = size(LF); 32 | 33 | HasWeight = (ndims(LF)>2 && LFSize(end)==2 || LFSize(end)==4); 34 | HasColor = (ndims(LF)>2 && (LFSize(end)==3 || LFSize(end)==4) ); 35 | HasMonoAndWeight = (ndims(LF)>2 && LFSize(end)==2); 36 | 37 | if( HasColor || HasMonoAndWeight ) 38 | GoalDims = 3; 39 | else 40 | GoalDims = 2; 41 | end 42 | while( ndims(LF) > GoalDims ) 43 | LF = squeeze(LF(round(end/2),:,:,:,:,:,:)); 44 | end 45 | if( HasWeight ) 46 | LF = squeeze(LF(:,:,1:end-1)); 47 | end 48 | 49 | if( nargout > 0 ) 50 | ImgOut = LF; 51 | else 52 | imagesc(LF); 53 | end 54 | 55 | 56 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFDispMousePan.m: -------------------------------------------------------------------------------- 1 | % LFDispMousePan - visualize a 4D light field using the mouse to pan through two dimensions 2 | % 3 | % Usage: 4 | % FigureHandle = LFDispMousePan( LF ) 5 | % FigureHandle = LFDispMousePan( LF, ScaleFactor ) 6 | % 7 | % A figure is set up for high-performance display, with the tag 'LFDisplay'. Subsequent calls to 8 | % this function and LFDispVidCirc will reuse the same figure, rather than creating a new window on 9 | % each call. The window should be closed when changing ScaleFactor. 10 | % 11 | % Inputs: 12 | % 13 | % LF : a colour or single-channel light field, and can a floating point or integer format. For 14 | % display, it is converted to 8 bits per channel. If LF contains more than three colour 15 | % channels, as is the case when a weight channel is present, only the first three are used. 16 | % 17 | % Optional Inputs: 18 | % 19 | % ScaleFactor : Adjusts the size of the display -- 1 means no change, 2 means twice as big, etc. 20 | % Integer values are recommended to avoid scaling artifacts. Note that the scale 21 | % factor is only applied the first time a figure is created. To change the scale 22 | % factor, close the figure before calling LFDispMousePan. 23 | % 24 | % Outputs: 25 | % 26 | % FigureHandle 27 | % 28 | % 29 | % See also: LFDisp, LFDispVidCirc 30 | 31 | % Part of LF Toolbox v0.4 released 12-Feb-2015 32 | % Copyright (c) 2013-2015 Donald G. Dansereau 33 | 34 | function FigureHandle = LFDispMousePan( LF, varargin ) 35 | 36 | %---Defaults--- 37 | MouseRateDivider = 30; 38 | 39 | %---Check for weight channel--- 40 | HasWeight = (size(LF,5) == 4); 41 | 42 | %---Discard weight channel--- 43 | if( HasWeight ) 44 | LF = LF(:,:,:,:,1:3); 45 | end 46 | 47 | %---Rescale for 8-bit display--- 48 | if( isfloat(LF) ) 49 | LF = uint8(LF ./ max(LF(:)) .* 255); 50 | else 51 | LF = uint8(LF.*(255 / double(intmax(class(LF))))); 52 | end 53 | 54 | %---Setup the display--- 55 | [ImageHandle,FigureHandle] = LFDispSetup( squeeze(LF(max(1,floor(end/2)),max(1,floor(end/2)),:,:,:)), varargin{:} ); 56 | 57 | BDH = @(varargin) ButtonDownCallback(FigureHandle, varargin); 58 | BUH = @(varargin) ButtonUpCallback(FigureHandle, varargin); 59 | set(FigureHandle, 'WindowButtonDownFcn', BDH ); 60 | set(FigureHandle, 'WindowButtonUpFcn', BUH ); 61 | 62 | 63 | [TSize,SSize, ~,~] = size(LF(:,:,:,:,1)); 64 | CurX = max(1,floor((SSize-1)/2+1)); 65 | CurY = max(1,floor((TSize-1)/2+1)); 66 | DragStart = 0; 67 | 68 | %---Update frame before first mouse drag--- 69 | LFRender = squeeze(LF(round(CurY), round(CurX), :,:,:)); 70 | set(ImageHandle,'cdata', LFRender); 71 | 72 | fprintf('Click and drag to shift perspective\n'); 73 | 74 | function ButtonDownCallback(FigureHandle,varargin) 75 | set(FigureHandle, 'WindowButtonMotionFcn', @ButtonMotionCallback); 76 | DragStart = get(gca,'CurrentPoint')'; 77 | DragStart = DragStart(1:2,1)'; 78 | end 79 | 80 | function ButtonUpCallback(FigureHandle, varargin) 81 | set(FigureHandle, 'WindowButtonMotionFcn', ''); 82 | end 83 | 84 | function ButtonMotionCallback(varargin) 85 | CurPoint = get(gca,'CurrentPoint'); 86 | CurPoint = CurPoint(1,1:2); 87 | RelPoint = CurPoint - DragStart; 88 | CurX = max(1,min(SSize, CurX - RelPoint(1)/MouseRateDivider)); 89 | CurY = max(1,min(TSize, CurY - RelPoint(2)/MouseRateDivider)); 90 | DragStart = CurPoint; 91 | 92 | LFRender = squeeze(LF(round(CurY), round(CurX), :,:,:)); 93 | set(ImageHandle,'cdata', LFRender); 94 | end 95 | 96 | end -------------------------------------------------------------------------------- /LFToolbox0.4/LFDispVidCirc.m: -------------------------------------------------------------------------------- 1 | % LFDispVidCirc - visualize a 4D light field animating a circular path through two dimensions 2 | % 3 | % Usage: 4 | % 5 | % FigureHandle = LFDispVidCirc( LF ) 6 | % FigureHandle = LFDispVidCirc( LF, PathRadius_percent, FrameDelay ) 7 | % FigureHandle = LFDispVidCirc( LF, PathRadius_percent, FrameDelay, ScaleFactor ) 8 | % FigureHandle = LFDispVidCirc( LF, [], [], ScaleFactor ) 9 | % 10 | % 11 | % A figure is set up for high-performance display, with the tag 'LFDisplay'. Subsequent calls to 12 | % this function and LFDispVidCirc will reuse the same figure, rather than creating a new window on 13 | % each call. All parameters except LF are optional -- pass an empty array "[]" to omit an optional 14 | % parameter. 15 | % 16 | % 17 | % Inputs: 18 | % 19 | % LF : a colour or single-channel light field, and can a floating point or integer format. For 20 | % display, it is converted to 8 bits per channel. If LF contains more than three colour 21 | % channels, as is the case when a weight channel is present, only the first three are used. 22 | % 23 | % Optional Inputs: 24 | % 25 | % PathRadius_percent : radius of the circular path taken by the viewpoint. Values that are too 26 | % high can result in collision with the edges of the lenslet image, while 27 | % values that are too small result in a less impressive visualization. The 28 | % default value is 60%. 29 | % 30 | % FrameDelay : sets the delay between frames, in seconds. The default value is 1/60th of 31 | % a second. 32 | % 33 | % ScaleFactor : Adjusts the size of the display -- 1 means no change, 2 means twice as 34 | % big, etc. Integer values are recommended to avoid scaling artifacts. Note 35 | % that the scale factor is only applied the first time a figure is created. 36 | % To change the scale factor, close the figure before calling 37 | % LFDispMousePan. 38 | % 39 | % Outputs: 40 | % 41 | % FigureHandle 42 | % 43 | % 44 | % See also: LFDisp, LFDispMousePan 45 | 46 | % Part of LF Toolbox v0.4 released 12-Feb-2015 47 | % Copyright (c) 2013-2015 Donald G. Dansereau 48 | 49 | function FigureHandle = LFDispVidCirc( LF, PathRadius_percent, FrameDelay, varargin ) 50 | 51 | %---Defaults--- 52 | PathRadius_percent = LFDefaultVal( 'PathRadius_percent', 60 ); 53 | FrameDelay = LFDefaultVal( 'FrameDelay', 1/60 ); 54 | 55 | 56 | %---Check for mono and clip off the weight channel if present--- 57 | Mono = (ndims(LF) == 4); 58 | if( ~Mono ) 59 | LF = LF(:,:,:,:,1:3); 60 | end 61 | 62 | %---Rescale for 8-bit display--- 63 | if( isfloat(LF) ) 64 | LF = uint8(LF ./ max(LF(:)) .* 255); 65 | else 66 | LF = uint8(LF.*(255 / double(intmax(class(LF))))); 67 | end 68 | 69 | %---Setup the display--- 70 | [ImageHandle,FigureHandle] = LFDispSetup( squeeze(LF(floor(end/2),floor(end/2),:,:,:)), varargin{:} ); 71 | 72 | %---Setup the motion path--- 73 | [TSize,SSize, ~,~] = size(LF(:,:,:,:,1)); 74 | TCent = (TSize-1)/2 + 1; 75 | SCent = (SSize-1)/2 + 1; 76 | 77 | t = 0; 78 | RotRate = 0.05; 79 | RotRad = TCent*PathRadius_percent/100; 80 | 81 | while(1) 82 | TVal = TCent + RotRad * cos( 2*pi*RotRate * t ); 83 | SVal = SCent + RotRad * sin( 2*pi*RotRate * t ); 84 | 85 | SIdx = round(SVal); 86 | TIdx = round(TVal); 87 | 88 | CurFrame = squeeze(LF( TIdx, SIdx, :,:,: )); 89 | set(ImageHandle,'cdata', CurFrame ); 90 | 91 | pause(FrameDelay) 92 | t = t + 1; 93 | end 94 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFFigure.m: -------------------------------------------------------------------------------- 1 | function h = LFFigure(h, varargin) 2 | % LFFIGURE (originally sfigure) Create figure window (minus annoying focus-theft). 3 | % 4 | % Usage is identical to figure. 5 | % 6 | % Daniel Eaton, 2005 7 | % 8 | % See also figure 9 | 10 | if nargin>=1 11 | if ishandle(h) 12 | set(0, 'CurrentFigure', h); 13 | else 14 | h = figure(h, varargin{:}); 15 | end 16 | else 17 | h = figure; 18 | end 19 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFFilt2DFFT.m: -------------------------------------------------------------------------------- 1 | % LFFilt2DFFT - Apply a 2D frequency-domain filter to a 4D light field using the FFT 2 | % 3 | % Usage: 4 | % 5 | % [LF, FiltOptions] = LFFilt2DFFT( LF, H, FiltDims, FiltOptions ) 6 | % LF = LFFilt2DFFT( LF, H, FiltDims ) 7 | % 8 | % 9 | % This filter works on 2D slices of the input light field, applying the 2D filter H to each in turn. It takes the FFT 10 | % of each slice of the input light field, multiplies by the provided magnitude response H, then calls the inverse FFT. 11 | % 12 | % The FiltDims input specifies the two dimensions along which H should be applied. The frequency-domain filter H should 13 | % match or exceed the size of the light field LF in these dimensions. If H is larger than the input light field, LF is 14 | % zero-padded to match the filter's size. If a weight channel is present in the light field it gets used during 15 | % normalization. 16 | % 17 | % See LFDemoBasicFiltLytro for example usage. 18 | % 19 | % 20 | % Inputs 21 | % 22 | % LF : The light field to be filtered 23 | % 24 | % H : The frequency-domain filter to apply, as constructed by one of the LFBuild4DFreq* functions 25 | % 26 | % FiltDims : The dimensions along which H should be applied 27 | % 28 | % [optional] FiltOptions : struct controlling filter operation 29 | % Precision : 'single' or 'double', default 'single' 30 | % Normalize : default true; when enabled the output is normalized so that darkening near image edges is 31 | % removed 32 | % MinWeight : during normalization, pixels for which the output value is not well defined (i.e. for 33 | % which the filtered weight is very low) get set to 0. MinWeight sets the threshold at which 34 | % this occurs, default is 10 * the numerical precision of the output, as returned by eps 35 | % 36 | % Outputs: 37 | % 38 | % LF : The filtered 4D light field 39 | % FiltOptions : The filter options including defaults, with an added FilterInfo field detailing the function and 40 | % time of filtering. 41 | % 42 | % See also: LFDemoBasicFiltGantry, LFDemoBasicFiltIllum, LFDemoBasicFiltLytroF01, LFBuild2DFreqFan, LFBuild2DFreqLine, 43 | % LFBuild4DFreqDualFan, LFBuild4DFreqHypercone, LFBuild4DFreqHyperfan, LFBuild4DFreqPlane, LFFilt2DFFT, LFFilt4DFFT, 44 | % LFFiltShiftSum 45 | 46 | % Part of LF Toolbox v0.4 released 12-Feb-2015 47 | % Copyright (c) 2013-2015 Donald G. Dansereau 48 | 49 | function [LF, FiltOptions] = LFFilt2DFFT( LF, H, FiltDims, FiltOptions ) 50 | 51 | FiltOptions = LFDefaultField('FiltOptions', 'Precision', 'single'); 52 | FiltOptions = LFDefaultField('FiltOptions', 'Normalize', true); 53 | FiltOptions = LFDefaultField('FiltOptions', 'MinWeight', 10*eps(FiltOptions.Precision)); 54 | %--- 55 | NColChans = size(LF,5); 56 | HasWeight = ( NColChans == 4 || NColChans == 2 ); 57 | if( HasWeight ) 58 | NColChans = NColChans-1; 59 | end 60 | 61 | %--- 62 | IterDims = 1:4; 63 | IterDims(FiltDims) = 0; 64 | IterDims = find(IterDims~=0); 65 | 66 | PermuteOrder = [IterDims, FiltDims, 5]; 67 | LF = permute(LF, PermuteOrder); 68 | 69 | LF = LFConvertToFloat(LF, FiltOptions.Precision); 70 | 71 | 72 | %--- 73 | LFSize = size(LF); 74 | SlicePaddedSize = size(H); 75 | 76 | for( IterDim1 = 1:LFSize(1) ) 77 | fprintf('.'); 78 | for( IterDim2 = 1:LFSize(2) ) 79 | CurSlice = squeeze(LF(IterDim1,IterDim2,:,:,:)); 80 | 81 | if( FiltOptions.Normalize ) 82 | if( HasWeight ) 83 | for( iColChan = 1:NColChans ) 84 | CurSlice(:,:,iColChan) = CurSlice(:,:,iColChan) .* CurSlice(:,:,end); 85 | end 86 | else % add a weight channel 87 | CurSlice(:,:,end+1) = ones(size(CurSlice(:,:,1)), FiltOptions.Precision); 88 | end 89 | end 90 | 91 | SliceSize = size(CurSlice); 92 | for( iColChan = 1:SliceSize(end) ) 93 | X = fftn(CurSlice(:,:,iColChan), SlicePaddedSize); 94 | X = X .* H; 95 | x = ifftn(X,'symmetric'); 96 | x = x(1:LFSize(3), 1:LFSize(4)); 97 | CurSlice(:,:,iColChan) = x; 98 | end 99 | 100 | if( FiltOptions.Normalize ) 101 | WeightChan = CurSlice(:,:,end); 102 | InvalidIdx = find(WeightChan < FiltOptions.MinWeight); 103 | ChanSize = numel(CurSlice(:,:,1)); 104 | for( iColChan = 1:NColChans ) 105 | CurSlice(:,:,iColChan) = CurSlice(:,:,iColChan) ./ WeightChan; 106 | CurSlice( InvalidIdx + ChanSize.*(iColChan-1) ) = 0; 107 | end 108 | end 109 | 110 | % record channel 111 | LF(IterDim1,IterDim2,:,:,:) = CurSlice(:,:,1:LFSize(5)); 112 | end 113 | end 114 | 115 | LF = max(0,LF); 116 | LF = min(1,LF); 117 | 118 | LF = ipermute(LF, PermuteOrder); 119 | 120 | %--- 121 | TimeStamp = datestr(now,'ddmmmyyyy_HHMMSS'); 122 | FiltOptions.FilterInfo = struct('mfilename', mfilename, 'time', TimeStamp, 'VersionStr', LFToolboxVersion); 123 | 124 | fprintf(' Done\n'); -------------------------------------------------------------------------------- /LFToolbox0.4/LFFilt4DFFT.m: -------------------------------------------------------------------------------- 1 | % LFFilt4DFFT -Applies a 4D frequency-domain filter using the FFT 2 | % 3 | % Usage: 4 | % 5 | % [LF, FiltOptions] = LFFilt4DFFT( LF, H, FiltOptions ) 6 | % LF = LFFilt4DFFT( LF, H ) 7 | % 8 | % 9 | % This filter works by taking the FFT of the input light field, multiplying by the provided magnitude response H, then 10 | % calling the inverse FFT. The frequency-domain filter H should match or exceed the size of the light field LF. If H is 11 | % larger than the input light field, LF is zero-padded to match the filter's size. If a weight channel is present in 12 | % the light field it gets used during normalization. 13 | % 14 | % See LFDemoBasicFiltLytro for example usage. 15 | % 16 | % 17 | % Inputs 18 | % 19 | % LF : The light field to be filtered 20 | % 21 | % H : The frequency-domain filter to apply, as constructed by one of the LFBuild4DFreq* functions 22 | % 23 | % [optional] FiltOptions : struct controlling filter operation 24 | % Precision : 'single' or 'double', default 'single' 25 | % Normalize : default true; when enabled the output is normalized so that darkening near image edges is 26 | % removed 27 | % MinWeight : during normalization, pixels for which the output value is not well defined (i.e. for 28 | % which the filtered weight is very low) get set to 0. MinWeight sets the threshold at which 29 | % this occurs, default is 10 * the numerical precision of the output, as returned by eps 30 | % 31 | % Outputs: 32 | % 33 | % LF : The filtered 4D light field 34 | % FiltOptions : The filter options including defaults, with an added FilterInfo field detailing the function and 35 | % time of filtering. 36 | % 37 | % See also: LFDemoBasicFiltGantry, LFDemoBasicFiltIllum, LFDemoBasicFiltLytroF01, LFBuild2DFreqFan, LFBuild2DFreqLine, 38 | % LFBuild4DFreqDualFan, LFBuild4DFreqHypercone, LFBuild4DFreqHyperfan, LFBuild4DFreqPlane, LFFilt2DFFT, LFFilt4DFFT, 39 | % LFFiltShiftSum 40 | 41 | % Part of LF Toolbox v0.4 released 12-Feb-2015 42 | % Copyright (c) 2013-2015 Donald G. Dansereau 43 | 44 | function [LF, FiltOptions] = LFFilt4DFFT( LF, H, FiltOptions ) 45 | 46 | FiltOptions = LFDefaultField('FiltOptions', 'Precision', 'single'); 47 | FiltOptions = LFDefaultField('FiltOptions', 'Normalize', true); 48 | FiltOptions = LFDefaultField('FiltOptions', 'MinWeight', 10*eps(FiltOptions.Precision)); 49 | 50 | %--- 51 | NColChans = size(LF,5); 52 | HasWeight = ( NColChans == 4 || NColChans == 2 ); 53 | HasColour = ( NColChans == 4 || NColChans == 3 ); 54 | 55 | if( HasWeight ) 56 | NColChans = NColChans-1; 57 | end 58 | 59 | %--- 60 | LFSize = size(LF); 61 | LFPaddedSize = size(H); 62 | 63 | LF = LFConvertToFloat(LF, FiltOptions.Precision); 64 | 65 | if( FiltOptions.Normalize ) 66 | if( HasWeight ) 67 | for( iColChan = 1:NColChans ) 68 | LF(:,:,:,:,iColChan) = LF(:,:,:,:,iColChan) .* LF(:,:,:,:,end); 69 | end 70 | else % add a weight channel 71 | LF(:,:,:,:,end+1) = ones(size(LF(:,:,:,:,1)), FiltOptions.Precision); 72 | end 73 | end 74 | 75 | SliceSize = size(LF); 76 | for( iColChan = 1:SliceSize(end) ) 77 | fprintf('.'); 78 | X = fftn(LF(:,:,:,:,iColChan), LFPaddedSize); 79 | X = X .* H; 80 | x = ifftn(X,'symmetric'); 81 | x = x(1:LFSize(1), 1:LFSize(2), 1:LFSize(3), 1:LFSize(4)); 82 | LF(:,:,:,:,iColChan) = x; 83 | end 84 | 85 | if( FiltOptions.Normalize ) 86 | WeightChan = LF(:,:,:,:,end); 87 | InvalidIdx = find(WeightChan <= FiltOptions.MinWeight); 88 | ChanSize = numel(LF(:,:,:,:,1)); 89 | for( iColChan = 1:NColChans ) 90 | LF(:,:,:,:,iColChan) = LF(:,:,:,:,iColChan) ./ WeightChan; 91 | LF( InvalidIdx + ChanSize.*(iColChan-1) ) = 0; 92 | end 93 | end 94 | 95 | LF = max(0,LF); 96 | LF = min(1,LF); 97 | 98 | %--- 99 | TimeStamp = datestr(now,'ddmmmyyyy_HHMMSS'); 100 | FiltOptions.FilterInfo = struct('mfilename', mfilename, 'time', TimeStamp, 'VersionStr', LFToolboxVersion); 101 | 102 | fprintf(' Done\n'); -------------------------------------------------------------------------------- /LFToolbox0.4/LFFiltShiftSum.m: -------------------------------------------------------------------------------- 1 | % LFFiltShiftSum - a spatial-domain depth-selective filter, with an effect similar to planar focus 2 | % 3 | % Usage: 4 | % 5 | % [ImgOut, FiltOptions, LF] = LFFiltShiftSum( LF, Slope, FiltOptions ) 6 | % ImgOut = LFFiltShiftSum( LF, Slope ) 7 | % 8 | % 9 | % This filter works by shifting all u,v slices of the light field to a common depth, then adding the slices together to 10 | % yield a single 2D output. The effect is very similar to planar focus, and by controlling the amount of shift one may 11 | % focus on different depths. If a weight channel is present in the light field it gets used during normalization. 12 | % 13 | % 14 | % See LFDemoBasicFiltLytro for example usage. 15 | % 16 | % 17 | % Inputs 18 | % 19 | % LF : The light field to be filtered 20 | % 21 | % Slope : The amount by which light field slices should be shifted, this encodes the depth at which the output will 22 | % be focused. The relationship between slope and depth depends on light field parameterization, but in 23 | % general a slope of 0 lies near the center of the captured depth of field. 24 | % 25 | % [optional] FiltOptions : struct controlling filter operation 26 | % Precision : 'single' or 'double', default 'single' 27 | % Aspect4D : aspect ratio of the light field, default [1 1 1 1] 28 | % Normalize : default true; when enabled the output is normalized so that darkening near image edges is 29 | % removed 30 | % FlattenMethod : 'Sum', 'Max' or 'Median', default 'Sum'; when the shifted light field slices are combined, 31 | % they are by default added together, but median and max can also yield useful results. 32 | % InterpMethod : default 'linear'; this is passed on to interpn to determine how shifted light field slices 33 | % are found; other useful settings are 'nearest', 'cubic' and 'spline' 34 | % ExtrapVal : default 0; when shifting light field slices, pixels falling outside the input light field 35 | % are set to this value 36 | % MinWeight : during normalization, pixels for which the output value is not well defined (i.e. for 37 | % which the filtered weight is very low) get set to 0. MinWeight sets the threshold at which 38 | % this occurs, default is 10 * the numerical precision of the output, as returned by eps 39 | % 40 | % Outputs: 41 | % 42 | % ImgOut : A 2D filtered image 43 | % FiltOptions : The filter options including defaults, with an added FilterInfo field detailing the function and 44 | % time of filtering. 45 | % LF : The 4D light field resulting from the shifting operation 46 | % 47 | % See also: LFDemoBasicFiltGantry, LFDemoBasicFiltIllum, LFDemoBasicFiltLytroF01, LFBuild2DFreqFan, LFBuild2DFreqLine, 48 | % LFBuild4DFreqDualFan, LFBuild4DFreqHypercone, LFBuild4DFreqHyperfan, LFBuild4DFreqPlane, LFFilt2DFFT, LFFilt4DFFT, 49 | % LFFiltShiftSum 50 | 51 | % Part of LF Toolbox v0.4 released 12-Feb-2015 52 | % Copyright (c) 2013-2015 Donald G. Dansereau 53 | 54 | function [ImgOut, FiltOptions, LF] = LFFiltShiftSum( LF, Slope, FiltOptions ) 55 | 56 | FiltOptions = LFDefaultField('FiltOptions', 'Precision', 'single'); 57 | FiltOptions = LFDefaultField('FiltOptions', 'Normalize', true); 58 | FiltOptions = LFDefaultField('FiltOptions', 'MinWeight', 10*eps(FiltOptions.Precision)); 59 | FiltOptions = LFDefaultField('FiltOptions', 'Aspect4D', 1); 60 | FiltOptions = LFDefaultField('FiltOptions', 'FlattenMethod', 'sum'); % 'Sum', 'Max', 'Median' 61 | FiltOptions = LFDefaultField('FiltOptions', 'InterpMethod', 'linear'); 62 | FiltOptions = LFDefaultField('FiltOptions', 'ExtrapVal', 0); 63 | 64 | if( length(FiltOptions.Aspect4D) == 1 ) 65 | FiltOptions.Aspect4D = FiltOptions.Aspect4D .* [1,1,1,1]; 66 | end 67 | 68 | LFSize = size(LF); 69 | NColChans = size(LF,5); 70 | HasWeight = ( NColChans == 4 || NColChans == 2 ); 71 | if( HasWeight ) 72 | NColChans = NColChans-1; 73 | end 74 | 75 | LF = LFConvertToFloat(LF, FiltOptions.Precision); 76 | 77 | %--- 78 | if( FiltOptions.Normalize ) 79 | if( HasWeight ) 80 | for( iColChan = 1:NColChans ) 81 | LF(:,:,:,:,iColChan) = LF(:,:,:,:,iColChan) .* LF(:,:,:,:,end); 82 | end 83 | else % add a weight channel 84 | LF(:,:,:,:,end+1) = ones(size(LF(:,:,:,:,1)), FiltOptions.Precision); 85 | end 86 | end 87 | 88 | %--- 89 | TVSlope = Slope * FiltOptions.Aspect4D(3) / FiltOptions.Aspect4D(1); 90 | SUSlope = Slope * FiltOptions.Aspect4D(4) / FiltOptions.Aspect4D(2); 91 | 92 | [vv, uu] = ndgrid(1:LFSize(3), 1:LFSize(4)); 93 | 94 | VVec = linspace(-0.5,0.5, LFSize(1)) * TVSlope*LFSize(1); 95 | UVec = linspace(-0.5,0.5, LFSize(2)) * SUSlope*LFSize(2); 96 | 97 | for( TIdx = 1:LFSize(1) ) 98 | VOffset = VVec(TIdx); 99 | for( SIdx = 1:LFSize(2) ) 100 | UOffset = UVec(SIdx); 101 | 102 | for( iChan=1:size(LF,5) ) 103 | CurSlice = squeeze(LF(TIdx, SIdx, :,:, iChan)); 104 | CurSlice = interpn(CurSlice, vv+VOffset, uu+UOffset, FiltOptions.InterpMethod, FiltOptions.ExtrapVal); 105 | LF(TIdx,SIdx, :,:, iChan) = CurSlice; 106 | end 107 | end 108 | fprintf('.'); 109 | end 110 | 111 | switch( lower(FiltOptions.FlattenMethod) ) 112 | case 'sum' 113 | ImgOut = squeeze(sum(sum(LF,1),2)); 114 | case 'max' 115 | ImgOut = squeeze(max(max(LF,[],1),[],2)); 116 | case 'median' 117 | t = reshape(LF, [prod(LFSize(1:2)), LFSize(3:end)]); 118 | ImgOut = squeeze(median(t)); 119 | otherwise 120 | error('Unrecognized method'); 121 | end 122 | 123 | %--- 124 | if( FiltOptions.Normalize ) 125 | WeightChan = ImgOut(:,:,end); 126 | InvalidIdx = find(WeightChan < FiltOptions.MinWeight); 127 | ChanSize = numel(ImgOut(:,:,1)); 128 | for( iColChan = 1:NColChans ) 129 | ImgOut(:,:,iColChan) = ImgOut(:,:,iColChan) ./ WeightChan; 130 | ImgOut( InvalidIdx + ChanSize.*(iColChan-1) ) = 0; 131 | end 132 | end 133 | 134 | TimeStamp = datestr(now,'ddmmmyyyy_HHMMSS'); 135 | FiltOptions.FilterInfo = struct('mfilename', mfilename, 'time', TimeStamp, 'VersionStr', LFToolboxVersion); -------------------------------------------------------------------------------- /LFToolbox0.4/LFFindFilesRecursive.m: -------------------------------------------------------------------------------- 1 | % LFFindFilesRecursive - Recursively searches a folder for files matching one or more patterns 2 | % 3 | % Usage: 4 | % 5 | % [AllFiles, BasePath, FolderList, PerFolderFiles] = LFFindFilesRecursive( InputPath ) 6 | % 7 | % Inputs: 8 | % 9 | % InputPath: the folder to recursively search 10 | % 11 | % Outputs: 12 | % 13 | % Allfiles : A list of all files found 14 | % BasePath : Top of the searched tree, excluding wildcards 15 | % FolderList : A list of all the folders explored 16 | % PerFolderFiles : A list of files organied by folder -- e.g. PerFolderFiles{1} are all the files 17 | % found in FolderList{1} 18 | % 19 | % Examples: 20 | % 21 | % LFFindFilesRecursive('Images') 22 | % LFFindFilesRecursive({'*.lfr','*.lfp'}) 23 | % LFFindFilesRecursive({'Images','*.lfr','*.lfp'}) 24 | % LFFindFilesRecursive('Images/*.lfr') 25 | % LFFindFilesRecursive('*.lfr') 26 | % LFFindFilesRecursive('Images/IMG_0001.LFR') 27 | % LFFindFilesRecursive('IMG_0001.LFR') 28 | % 29 | 30 | % Part of LF Toolbox v0.4 released 12-Feb-2015 31 | % Copyright (c) 2013-2015 Donald G. Dansereau 32 | 33 | function [AllFiles, BasePath, FolderList, PerFolderFiles] = LFFindFilesRecursive( InputPath, DefaultFileSpec, DefaultPath ) 34 | 35 | PerFolderFiles = []; 36 | AllFiles = []; 37 | 38 | %---Defaults--- 39 | DefaultFileSpec = LFDefaultVal( 'DefaultFileSpec', {'*'} ); 40 | DefaultPath = LFDefaultVal( 'DefaultPath', '.' ); 41 | InputPath = LFDefaultVal( 'InputPath', '.' ); 42 | 43 | PathOnly = ''; 44 | if( ~iscell(InputPath) ) 45 | InputPath = {InputPath}; 46 | end 47 | if( ~iscell(DefaultFileSpec) ) 48 | DefaultFileSpec = {DefaultFileSpec}; 49 | end 50 | InputFileSpec = DefaultFileSpec; 51 | 52 | if( exist(InputPath{1}, 'dir') ) % try interpreting first param as a folder, if it exists, grab is as such 53 | PathOnly = InputPath{1}; 54 | InputPath(1) = []; 55 | end 56 | if( numel(InputPath) > 0 ) % interpret remaining elements as filespecs 57 | % Check if the filespec includes a folder name, and crack it out as part of the input path 58 | [MorePath, Stripped, Ext] = fileparts(InputPath{1}); 59 | PathOnly = fullfile(PathOnly, MorePath); 60 | InputPath{1} = [Stripped,Ext]; 61 | InputFileSpec = InputPath; 62 | end 63 | PathOnly = LFDefaultVal('PathOnly', DefaultPath); 64 | InputPath = PathOnly; 65 | 66 | % Clean up the inputpath to omit trailing slashes 67 | while( InputPath(end) == filesep ) 68 | InputPath = InputPath(1:end-1); 69 | end 70 | BasePath = InputPath; 71 | 72 | %---Crawl folder structure locating raw lenslet images--- 73 | fprintf('Searching for files [ '); 74 | fprintf('%s ', InputFileSpec{:}); 75 | fprintf('] in %s\n', InputPath); 76 | 77 | %--- 78 | FolderList = genpath(InputPath); 79 | if( isempty(FolderList) ) 80 | error(['Input path not found... are you running from the correct folder? ' ... 81 | 'Current folder: %s'], pwd); 82 | end 83 | FolderList = textscan(FolderList, '%s', 'Delimiter', pathsep); 84 | FolderList = FolderList{1}; 85 | 86 | %---Compile a list of all files--- 87 | PerFolderFiles = cell(length(FolderList),1); 88 | for( iFileSpec=1:length(InputFileSpec) ) 89 | FilePattern = InputFileSpec{iFileSpec}; 90 | for( iFolder = 1:length(FolderList) ) 91 | 92 | %---Search each subfolder for raw lenslet files--- 93 | CurFolder = FolderList{iFolder}; 94 | CurDirList = dir(fullfile(CurFolder, FilePattern)); 95 | 96 | CurDirList = CurDirList(~[CurDirList.isdir]); 97 | CurDirList = {CurDirList.name}; 98 | PerFolderFiles{iFolder} = [PerFolderFiles{iFolder}, CurDirList]; 99 | 100 | % Prepend the current folder name for a complete path to each file 101 | % but fist strip off the leading InputPath so that all files are expressed relative to InputPath 102 | CurFolder = CurFolder(length(InputPath)+1:end); 103 | while( ~isempty(CurFolder) && CurFolder(1) == filesep ) 104 | CurFolder = CurFolder(2:end); 105 | end 106 | 107 | CurDirList = cellfun(@(Fname) fullfile(CurFolder, Fname), CurDirList, 'UniformOutput',false); 108 | 109 | AllFiles = [AllFiles; CurDirList']; 110 | 111 | end 112 | end 113 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFHistEqualize.m: -------------------------------------------------------------------------------- 1 | % LFHistEqualize - histogram-based contrast adjustment 2 | % 3 | % Usage: 4 | % 5 | % LF = LFHistEqualize( LF ) 6 | % [LF, LowerBound, UpperBound] = LFHistEqualize( LF, Cutoff_percent ) 7 | % LF = LFHistEqualize( LF, [], LowerBound, UpperBound ) 8 | % LF = LFHistEqualize(LF, Cutoff_percent, [], [], Precision) 9 | % 10 | % This function performs contrast adjustment on images based on a histogram of intensity. Colour 11 | % images are handled by building a histogram of the `value' channel in the HSV colour space. 12 | % Saturation points are computed based on a desired percentage of saturated white / black pixels. 13 | % 14 | % All parameters except LF are optional. Pass an empty array "[]" to omit a parameter. 15 | % 16 | % Inputs: 17 | % 18 | % LF : a light field or image to adjust. Integer formats are automatically converted to floating 19 | % point. The default precision is 'single', though this is controllable via the optional 20 | % Precision parameter. The function can handle most input dimensionalities as well as 21 | % colour and monochrome inputs. For example, a colour 2D image of size [Nl,Nk,3], a mono 2D 22 | % image of size [Nl,Nk], a colour 4D image of size [Nj,Ni,Nl,Nk,3], and a mono 4D image of 23 | % size [Nj,Ni,Nl,Nk] are all valid. 24 | % 25 | % Including a weight channel will result in zero-weight pixels being ignored. Weight should 26 | % be included as a fourth colour channel -- e.g. an image of size [Nl,Nk,4]. 27 | % 28 | % Optional inputs: 29 | % 30 | % Cutoff_percent : controls how much of the histogram gets saturated on both the high 31 | % and lower ends. Higher values result in more saturated black and 32 | % white pixels. The default value is 0.1%. 33 | % 34 | % LowerBound, UpperBound : bypass the histogram computation and instead directly saturate the 35 | % input image at the prescribed limits. If no bounds are provided, they 36 | % are computed from the histogram. 37 | % 38 | % Precision : 'single' or 'double' 39 | % 40 | % 41 | % Outputs: 42 | % 43 | % LF : the contrast-adjusted image, in floating point values scaled between 44 | % 0 and 1. 45 | % 46 | % LowerBound, UpperBound : the saturation points used, on the intensity scale of the input after 47 | % converting to the requested floating point precision. These are 48 | % useful in applying the same contrast adjustment to a number of light 49 | % fields, by saving and passing these bounds on subsequent function 50 | % calls. 51 | % 52 | % Example: 53 | % 54 | % load('Images/F01/IMG_0002__Decoded.mat', 'LF'); 55 | % LF = LFHistEqualize(LF); 56 | % LFDispMousePan(LF, 2); 57 | % 58 | % Run from the top level of the light field samples will load the decoded sample, apply histogram 59 | % equalization, then display the result in a shifting-perspective display with x2 magnification. 60 | % LFUtilProcessWhiteImages and LFUtilDecodeLytroFolder must be run to decode the light field. 61 | % 62 | % See also: LFUtilDecodeLytroFolder, LFUtilProcessWhiteImages, LFColourCorrect 63 | 64 | % Part of LF Toolbox v0.4 released 12-Feb-2015 65 | % Copyright (c) 2013-2015 Donald G. Dansereau 66 | 67 | function [LF, LowerBound, UpperBound] = ... 68 | LFHistEqualize(LF, Cutoff_percent, LowerBound, UpperBound, Precision) 69 | 70 | %---Defaults--- 71 | Cutoff_percent = LFDefaultVal( 'Cutoff_percent', 0.1 ); 72 | Precision = LFDefaultVal( 'Precision', 'single' ); 73 | MaxBlkSize = LFDefaultVal( 'MaxBlkSize', 10e6 ); % slice up to limit memory utilization 74 | 75 | %---Make sure LF is floating point, as required by hist function--- 76 | if( ~strcmp(class(LF), Precision) ) 77 | LF = cast(LF, Precision); 78 | end 79 | 80 | %---Flatten to a single list of N x NChans entries--- 81 | LFSize = size(LF); 82 | NDims = numel(LFSize); 83 | NChans = LFSize(end); 84 | LF = reshape(LF, [prod(LFSize(1:NDims-1)), NChans]); 85 | 86 | %---Strip out and use the weight channel if it's present--- 87 | if( NChans == 4 ) 88 | % Weight channel found, strip it out and use it 89 | LFW = LF(:,4); 90 | LF = LF(:,1:3); 91 | ValidIdx = find(LFW > 0); 92 | else 93 | LFW = []; 94 | ValidIdx = ':'; 95 | end 96 | 97 | %---Convert colour images to HSV, and operate on value only--- 98 | if( size(LF,2) == 3 ) 99 | LF = LF - min(LF(ValidIdx)); 100 | LF = LF ./ max(LF(ValidIdx)); 101 | LF = max(0,min(1,LF)); 102 | fprintf('Converting to HSV...'); 103 | 104 | for( UStart = 1:MaxBlkSize:size(LF,1) ) 105 | UStop = UStart + MaxBlkSize - 1; 106 | UStop = min(UStop, size(LF,1)); 107 | 108 | % matlab 2014b's rgb2hsv requires doubles 109 | LF(UStart:UStop,:) = cast(rgb2hsv( double(LF(UStart:UStop,:)) ), Precision); 110 | fprintf('.') 111 | end 112 | LF_hsv = LF(:,1:2); 113 | LF = LF(:,3); % operate on value channel only 114 | else 115 | LF_hsv = []; 116 | end 117 | 118 | fprintf(' Equalizing...'); 119 | %---Compute bounds from histogram--- 120 | if( ~exist('LowerBound','var') || ~exist('UpperBound','var') || ... 121 | isempty(LowerBound) || isempty(UpperBound)) 122 | [ha,xa] = hist(LF(ValidIdx), 2^16); 123 | ha = cumsum(ha); 124 | ha = ha ./ max(ha(:)); 125 | Cutoff = Cutoff_percent / 100; 126 | LowerBound = xa(find(ha >= Cutoff, 1, 'first')); 127 | UpperBound = xa(find(ha <= 1-Cutoff, 1, 'last')); 128 | end 129 | if( isempty(UpperBound) ) 130 | UpperBound = max(LF(ValidIdx)); 131 | end 132 | if( isempty(LowerBound) ) 133 | LowerBound = min(LF(ValidIdx)); 134 | end 135 | clear ValidIdx 136 | 137 | %---Apply bounds and rescale to 0-1 range--- 138 | LF = max(LowerBound, min(UpperBound, LF)); 139 | LF = (LF - LowerBound) ./ (UpperBound - LowerBound); 140 | 141 | %---Rebuild hsv, then rgb colour light field--- 142 | if( ~isempty(LF_hsv) ) 143 | LF = cat(2,LF_hsv,LF); 144 | clear LF_hsv 145 | 146 | fprintf(' Converting to RGB...'); 147 | for( UStart = 1:MaxBlkSize:size(LF,1) ) 148 | UStop = UStart + MaxBlkSize - 1; 149 | UStop = min(UStop, size(LF,1)); 150 | 151 | LF(UStart:UStop,:) = hsv2rgb(LF(UStart:UStop,:)); 152 | fprintf('.'); 153 | end 154 | end 155 | 156 | %---Return the weight channel--- 157 | if( ~isempty(LFW) ) 158 | LF(:,4) = LFW; 159 | end 160 | 161 | %---Unflatten--- 162 | LF = reshape(LF, [LFSize(1:NDims-1),NChans]); 163 | 164 | fprintf(' Done.\n'); 165 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFLytroDecodeImage.m: -------------------------------------------------------------------------------- 1 | % LFLytroDecodeImage - decode a Lytro light field from a raw lenslet image, called by LFUtilDecodeLytroFolder 2 | % 3 | % Usage: 4 | % [LF, LFMetadata, WhiteImageMetadata, LensletGridModel, DecodeOptions] = ... 5 | % LFLytroDecodeImage( InputFname, DecodeOptions ) 6 | % [LF, LFMetadata, WhiteImageMetadata, LensletGridModel, DecodeOptions] = ... 7 | % LFLytroDecodeImage( InputFname ) 8 | % 9 | % This function decodes a raw lenslet image into a 4D light field. Its purpose is to tailor the core lenslet decoding 10 | % function, LFDecodeLensletImageSimple, for use with Lytro data. It is envisioned that other camera formats will be 11 | % supported by similar functions in future. 12 | % 13 | % Supported file formats include Lytro LFP files and extracted .raw files accompanied by metadata, as extracted by using 14 | % LFP Reader v2.0.0, for example. See LFToolbox.pdf for more information. 15 | % 16 | % The white image appropriate to a light field is selected based on a white image database, and so 17 | % LFUtilProcessWhiteImages must be run before this function. 18 | % 19 | % LFUtilDecodeLytroFolder is useful for decoding multiple images. 20 | % 21 | % The optional DecodeOptions argument includes several fields defining filename patterns. These are 22 | % combined with the input LFFnameBase to build complete filenames. Filename patterns include the 23 | % placeholder '%s' to signify the position of the base filename. For example, the defualt filename 24 | % pattern for a raw input file, LensletImageFnamePattern, is '%s__frame.raw'. So a call of the 25 | % form LFLytroDecodeImage('IMG_0001') will look for the raw input file 'IMG_0001__frame.raw'. 26 | % 27 | % Inputs: 28 | % 29 | % InputFname : Filename of the input light field -- the extension is used to detect LFP or raw input. 30 | % 31 | % [optinal] DecodeOptions : all fields are optional, defaults are for LFP Reader v2.0.0 naming 32 | % .WhiteProcDataFnameExtension : Grid model from LFUtilProcessWhiteImages, default 'grid.json' 33 | % .WhiteRawDataFnameExtension : White image file extension, default '.RAW' 34 | % .WhiteImageDatabasePath : White image database, default 'Cameras/WhiteImageDatabase.mat' 35 | % 36 | % For compatibility with extracted .raw and .json files: 37 | % .MetadataFnamePattern : JSON file containing light field metadata, default '_metadata.json' 38 | % .SerialdataFnamePattern : JSON file containing serial numbers, default '_private_metadata.json' 39 | % 40 | % Outputs: 41 | % 42 | % LF : 5D array containing a 4-channel (RGB + Weight) light field, indexed in 43 | % the order [j,i,l,k, channel] 44 | % LFMetadata : Contents of the metadata and serial metadata files 45 | % WhiteImageMetadata : Conents of the white image metadata file 46 | % LensletGridModel : Lenslet grid model used to decode the light field, as constructed from 47 | % the white image by LFUtilProcessWhiteImages / LFBuildLensletGridModel 48 | % DecodeOptions : The options as applied, including any default values omitted in the input 49 | % 50 | % 51 | % Example: 52 | % 53 | % LF = LFLytroDecodeImage('Images/F01/IMG_0001__frame.raw'); 54 | % or 55 | % LF = LFLytroDecodeImage('Images/Illum/LorikeetHiding.lfp'); 56 | % 57 | % Run from the top level of the light field samples will decode the respective raw or lfp light fields. 58 | % LFUtilProcessWhiteImages must be run before decoding will work. 59 | % 60 | % See also: LFUtilDecodeLytroFolder, LFUtilProcessWhiteImages, LFDecodeLensletImageSimple, LFSelectFromDatabase 61 | 62 | % Part of LF Toolbox v0.4 released 12-Feb-2015 63 | % Copyright (c) 2013-2015 Donald G. Dansereau 64 | 65 | function [LF, LFMetadata, WhiteImageMetadata, LensletGridModel, DecodeOptions] = ... 66 | LFLytroDecodeImage( InputFname, DecodeOptions ) 67 | 68 | %---Defaults--- 69 | DecodeOptions = LFDefaultField( 'DecodeOptions', 'WhiteProcDataFnameExtension', '.grid.json' ); 70 | DecodeOptions = LFDefaultField( 'DecodeOptions', 'WhiteRawDataFnameExtension', '.RAW' ); 71 | DecodeOptions = LFDefaultField( 'DecodeOptions', 'WhiteImageDatabasePath', fullfile('Cameras','WhiteImageDatabase.mat')); 72 | % Compatibility: for loading extracted raw / json files 73 | DecodeOptions = LFDefaultField( 'DecodeOptions', 'MetadataFnamePattern', '_metadata.json' ); 74 | DecodeOptions = LFDefaultField( 'DecodeOptions', 'SerialdataFnamePattern', '_private_metadata.json' ); 75 | 76 | %--- 77 | LF = []; 78 | LFMetadata = []; 79 | WhiteImageMetadata = []; 80 | LensletGridModel = []; 81 | 82 | %---Read the LFP or raw file + external metadata--- 83 | FileExtension = InputFname(end-2:end); 84 | switch( lower(FileExtension) ) 85 | case 'raw' %---Load raw light field and metadata--- 86 | FNameBase = InputFname(1:end-4); 87 | MetadataFname = [FNameBase, DecodeOptions.MetadataFnamePattern]; 88 | SerialdataFname = [FNameBase, DecodeOptions.SerialdataFnamePattern]; 89 | fprintf('Loading lenslet image and metadata:\n\t%s\n', InputFname); 90 | LFMetadata = LFReadMetadata(MetadataFname); 91 | LFMetadata.SerialData = LFReadMetadata(SerialdataFname); 92 | 93 | switch( LFMetadata.camera.model ) 94 | case 'F01' 95 | BitPacking = '12bit'; 96 | DecodeOptions.DemosaicOrder = 'bggr'; 97 | case 'B01' 98 | BitPacking = '10bit'; 99 | DecodeOptions.DemosaicOrder = 'grbg'; 100 | end 101 | LensletImage = LFReadRaw(InputFname, BitPacking); 102 | 103 | otherwise %---Load Lytro LFP format--- 104 | fprintf('Loading LFP %s\n', InputFname ); 105 | LFP = LFReadLFP( InputFname ); 106 | if( ~isfield(LFP, 'RawImg') ) 107 | fprintf('No light field image found, skipping...\n'); 108 | return 109 | end 110 | LFMetadata = LFP.Metadata; 111 | LFMetadata.SerialData = LFP.Serials; 112 | LensletImage = LFP.RawImg; 113 | DecodeOptions.DemosaicOrder = LFP.DemosaicOrder; 114 | end 115 | 116 | %---Select appropriate white image--- 117 | DesiredCam = struct('CamSerial', LFMetadata.SerialData.camera.serialNumber, ... 118 | 'ZoomStep', LFMetadata.devices.lens.zoomStep, ... 119 | 'FocusStep', LFMetadata.devices.lens.focusStep ); 120 | DecodeOptions.WhiteImageInfo = LFSelectFromDatabase( DesiredCam, DecodeOptions.WhiteImageDatabasePath ); 121 | PathToDatabase = fileparts( DecodeOptions.WhiteImageDatabasePath ); 122 | if( isempty(DecodeOptions.WhiteImageInfo) || ~strcmp(DecodeOptions.WhiteImageInfo.CamSerial, DesiredCam.CamSerial) ) 123 | fprintf('No appropriate white image found, skipping...\n'); 124 | return 125 | end 126 | 127 | %---Display image info--- 128 | %---Check serial number--- 129 | fprintf('\nWhite image / LF Picture:\n'); 130 | fprintf('%s, %s\n', DecodeOptions.WhiteImageInfo.Fname, InputFname); 131 | fprintf('Serial:\t%s\t%s\n', DecodeOptions.WhiteImageInfo.CamSerial, DesiredCam.CamSerial); 132 | fprintf('Zoom:\t%d\t\t%d\n', DecodeOptions.WhiteImageInfo.ZoomStep, DesiredCam.ZoomStep); 133 | fprintf('Focus:\t%d\t\t%d\n\n', DecodeOptions.WhiteImageInfo.FocusStep, DesiredCam.FocusStep); 134 | 135 | %---Load white image, white image metadata, and lenslet grid parameters--- 136 | WhiteMetadataFname = fullfile(PathToDatabase, DecodeOptions.WhiteImageInfo.Fname); 137 | WhiteProcFname = LFFindLytroPartnerFile(WhiteMetadataFname, DecodeOptions.WhiteProcDataFnameExtension); 138 | WhiteRawFname = LFFindLytroPartnerFile(WhiteMetadataFname, DecodeOptions.WhiteRawDataFnameExtension); 139 | 140 | fprintf('Loading white image and metadata...\n'); 141 | LensletGridModel = LFStruct2Var(LFReadMetadata(WhiteProcFname), 'LensletGridModel'); 142 | WhiteImageMetadataWhole = LFReadMetadata( WhiteMetadataFname ); 143 | WhiteImageMetadata = WhiteImageMetadataWhole.master.picture.frameArray.frame.metadata; 144 | WhiteImageMetadata.SerialData = WhiteImageMetadataWhole.master.picture.frameArray.frame.privateMetadata; 145 | 146 | switch( WhiteImageMetadata.camera.model ) 147 | case 'F01' 148 | assert( WhiteImageMetadata.image.rawDetails.pixelPacking.bitsPerPixel == 12 ); 149 | assert( strcmp(WhiteImageMetadata.image.rawDetails.pixelPacking.endianness, 'big') ); 150 | DecodeOptions.LevelLimits = [LFMetadata.image.rawDetails.pixelFormat.black.gr, LFMetadata.image.rawDetails.pixelFormat.white.gr]; 151 | DecodeOptions.ColourMatrix = reshape(LFMetadata.image.color.ccmRgbToSrgbArray, 3,3); 152 | DecodeOptions.ColourBalance = [... 153 | LFMetadata.image.color.whiteBalanceGain.r, ... 154 | LFMetadata.image.color.whiteBalanceGain.gb, ... 155 | LFMetadata.image.color.whiteBalanceGain.b ]; 156 | DecodeOptions.Gamma = LFMetadata.image.color.gamma^0.5; 157 | BitPacking = '12bit'; 158 | 159 | case 'B01' 160 | assert( WhiteImageMetadata.image.rawDetails.pixelPacking.bitsPerPixel == 10 ); 161 | assert( strcmp(WhiteImageMetadata.image.rawDetails.pixelPacking.endianness, 'little') ); 162 | DecodeOptions.LevelLimits = [LFMetadata.image.pixelFormat.black.gr, LFMetadata.image.pixelFormat.white.gr]; 163 | DecodeOptions.ColourMatrix = reshape(LFMetadata.image.color.ccm, 3,3); 164 | DecodeOptions.ColourBalance = [1,1,1]; 165 | DecodeOptions.Gamma = 1; 166 | BitPacking = '10bit'; 167 | 168 | otherwise 169 | fprintf('Unrecognized camera model, skipping...\'); 170 | return 171 | end 172 | WhiteImage = LFReadRaw( WhiteRawFname, BitPacking ); 173 | 174 | %---Decode--- 175 | fprintf('Decoding lenslet image :'); 176 | [LF, LFWeight, DecodeOptions] = LFDecodeLensletImageSimple( LensletImage, WhiteImage, LensletGridModel, DecodeOptions ); 177 | LF(:,:,:,:,4) = LFWeight; 178 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFMatlabPathSetup.m: -------------------------------------------------------------------------------- 1 | % LFMatlabPathSetup - convenience function to add the light field toolbox to matlab's path 2 | % 3 | % It may be convenient to add this to your startup.m file. 4 | 5 | % Part of LF Toolbox v0.4 released 12-Feb-2015 6 | % Copyright (c) 2013-2015 Donald G. Dansereau 7 | 8 | function LFMatlabPathSetup 9 | 10 | % Find the path to this script, and use it as the base path 11 | LFToolboxPath = fileparts(mfilename('fullpath')); 12 | 13 | fprintf('Adding paths for LF Toolbox '); 14 | addpath( fullfile(LFToolboxPath) ); 15 | addpath( fullfile(LFToolboxPath, 'SupportFunctions') ); 16 | addpath( fullfile(LFToolboxPath, 'SupportFunctions', 'CameraCal') ); 17 | fprintf('%s, done.\n', LFToolboxVersion); -------------------------------------------------------------------------------- /LFToolbox0.4/LFReadGantryArray.m: -------------------------------------------------------------------------------- 1 | % LFReadGantryArray - load gantry-style light field, e.g. the Stanford light fields at lightfield.stanford.edu 2 | % 3 | % Usage: 4 | % 5 | % LF = LFReadGantryArray( InputPath, DecodeOptions ) 6 | % 7 | % To use, download and unzip an image archive from the Stanford light field archive, and pass this function the path to 8 | % the unzipped files. All inputs are optional, by default the light field is loaded from the current directory. 9 | % DecodeOptions.UVScale and DecodeOptions.UVLimit allow the input images to be scaled, either by the constant factor 10 | % UVScale, or to achieve the maximum u,v image size specified by UVLimit. If both UVScale and UVLimit are specified, the 11 | % one resulting in smaller images is applied. 12 | % 13 | % The defaults are all set to load Stanford Lego Gantry light fields, and must be adjusted for differently sized or 14 | % ordered light fields. 15 | % 16 | % Inputs : 17 | % 18 | % InputPath : path to folder of image files, e.g. as obtained by decompressing a Stanford light field 19 | % 20 | % DecodeOptions : 21 | % UVScale : constant scaling factor applied to each input image; default: 1 22 | % UVLimit : scale is adjusted to ensure a maximum image dimension of DecodeOptions.UVLimit 23 | % Order : 'RowMajor' or 'ColumnMajor', specifies the order in which images appear when sorted 24 | % alphabetically; default: 'RowMajor' 25 | % STSize : Size of the array of images; default: [17, 17] 26 | % FnamePattern : Pattern used to locate input file, using standard wildcards; default '*.png' 27 | % 28 | % Outputs: 29 | % 30 | % LF : 5D array containing a 3-channel (RGB) light field, indexed in the order [j,i,l,k, colour] 31 | % DecodeOptions : Reflects the parameters as applied, including the UVScale resulting from UVLimit 32 | % 33 | % 34 | % Example 1: 35 | % 36 | % After unzipping the LegoKnights Stanford light fields into '~/Data/Stanford/LegoKnights/rectified', the following 37 | % reads the light field at full resolution, yielding a 17 x 17 x 1024 x 1024 x 3 array, occupying 909 MBytes of RAM: 38 | % 39 | % LF = LFReadGantryArray('~/Data/Stanford/LegoKnights/rectified'); 40 | % 41 | % Example 2: 42 | % 43 | % As above, but scales each image to a maximum dimension of 256 pixels, yielding a 17 x 17 x 256 x 256 x 3 array. 44 | % LFDIspMousePan then displays the light field, click and pan around to view the light field. 45 | % 46 | % LF = LFReadGantryArray('~/Data/Stanford/LegoKnights/rectified', struct('UVLimit', 256)); 47 | % LFDispMousePan(LF) 48 | % 49 | % Example 3: 50 | % 51 | % A few of the Stanford "Gantry" (not "Lego Gantry") light fields follow a lawnmower pattern. These can be read and 52 | % adjusted as follows: 53 | % 54 | % LF = LFReadGantryArray('humvee-tree', struct('STSize', [16,16])); 55 | % LF(1:2:end,:,:,:,:) = LF(1:2:end,end:-1:1,:,:,:); 56 | 57 | % See also: LFDispMousePan, LFDispVidCirc 58 | 59 | % Part of LF Toolbox v0.4 released 12-Feb-2015 60 | % Copyright (c) 2013-2015 Donald G. Dansereau 61 | 62 | function [LF, DecodeOptions] = LFReadGantryArray( InputPath, DecodeOptions ) 63 | 64 | InputPath = LFDefaultVal('InputPath', '.'); 65 | DecodeOptions = LFDefaultField('DecodeOptions','UVScale', 1); 66 | DecodeOptions = LFDefaultField('DecodeOptions','UVLimit', []); 67 | DecodeOptions = LFDefaultField('DecodeOptions','STSize', [17,17]); 68 | DecodeOptions = LFDefaultField('DecodeOptions','FnamePattern', '*.png'); 69 | DecodeOptions = LFDefaultField('DecodeOptions','Order', 'RowMajor'); 70 | 71 | %---Gather info--- 72 | FList = dir(fullfile(InputPath, DecodeOptions.FnamePattern)); 73 | if( isempty(FList) ) 74 | error('No files found'); 75 | end 76 | 77 | NumImgs = length(FList); 78 | assert( NumImgs == prod(DecodeOptions.STSize), 'Unexpected image count: expected %d x %d = %d found %d', ... 79 | DecodeOptions.STSize(1), DecodeOptions.STSize(2), prod(DecodeOptions.STSize), NumImgs ); 80 | 81 | %---Get size, scaling info from first file, assuming all are same size--- 82 | Img = imread(fullfile(InputPath, FList(1).name)); 83 | ImgClass = class(Img); 84 | UVSizeIn = size(Img); 85 | 86 | if( ~isempty(DecodeOptions.UVLimit) ) 87 | UVMinScale = min(DecodeOptions.UVLimit ./ UVSizeIn(1:2)); 88 | DecodeOptions.UVScale = min(DecodeOptions.UVScale, UVMinScale); 89 | end 90 | Img = imresize(Img, DecodeOptions.UVScale); 91 | 92 | UVSize = size(Img); 93 | TSize = DecodeOptions.STSize(2); 94 | SSize = DecodeOptions.STSize(1); 95 | VSize = UVSize(1); 96 | USize = UVSize(2); 97 | 98 | %---Allocate mem--- 99 | LF = zeros(TSize, SSize, VSize,USize, 3, ImgClass); 100 | LF(1,1,:,:,:) = Img; 101 | 102 | switch( lower(DecodeOptions.Order) ) 103 | case 'rowmajor' 104 | [SIdx,TIdx] = ndgrid( 1:SSize, 1:TSize ); 105 | case 'columnmajor' 106 | [TIdx,SIdx] = ndgrid( 1:TSize, 1:SSize ); 107 | otherwise 108 | error( 'Unrecognized image order' ); 109 | end 110 | 111 | %---Load and scale images--- 112 | fprintf('Loading %d images', NumImgs); 113 | for(i=2:NumImgs) 114 | if( mod(i, ceil(length(FList)/10)) == 0 ) 115 | fprintf('.'); 116 | end 117 | 118 | Img = imread(fullfile(InputPath, FList(i).name)); 119 | Img = imresize(Img, DecodeOptions.UVScale); 120 | 121 | LF(TIdx(i),SIdx(i),:,:,:) = Img; 122 | end 123 | fprintf(' done\n'); -------------------------------------------------------------------------------- /LFToolbox0.4/LFReadLFP.m: -------------------------------------------------------------------------------- 1 | % LFReadLFP - Load a lytro LFP / LFR file 2 | % 3 | % Usage: 4 | % [LFP, ExtraSections] = LFReadLFP( Fname ) 5 | % 6 | % The Lytro LFP is a container format and may contain one of several types of data. The file extension varies based on 7 | % the source of the files, with exported files, on-camera files and image library files variously taking on the 8 | % extensions lfp, lfr, LFP and LFR. 9 | % 10 | % This function loads all the sections of an LFP and interprets those that it recognizes. Recognized sections include 11 | % thumbnails and focal stacks, raw light field and white images, metadata and serial data. If more than one section of 12 | % the same type appears, a cell array is constructed in the output struct -- this is the case for focal stacks, for 13 | % example. Files generated using Lytro Desktop 4.0 and 3.0 are supported. 14 | % 15 | % Additional output information includes the appropriate demosaic order for raw light field images, and the size of raw 16 | % images. 17 | % 18 | % Unrecognized sections are returned in the ExtraSections output argument. 19 | % 20 | % This function is based in part on Nirav Patel's lfpsplitter.c and Doug Kelley's read_lfp; Thanks to Michael Tao for 21 | % help and samples for decoding Illum imagery. 22 | % 23 | % Inputs : 24 | % Fname : path to an input LFP file 25 | % 26 | % Outputs: 27 | % LFP : Struct containing decoded LFP sections and supporting information, which may include one or more of 28 | % .Jpeg : Thumbnails, focal stacks -- see LFUtilExtractLFPThumbs for saving these to disk 29 | % .RawImg : Raw light field image 30 | % .WhiteImg : White image bundled into Illum LFP 31 | % .Metadata, .Serials : Information about the image and camera 32 | % .DemosaicOrder : The appropriate parameter to pass to Matlab's "demosaic" to debayer a RawImg 33 | % .ImgSize : Size of RawImg 34 | % 35 | % ExtraSections : Struct array containing unrecognized LFP sections 36 | % .Data : Buffer of chars containing the section's uninterpreted data block 37 | % .SectType : Descriptive name for the section, e.g. "hotPixelRef" 38 | % .Sha1 : Unique hash identifying the section 39 | % .SectHeader : Header bytes identifying the section as a table of contents or data 40 | % 41 | % See also: LFUtilExtractLFPThumbs, LFUtilUnpackLytroArchive, LFUtilDecodeLytroFolder 42 | 43 | % Part of LF Toolbox v0.4 released 12-Feb-2015 44 | % Copyright (c) 2013-2015 Donald G. Dansereau 45 | 46 | function [LFP, ExtraSections] = LFReadLFP( Fname ) 47 | 48 | %---Consts--- 49 | LFPConsts.LFPHeader = hex2dec({'89', '4C', '46', '50', '0D', '0A', '1A', '0A', '00', '00', '00', '01'}); % 12-byte LFPSections header 50 | LFPConsts.SectHeaderLFM = hex2dec({'89', '4C', '46', '4D', '0D', '0A', '1A', '0A'})'; % header for table of contents 51 | LFPConsts.SectHeaderLFC = hex2dec({'89', '4C', '46', '43', '0D', '0A', '1A', '0A'})'; % header for content section 52 | LFPConsts.SecHeaderPaddingLen = 4; 53 | LFPConsts.Sha1Length = 45; 54 | LFPConsts.ShaPaddingLen = 35; % Sha1 codes are followed by 35 null bytes 55 | 56 | %---Break out recognized sections--- 57 | KnownSectionTypes = { ... 58 | ... % Lytro Desktop 4 59 | 'Jpeg', 'picture.accelerationArray.vendorContent.imageArray.imageRef', 'jpeg'; ... 60 | 'Jpeg', 'thumbnails.imageRef', 'jpeg'; ... 61 | 'RawImg', 'frames.frame.imageRef', 'raw'; ... 62 | 'WhiteImg', 'frames.frame.modulationDataRef', 'raw';... 63 | 'Metadata', 'frames.frame.metadataRef', 'json'; ... 64 | 'Serials', 'frames.frame.privateMetadataRef', 'json'; ... 65 | ... % Earlier Lytro Desktop versions 66 | 'RawImg', 'picture.frameArray.frame.imageRef', 'raw'; ... 67 | 'Metadata', 'picture.frameArray.frame.metadataRef', 'json'; ... 68 | 'Serials', 'picture.frameArray.frame.privateMetadataRef', 'json'; ... 69 | }; 70 | 71 | %--- 72 | ExtraSections = []; 73 | LFP = []; 74 | InFile=fopen(Fname, 'rb'); 75 | 76 | %---Check for the magic header--- 77 | HeaderBytes = fread( InFile, length(LFPConsts.LFPHeader), 'uchar' ); 78 | if( (length(HeaderBytes)~=length(LFPConsts.LFPHeader)) || ~all( HeaderBytes == LFPConsts.LFPHeader ) ) 79 | fclose(InFile); 80 | fprintf( 'Unrecognized file type\n' ); 81 | return 82 | end 83 | 84 | %---Confirm headerlength bytes--- 85 | HeaderLength = fread(InFile,1,'uint32','ieee-be'); 86 | assert( HeaderLength == 0, 'Unexpected length at top-level header' ); 87 | 88 | %---Read each section--- 89 | NSections = 0; 90 | TOCIdx = []; 91 | while( ~feof(InFile) ) 92 | NSections = NSections+1; 93 | LFPSections( NSections ) = ReadSection( InFile, LFPConsts ); 94 | 95 | %---Mark the table of contents section--- 96 | if( all( LFPSections( NSections ).SectHeader == LFPConsts.SectHeaderLFM ) ) 97 | assert( isempty(TOCIdx), 'Found more than one LFM metadata section' ); 98 | TOCIdx = NSections; 99 | end 100 | end 101 | fclose( InFile ); 102 | 103 | %---Decode the table of contents--- 104 | assert( ~isempty(TOCIdx), 'Found no LFM metadata sections' ); 105 | TOC = LFReadMetadata( LFPSections(TOCIdx).Data ); 106 | LFPSections(TOCIdx).SectType = 'TOC'; 107 | 108 | %---find all sha1 refs in TOC--- 109 | TocData = LFPSections(TOCIdx).Data; 110 | ShaIdx = strfind( TocData, 'sha1-' ); 111 | SeparatorIdx = find( TocData == ':' ); 112 | EolIdx = find( TocData == 10 ); 113 | 114 | for( iSha = 1:length(ShaIdx) ) 115 | LabelStopIdx = SeparatorIdx( find( SeparatorIdx < ShaIdx(iSha), 1, 'last' ) ); 116 | LabelStartIdx = EolIdx( find( EolIdx < LabelStopIdx, 1, 'last' ) ); 117 | ShaEndIdx = EolIdx( find( EolIdx > ShaIdx(iSha), 1, 'first' ) ); 118 | CurLabel = TocData(LabelStartIdx:LabelStopIdx); 119 | CurSha = TocData(LabelStopIdx:ShaEndIdx); 120 | 121 | CurLabel = strsplit(CurLabel, '"'); 122 | CurSha = strsplit(CurSha, '"'); 123 | 124 | CurLabel = CurLabel{2}; 125 | CurSha = CurSha{2}; 126 | 127 | SectNames{iSha} = CurLabel; 128 | SectIDs{iSha} = CurSha; 129 | end 130 | 131 | %---Apply section labels--- 132 | for( iSect = 1:length(SectNames) ) 133 | CurSectSHA = SectIDs{iSect}; 134 | MatchingSectIdx = find( strcmp( CurSectSHA, {LFPSections.Sha1} ) ); 135 | if( ~isempty(MatchingSectIdx) ) 136 | LFPSections(MatchingSectIdx).SectType = SectNames{iSect}; 137 | end 138 | end 139 | 140 | for( iSect = 1:size(KnownSectionTypes,1) ) 141 | FoundField = true; 142 | while(FoundField) 143 | [LFP, LFPSections, TOC, FoundField] = ExtractNamedField(LFP, LFPSections, TOC, KnownSectionTypes(iSect,:) ); 144 | end 145 | end 146 | ExtraSections = LFPSections; 147 | 148 | %---unpack the image(s)--- 149 | if( isfield( LFP, 'RawImg') ) 150 | LFP.ImgSize = [LFP.Metadata.image.width, LFP.Metadata.image.height]; 151 | switch( LFP.Metadata.camera.model ) 152 | case 'F01' 153 | assert( LFP.Metadata.image.rawDetails.pixelPacking.bitsPerPixel == 12 ); 154 | assert( strcmp(LFP.Metadata.image.rawDetails.pixelPacking.endianness, 'big') ); 155 | LFP.RawImg = LFUnpackRawBuffer( LFP.RawImg, '12bit', LFP.ImgSize )'; 156 | LFP.DemosaicOrder = 'bggr'; 157 | 158 | case 'ILLUM' 159 | assert( LFP.Metadata.image.pixelPacking.bitsPerPixel == 10 ); 160 | assert( strcmp(LFP.Metadata.image.pixelPacking.endianness, 'little') ); 161 | LFP.RawImg = LFUnpackRawBuffer( LFP.RawImg, '10bit', LFP.ImgSize )'; 162 | if( isfield( LFP, 'WhiteImg' ) ) 163 | LFP.WhiteImg = LFUnpackRawBuffer( LFP.WhiteImg, '10bit', LFP.ImgSize )'; 164 | end 165 | LFP.DemosaicOrder = 'grbg'; 166 | 167 | otherwise 168 | warning('Unrecognized camera model'); 169 | return 170 | end 171 | end 172 | 173 | end 174 | 175 | % -------------------------------------------------------------------- 176 | function LFPSect = ReadSection( InFile, LFPConsts ) 177 | LFPSect.SectHeader = fread(InFile, length(LFPConsts.SectHeaderLFM), 'uchar')'; 178 | Padding = fread(InFile, LFPConsts.SecHeaderPaddingLen, 'uint8'); % skip padding 179 | 180 | SectLength = fread(InFile, 1, 'uint32', 'ieee-be'); 181 | LFPSect.Sha1 = char(fread(InFile, LFPConsts.Sha1Length, 'uchar')'); 182 | Padding = fread(InFile, LFPConsts.ShaPaddingLen, 'uint8'); % skip padding 183 | 184 | LFPSect.Data = char(fread(InFile, SectLength, 'uchar'))'; 185 | 186 | while( 1 ) 187 | Padding = fread(InFile, 1, 'uchar'); 188 | if( feof(InFile) || (Padding ~= 0) ) 189 | break; 190 | end 191 | end 192 | if ~feof(InFile) 193 | fseek( InFile, -1, 'cof'); % rewind one byte 194 | end 195 | 196 | end 197 | 198 | % -------------------------------------------------------------------- 199 | function [LFP, LFPSections, TOC, FoundField] = ExtractNamedField(LFP, LFPSections, TOC, FieldInfo) 200 | FoundField = false; 201 | 202 | FieldName = FieldInfo{1}; 203 | JsonName = FieldInfo{2}; 204 | FieldFormat = FieldInfo{3}; 205 | 206 | JsonTokens = strsplit(JsonName, '.'); 207 | TmpToc = TOC; 208 | if( ~iscell(JsonTokens) ) 209 | JsonTokens = {JsonTokens}; 210 | end 211 | for( i=1:length(JsonTokens) ) 212 | if( ~isfield(TmpToc, JsonTokens{i}) || isempty([TmpToc.(JsonTokens{i})]) ) 213 | return; 214 | end 215 | TmpToc = TmpToc.(JsonTokens{i}); % takes the first one in the case of an array 216 | end 217 | 218 | FieldIdx = find( strcmp( TmpToc, {LFPSections.Sha1} ) ); 219 | if( ~isempty(FieldIdx) ) 220 | SubField = struct('type','.','subs',FieldName); 221 | 222 | %--- detect image array and force progress by removing the currently-processed entry --- 223 | S = struct('type','.','subs',JsonTokens(1:end-1)); 224 | t = subsref( TOC, S ); 225 | ArrayLen = length(t); 226 | if( (isstruct(t) && ArrayLen>1) || isfield( LFP, FieldName ) ) 227 | S(end+1).type = '()'; 228 | S(end).subs = {1}; 229 | TOC = subsasgn( TOC, S, [] ); 230 | 231 | % Add an indexing subfield for image arrays 232 | SubField(end+1).type = '{}'; 233 | SubField(end).subs = {ArrayLen}; 234 | end 235 | 236 | %---Copy the data into the LFP struct--- 237 | LFP = subsasgn( LFP, SubField, LFPSections(FieldIdx).Data ); 238 | LFPSections = LFPSections([1:FieldIdx-1, FieldIdx+1:end]); 239 | 240 | %---Decode JSON-formatted sections--- 241 | switch( FieldFormat ) 242 | case 'json' 243 | LFP.(FieldName) = LFReadMetadata( LFP.(FieldName) ); 244 | end 245 | 246 | FoundField = true; 247 | end 248 | end 249 | 250 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFReadRaw.m: -------------------------------------------------------------------------------- 1 | % LFReadRaw - Reads 8, 10, 12 and 16-bit raw image files 2 | % 3 | % Usage: 4 | % 5 | % Img = LFReadRaw( Fname ) 6 | % Img = LFReadRaw( Fname, BitPacking, ImgSize ) 7 | % Img = LFReadRaw( Fname, [], ImgSize ) 8 | % 9 | % There is no universal `RAW' file format. This function reads a few variants, including the 12-bit and 10-bit files 10 | % commonly employed in Lytro cameras, and the 16-bit files produced by some third-party LFP extraction tools. The output 11 | % is always an array of type uint16, except for 8-bit files which produce an 8-bit output. 12 | % 13 | % Raw images may be converted to more portable formats, including .png, using an external tool such as the 14 | % cross-platform ImageMagick tool. 15 | % 16 | % Inputs : 17 | % 18 | % Fname : path to raw file to read 19 | % 20 | % [optional] BitPacking : one of '12bit', '10bit' or '16bit'; default is '12bit' 21 | % 22 | % [optional] ImgSize : a 2D vector defining the size of the image, in pixels. The default value varies according to 23 | % the value of 'BitPacking', to correspond to commonly-found Lytro file formats: 12 bit images are employed by the 24 | % Lytro F01, producing images of size 3280x3280, while 10-bit images are produced by the Illum at a resolutio of 25 | % 7728x5368; 16-bit images default to 3280x3280. 26 | % 27 | % Outputs: 28 | % 29 | % Img : an array of uint16 gray levels. No demosaicing (decoding Bayer pattern) is performed. 30 | % 31 | % See also: LFReadLFP, LFDecodeLensletImageSimple, demosaic 32 | 33 | % Part of LF Toolbox v0.4 released 12-Feb-2015 34 | % Copyright (c) 2013-2015 Donald G. Dansereau 35 | 36 | function Img = LFReadRaw( Fname, BitPacking, ImgSize ) 37 | 38 | %---Defaults--- 39 | BitPacking = LFDefaultVal( 'BitPacking', '12bit' ); 40 | 41 | switch( BitPacking ) 42 | case '8bit' 43 | ImgSize = LFDefaultVal( 'ImgSize', [3280,3280] ); 44 | BuffSize = prod(ImgSize); 45 | 46 | case '12bit' 47 | ImgSize = LFDefaultVal( 'ImgSize', [3280,3280] ); 48 | BuffSize = prod(ImgSize) * 12/8; 49 | 50 | case '10bit' 51 | ImgSize = LFDefaultVal( 'ImgSize', [7728, 5368] ); 52 | BuffSize = prod(ImgSize) * 10/8; 53 | 54 | case '16bit' 55 | ImgSize = LFDefaultVal( 'ImgSize', [3280,3280] ); 56 | BuffSize = prod(ImgSize) * 16/8; 57 | 58 | otherwise 59 | error('Unrecognized bit packing format'); 60 | end 61 | 62 | %---Read and unpack--- 63 | f = fopen( Fname ); 64 | Img = fread( f, BuffSize, 'uchar' ); 65 | Img = LFUnpackRawBuffer( Img, BitPacking, ImgSize )'; % note the ' is necessary to get the rotation right 66 | fclose( f ); 67 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFRecenterIntrinsics.m: -------------------------------------------------------------------------------- 1 | % LFRecenterIntrinsics - Recenter a light field intrinsic matrix 2 | % 3 | % Usage: 4 | % H = LFRecenterIntrinsics( H, LFSize ) 5 | % 6 | % The recentering works by forcing the central sample in a light field of LFSize samples to 7 | % correspond to the ray [s,t,u,v] = 0. Note that 1-based indexing is assumed in [i,j,k,l]. 8 | 9 | % Part of LF Toolbox v0.4 released 12-Feb-2015 10 | % Copyright (c) 2013-2015 Donald G. Dansereau 11 | 12 | function H = LFRecenterIntrinsics( H, LFSize ) 13 | 14 | CenterRay = [(LFSize([2,1,4,3])-1)/2 + 1, 1]'; % note indices start at 1 15 | H(1:4,5) = 0; 16 | Decentering = H * CenterRay; 17 | H(1:4,5) = -Decentering(1:4); 18 | 19 | end 20 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFToolbox.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazirbas/light-field-toolbox/28637489f87d37dcd55d71436be5772413769397/LFToolbox0.4/LFToolbox.pdf -------------------------------------------------------------------------------- /LFToolbox0.4/LFUtilCalLensletCam.m: -------------------------------------------------------------------------------- 1 | % LFUtilCalLensletCam - calibrate a lenslet-based light field camera 2 | % 3 | % Usage: 4 | % 5 | % LFUtilCalLensletCam 6 | % LFUtilCalLensletCam( Inputpath ) 7 | % LFUtilCalLensletCam( InputPath, CalOptions ) 8 | % LFUtilProcessCalibrations( [], CalOptions ) 9 | % 10 | % All parameters are optional and take on default values as set in the "Defaults" section at the top 11 | % of the implementation. As such, this can be called as a function or run directly by editing the 12 | % code. When calling as a function, pass an empty array "[]" to omit a parameter. 13 | % 14 | % This function recursively crawls through a folder identifying decoded light field images and 15 | % performing a calibration based on those images. It follows the calibration procedure described in: 16 | % 17 | % D. G. Dansereau, O. Pizarro, and S. B. Williams, "Decoding, calibration and rectification for 18 | % lenslet-based plenoptic cameras," in Computer Vision and Pattern Recognition (CVPR), IEEE 19 | % Conference on. IEEE, Jun 2013. 20 | % 21 | % Minor differences from the paper: camera parameters are automatically initialized, so no prior 22 | % knowledge of the camera's parameters is required; the free intrinsic parameters have been reduced 23 | % by two: H(3:4,5) were previously redundant with the camera's extrinsics, and are now automatically 24 | % centered; and the light field indices [i,j,k,l] are 1-based in this implementation, and not 25 | % 0-based as described in the paper. 26 | % 27 | % The calibration produced by this process is saved in a JSON file, by default named 'CalInfo.json', 28 | % in the top-level folder of the calibration images. The calibration includes a 5x5 homogeneous 29 | % intrinsic matrix EstCamIntrinsicsH, a 5-element vector EstCamDistortionV describing its distortion 30 | % parameters, and the lenslet grid model formed from the white image used to decode the 31 | % checkerboard images. Taken together, these relate light field indices [i,j,k,l] to spatial rays 32 | % [s,t,u,v], and can be utilized to rectify light fields, as demonstrated in LFUtilDecodeLytroFolder 33 | % / LFCalRectifyLF. 34 | % 35 | % The input light fields are ideally of a small checkerboard (order mm per square), taken at close 36 | % range, and over a diverse set of poses to maximize the quality of the calibration. The 37 | % checkerboard light field images should be decoded without rectification, and colour correction is 38 | % not required. 39 | % 40 | % Calibration is described in more detail in LFToolbox.pdf, including links to example datasets and 41 | % a walkthrough of a calibration process. 42 | % 43 | % Inputs -- all are optional, see code below for default values : 44 | % 45 | % InputPath : Path to folder containing decoded checkerboard images -- note the function 46 | % operates recursively, i.e. it will search sub-folders. 47 | % 48 | % CalOptions : struct controlling calibration parameters 49 | % .ExpectedCheckerSize : Number of checkerboard corners, as recognized by the automatic 50 | % corner detector; edge corners are not recognized, so a standard 51 | % 8x8-square chess board yields 7x7 corners 52 | % .ExpectedCheckerSpacing_m : Physical extents of the checkerboard, in meters 53 | % .LensletBorderSize : Number of pixels to skip around the edges of lenslets; a low 54 | % value of 1 or 0 is generally appropriate, as invalid pixels are 55 | % automatically skipped 56 | % .SaveResult : Set to false to perform a "dry run" 57 | % .ShowDisplay : Enables various displays throughout the calibration process 58 | % .ForceRedoCornerFinding : Forces the corner finding procedure to run, overwriting existing 59 | % results 60 | % .ForceRedoInit : Forces the parameter initialization step to run, overwriting 61 | % existing results 62 | % .OptTolX : Determines when the optimization process terminates. When the 63 | % estimted parameter values change by less than this amount, the 64 | % optimization terminates. See the Matlab documentation on lsqnonlin, 65 | % option `TolX' for more information. The default value of 5e-5 is set 66 | % within the LFCalRefine function; a value of 0 means the optimization 67 | % never terminates based on this criterion. 68 | % .OptTolFun : Similar to OptTolX, except this tolerance deals with the error value. 69 | % This corresponds to Matlab's lsqnonlin option `TolFun'. The default 70 | % value of 0 is set within the LFCalRefine function, and means the 71 | % optimization never terminates based on this criterion. 72 | % 73 | % Output takes the form of saved checkerboard info and calibration files. 74 | % 75 | % Example : 76 | % 77 | % LFUtilCalLensletCam('.', ... 78 | % struct('ExpectedCheckerSize', [8,6], 'ExpectedCheckerSpacing_m', 1e-3*[35.1, 35.0])) 79 | % 80 | % Run from within the top-level path of a set of decoded calibration images of an 8x6 checkerboard 81 | % of dimensions 35.1x35.0 mm, will carry out all the stages of a calibration. See the toolbox 82 | % documentation for a more complete example. 83 | % 84 | % See also: LFCalFindCheckerCorners, LFCalInit, LFCalRefine, LFUtilDecodeLytroFolder, LFSelectFromDatabase 85 | 86 | % Part of LF Toolbox v0.4 released 12-Feb-2015 87 | % Copyright (c) 2013-2015 Donald G. Dansereau 88 | 89 | function LFUtilCalLensletCam( InputPath, CalOptions ) 90 | 91 | %---Tweakables--- 92 | InputPath = LFDefaultVal('InputPath', '.'); 93 | 94 | CalOptions = LFDefaultField( 'CalOptions', 'ExpectedCheckerSize', [19, 19] ); 95 | CalOptions = LFDefaultField( 'CalOptions', 'ExpectedCheckerSpacing_m', [3.61, 3.61] * 1e-3 ); 96 | CalOptions = LFDefaultField( 'CalOptions', 'LensletBorderSize', 1 ); 97 | CalOptions = LFDefaultField( 'CalOptions', 'SaveResult', true ); 98 | CalOptions = LFDefaultField( 'CalOptions', 'ForceRedoCornerFinding', false ); 99 | CalOptions = LFDefaultField( 'CalOptions', 'ForceRedoInit', false ); 100 | CalOptions = LFDefaultField( 'CalOptions', 'ShowDisplay', true ); 101 | CalOptions = LFDefaultField( 'CalOptions', 'CalInfoFname', 'CalInfo.json' ); 102 | 103 | %---Check for previously started calibration--- 104 | CalInfoFname = fullfile(InputPath, CalOptions.CalInfoFname); 105 | if( ~CalOptions.ForceRedoInit && exist(CalInfoFname, 'file') ) 106 | fprintf('---File %s already exists\n Loading calibration state and options\n', CalInfoFname); 107 | CalOptions = LFStruct2Var( LFReadMetadata(CalInfoFname), 'CalOptions' ); 108 | else 109 | CalOptions.Phase = 'Start'; 110 | end 111 | 112 | RefineComplete = false; % always at least refine once 113 | 114 | %---Step through the calibration phases--- 115 | while( ~strcmp(CalOptions.Phase, 'Refine') || ~RefineComplete ) 116 | switch( CalOptions.Phase ) 117 | 118 | case 'Start' 119 | %---Find checkerboard corners--- 120 | CalOptions.Phase = 'Corners'; 121 | CalOptions = LFCalFindCheckerCorners( InputPath, CalOptions ); 122 | 123 | case 'Corners' 124 | %---Initialize calibration process--- 125 | CalOptions.Phase = 'Init'; 126 | CalOptions = LFCalInit( InputPath, CalOptions ); 127 | 128 | if( CalOptions.ShowDisplay ) 129 | LFFigure(2); 130 | clf 131 | LFCalDispEstPoses( InputPath, CalOptions, [], [0.7,0.7,0.7] ); 132 | end 133 | 134 | case 'Init' 135 | %---First step of optimization process will exclude distortion--- 136 | CalOptions.Phase = 'NoDistort'; 137 | CalOptions = LFCalRefine( InputPath, CalOptions ); 138 | 139 | if( CalOptions.ShowDisplay ) 140 | LFFigure(2); 141 | LFCalDispEstPoses( InputPath, CalOptions, [], [0,0.7,0] ); 142 | end 143 | 144 | case 'NoDistort' 145 | %---Next step of optimization process adds distortion--- 146 | CalOptions.Phase = 'WithDistort'; 147 | CalOptions = LFCalRefine( InputPath, CalOptions ); 148 | if( CalOptions.ShowDisplay ) 149 | LFFigure(2); 150 | LFCalDispEstPoses( InputPath, CalOptions, [], [0,0,1] ); 151 | end 152 | 153 | otherwise 154 | %---Subsequent calls refine the estimate--- 155 | CalOptions.Phase = 'Refine'; 156 | CalOptions = LFCalRefine( InputPath, CalOptions ); 157 | RefineComplete = true; 158 | if( CalOptions.ShowDisplay ) 159 | LFFigure(2); 160 | LFCalDispEstPoses( InputPath, CalOptions, [], [1,0,0] ); 161 | end 162 | end 163 | end 164 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFUtilExtractLFPThumbs.m: -------------------------------------------------------------------------------- 1 | % LFUtilExtractLFPThumbs - extract thumbnails from LFP files and write to disk 2 | % 3 | % Usage: 4 | % 5 | % LFUtilExtractLFPThumbs 6 | % LFUtilExtractLFPThumbs( InputPath ) 7 | % 8 | % This extracts the thumbnail preview and focal stack images from LFR and LFP files, and is useful in providing a 9 | % preview, e.g. when copying files directly from an Illum camera. 10 | % 11 | % Inputs -- all are optional : 12 | % 13 | % InputPath : Path / filename pattern for locating LFP files. The function will move recursively through a tree, 14 | % matching one or more filename patterns. See LFFindFilesRecursive for a full description. 15 | % 16 | % The default input path is {'.', '*.LFP','*.LFR','*.lfp','*.lfr'}, i.e. the current folder, recursively searching 17 | % for all files matching uppercase and lowercase 'LFP' and 'LFR' extensions. 18 | % 19 | % Examples: 20 | % 21 | % LFUtilExtractLFPThumbs 22 | % 23 | % Will extract thumbnails from all LFP and LFR images in the current folder and its subfolders. 24 | % 25 | % The following are also valid, see LFFindFilesRecursive for more. 26 | % 27 | % LFUtilExtractLFPThumbs('Images') 28 | % LFUtilExtractLFPThumbs({'*.lfr','*.lfp'}) 29 | % LFUtilExtractLFPThumbs({'Images','*.lfr','*.lfp'}) 30 | % LFUtilExtractLFPThumbs('Images/*.lfr') 31 | % LFUtilExtractLFPThumbs('*.lfr') 32 | % LFUtilExtractLFPThumbs('Images/IMG_0001.LFR') 33 | % LFUtilExtractLFPThumbs('IMG_0001.LFR') 34 | % 35 | % See also: LFFindFilesRecursive 36 | 37 | % Part of LF Toolbox v0.4 released 12-Feb-2015 38 | % Copyright (c) 2013-2015 Donald G. Dansereau 39 | 40 | function LFUtilExtractLFPThumbs( InputPath ) 41 | 42 | %---Defaults--- 43 | InputPath = LFDefaultVal( 'InputPath','.' ); 44 | DefaultFileSpec = {'*.LFP','*.LFR','*.lfp','*.lfr'}; % gets overriden below, if a file spec is provided 45 | 46 | [FileList, BasePath] = LFFindFilesRecursive( InputPath, DefaultFileSpec ); 47 | 48 | fprintf('Found :\n'); 49 | disp(FileList) 50 | 51 | %---Process each file--- 52 | for( iFile = 1:length(FileList) ) 53 | CurFname = fullfile(BasePath, FileList{iFile}); 54 | 55 | fprintf('Processing [%d / %d] %s\n', iFile, length(FileList), CurFname); 56 | LFP = LFReadLFP( CurFname ); 57 | 58 | if( ~isfield(LFP, 'Jpeg') ) 59 | continue; 60 | end 61 | if( ~iscell(LFP.Jpeg) ) 62 | LFP.Jpeg = {LFP.Jpeg}; 63 | end 64 | for( i=1:length(LFP.Jpeg) ) 65 | OutFname = sprintf('%s-%03d.jpg', CurFname, i-1); 66 | fprintf('%s', OutFname); 67 | if( exist(OutFname,'file') ) 68 | fprintf(' Exists, skipping\n'); 69 | else 70 | OutFile = fopen(OutFname, 'wb'); 71 | fwrite(OutFile, LFP.Jpeg{i}); 72 | fclose(OutFile); 73 | fprintf('\n'); 74 | end 75 | end 76 | end 77 | 78 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFUtilProcessCalibrations.m: -------------------------------------------------------------------------------- 1 | % LFUtilProcessCalibrations - process a folder/tree of camera calibrations 2 | % 3 | % Usage: 4 | % 5 | % LFUtilProcessCalibrations 6 | % LFUtilProcessCalibrations( CalibrationsPath ) 7 | % LFUtilProcessCalibrations( CalibrationsPath, FileOptions ) 8 | % LFUtilProcessCalibrations( [], FileOptions ) 9 | % 10 | % All parameters are optional and take on default values as set in the "Defaults" section at the top 11 | % of the implementation. As such, this can be called as a function or run directly by editing the 12 | % code. When calling as a function, pass an empty array "[]" to omit a parameter. 13 | % 14 | % This function recursively crawls through a folder identifying camera "calibration info" files and 15 | % building a database for use in selecting a calibration appropriate to a light field. An example 16 | % usage is in the image rectification code in LFUtilDecodeLytroFolder / LFSelectFromDatabase. 17 | % 18 | % Inputs -- all are optional, see code below for default values : 19 | % 20 | % CalibrationsPath : Path to folder containing calibrations -- note the function operates 21 | % recursively, i.e. it will search sub-folders. The calibration database will 22 | % be created at the top level of this path. A typical configuration is to 23 | % create a "Cameras" folder with a separate subfolder of calibrations for each 24 | % camera in use. The appropriate path to pass to this function is the top 25 | % level of that cameras folder. 26 | % 27 | % 28 | % FileOptions : struct controlling file naming and saving 29 | % .SaveResult : Set to false to perform a "dry run" 30 | % .CalibrationDatabaseFname : Name of file to which white image database is saved 31 | % .CalInfoFilenamePattern : File search pattern for finding calibrations 32 | % 33 | % Output takes the form of a saved calibration database. 34 | % 35 | % See also: LFUtilDecodeLytroFolder, LFCalRectifyLF, LFSelectFromDatabase, LFUtilCalLensletCam, 36 | % LFUtilProcessWhiteImages 37 | 38 | % Part of LF Toolbox v0.4 released 12-Feb-2015 39 | % Copyright (c) 2013-2015 Donald G. Dansereau 40 | 41 | function LFUtilProcessCalibrations( CalibrationsPath, FileOptions ) 42 | 43 | %---Defaults--- 44 | CalibrationsPath = LFDefaultVal( 'CalibrationsPath', 'Cameras' ); 45 | 46 | FileOptions = LFDefaultField( 'FileOptions', 'SaveResult', true ); 47 | FileOptions = LFDefaultField( 'FileOptions', 'CalibrationDatabaseFname', 'CalibrationDatabase.mat' ); 48 | FileOptions = LFDefaultField( 'FileOptions', 'CalInfoFilenamePattern', 'CalInfo*.json' ); 49 | 50 | 51 | %---Crawl folder structure locating calibrations--- 52 | fprintf('Building database of calibrations in %s\n', CalibrationsPath); 53 | CamInfo = LFGatherCamInfo( CalibrationsPath, FileOptions.CalInfoFilenamePattern ); 54 | 55 | %---Optionally save--- 56 | if( FileOptions.SaveResult ) 57 | SaveFpath = fullfile(CalibrationsPath, FileOptions.CalibrationDatabaseFname); 58 | fprintf('Saving to %s\n', SaveFpath); 59 | 60 | TimeStamp = datestr(now,'ddmmmyyyy_HHMMSS'); 61 | GeneratedByInfo = struct('mfilename', mfilename, 'time', TimeStamp, 'VersionStr', LFToolboxVersion); 62 | save(SaveFpath, 'GeneratedByInfo', 'CamInfo'); 63 | end 64 | -------------------------------------------------------------------------------- /LFToolbox0.4/LFUtilUnpackLytroArchive.m: -------------------------------------------------------------------------------- 1 | % LFUtilUnpackLytroArchive - extract white images and other files from a multi-volume Lytro archive 2 | % 3 | % Usage: 4 | % LFUtilUnpackLytroArchive 5 | % LFUtilUnpackLytroArchive( InputPath ) 6 | % LFUtilUnpackLytroArchive( InputPath, FirstVolumeFname ) 7 | % LFUtilUnpackLytroArchive( [], FirstVolumeFname ) 8 | % 9 | % This extracts all the files from all Lytro archives found in the requested path. Archives typically take on names like 10 | % data.C.0, data.C.1 and so forth, and contain white images, metadata and other information. 11 | % 12 | % The function searches for archives recursively, so if there are archives in multiple sub-folders, they will all be 13 | % expanded. The file LFToolbox.json is created to mark completion of the extraction in a folder. Already-expanded 14 | % archives are skipped; delete LFToolbox.json to force re-extraction in a folder. 15 | % 16 | % Based in part on Nirav Patel and Doug Kelley's LFP readers. Thanks to Michael Tao for help and samples for decoding 17 | % Illum imagery. 18 | % 19 | % Inputs -- all are optional : 20 | % 21 | % InputPath : Path to folder containing the archive, default 'Cameras' 22 | % FirstVolumeFname : Name of the first file in the archive, default 'data.C.0' 23 | % 24 | % Example: 25 | % 26 | % LFUtilUnpackLytroArchive 27 | % 28 | % Will extract the contents of all archives in all subfolders of the current folder. If you are working with 29 | % multiple cameras, place each multi-volume archve in its own sub-folder, then call this from the top-level folder 30 | % to expand them all. 31 | % 32 | % See also: LFUtilProcessWhiteImages, LFReadLFP, LFUtilExtractLFPThumbs 33 | 34 | % Part of LF Toolbox v0.4 released 12-Feb-2015 35 | % Copyright (c) 2013-2015 Donald G. Dansereau 36 | 37 | function LFUtilUnpackLytroArchive( InputPath, FirstVolumeFname ) 38 | 39 | %---Defaults--- 40 | InputPath = LFDefaultVal('InputPath','Cameras'); 41 | FirstVolumeFname = LFDefaultVal('FirstVolumeFname','data.C.0'); 42 | 43 | 44 | [AllVolumes, BasePath] = LFFindFilesRecursive(InputPath, FirstVolumeFname); 45 | fprintf('Found :\n'); 46 | disp(AllVolumes) 47 | 48 | %---Consts--- 49 | LFPConsts.LFPHeader = hex2dec({'89', '4C', '46', '50', '0D', '0A', '1A', '0A', '00', '00', '00', '01'}); % 12-byte LFPSections header 50 | LFPConsts.SectHeaderLFM = hex2dec({'89', '4C', '46', '4D', '0D', '0A', '1A', '0A'})'; % header for table of contents 51 | LFPConsts.SectHeaderLFC = hex2dec({'89', '4C', '46', '43', '0D', '0A', '1A', '0A'})'; % header for content section 52 | LFPConsts.SecHeaderPaddingLen = 4; 53 | LFPConsts.Sha1Length = 45; 54 | LFPConsts.ShaPaddingLen = 35; % Sha1 codes are followed by 35 null bytes 55 | LFToolboxInfoFname = 'LFToolbox.json'; 56 | 57 | %--- 58 | for( VolumeIdx = 1:length(AllVolumes) ) 59 | 60 | CurFile = fullfile(BasePath, AllVolumes{VolumeIdx}); 61 | OutPath = fileparts(CurFile); 62 | 63 | fprintf('Extracting files in "%s"...\n', OutPath); 64 | CurInfoFname = fullfile( OutPath, LFToolboxInfoFname ); 65 | if( exist(CurInfoFname, 'file') ) 66 | fprintf('Already done, skipping (delete "%s" to force redo)\n\n', CurInfoFname); 67 | continue; 68 | end 69 | 70 | while( 1 ) 71 | fprintf(' %s...\n', CurFile); 72 | InFile=fopen(CurFile, 'rb'); 73 | 74 | %---Check for the magic header--- 75 | HeaderBytes = fread( InFile, length(LFPConsts.LFPHeader), 'uchar' ); 76 | if( ~all( HeaderBytes == LFPConsts.LFPHeader ) ) 77 | fclose(InFile); 78 | fprintf( 'Unrecognized file type' ); 79 | return 80 | end 81 | 82 | %---Confirm headerlength bytes--- 83 | HeaderLength = fread(InFile,1,'uint32','ieee-be'); 84 | assert( HeaderLength == 0, 'Unexpected length at top-level header' ); 85 | 86 | %---Read each section--- 87 | % This implementation assumes the TOC appears first in each file 88 | clear TOC 89 | while( ~feof(InFile) ) 90 | CurSection = ReadSection( InFile, LFPConsts ); 91 | 92 | if( all( CurSection.SectHeader == LFPConsts.SectHeaderLFM ) ) 93 | TOC = LFReadMetadata( CurSection.Data ); 94 | else 95 | assert( exist('TOC','var')==1, 'Expected to find table of contents at top of file' ); 96 | MatchingSectIdx = find( strcmp( CurSection.Sha1, {TOC.files.dataRef} ) ); 97 | CurFname = TOC.files(MatchingSectIdx).name; 98 | CurFname = strrep( CurFname, 'C:\', '' ); 99 | CurFname = strrep( CurFname, '\', '__' ); 100 | OutFile = fopen( fullfile(OutPath, CurFname), 'wb' ); 101 | fwrite( OutFile, CurSection.Data ); 102 | fclose(OutFile); 103 | end 104 | end 105 | fclose( InFile ); 106 | 107 | if( isfield(TOC, 'nextFile') ) 108 | CurFile = fullfile(OutPath, TOC.nextFile); 109 | else 110 | break; 111 | end 112 | end 113 | 114 | TimeStamp = datestr(now,'ddmmmyyyy_HHMMSS'); 115 | GeneratedByInfo = struct('mfilename', mfilename, 'time', TimeStamp, 'VersionStr', LFToolboxVersion); 116 | fprintf( 'Marking completion in "%s"\n\n', CurInfoFname ); 117 | LFWriteMetadata( CurInfoFname, GeneratedByInfo ); 118 | end 119 | fprintf('Done\n'); 120 | 121 | end 122 | 123 | % -------------------------------------------------------------------- 124 | function LFPSect = ReadSection( InFile, LFPConsts ) 125 | LFPSect.SectHeader = fread(InFile, length(LFPConsts.SectHeaderLFM), 'uchar')'; 126 | Padding = fread(InFile, LFPConsts.SecHeaderPaddingLen, 'uint8'); % skip padding 127 | 128 | SectLength = fread(InFile, 1, 'uint32', 'ieee-be'); 129 | LFPSect.Sha1 = char(fread(InFile, LFPConsts.Sha1Length, 'uchar')'); 130 | Padding = fread(InFile, LFPConsts.ShaPaddingLen, 'uint8'); % skip padding 131 | 132 | LFPSect.Data = char(fread(InFile, SectLength, 'uchar'))'; 133 | 134 | while( 1 ) 135 | Padding = fread(InFile, 1, 'uchar'); 136 | if( feof(InFile) || (Padding ~= 0) ) 137 | break; 138 | end 139 | end 140 | if ~feof(InFile) 141 | fseek( InFile, -1, 'cof'); % rewind one byte 142 | end 143 | 144 | end 145 | 146 | -------------------------------------------------------------------------------- /LFToolbox0.4/README: -------------------------------------------------------------------------------- 1 | Matlab Light Field Toolbox v0.4 released 12-Feb-2015 2 | Copyright (c) 2013, 2014 by Donald G. Dansereau 3 | 4 | Please refer to LFToolbox.pdf for installation instructions and further information. 5 | 6 | This is a set of tools for working with light field (aka plenoptic) imagery in Matlab. Features include decoding, calibration, rectification, colour correction, basic filtering and visualization of light field images. New in version 0.4 are some linear depth/focus and denoising filters. 7 | 8 | Download the sample light field pack at http://www-personal.acfr.usyd.edu.au/ddan1654/LFToolbox0.3_Samples1.zip. Sample calibration datasets can be found at http://marine.acfr.usyd.edu.au/plenoptic-imaging. 9 | 10 | ---Compatibility--- 11 | LFToolbox 0.4 is reverse-compatible with LFToolbox 0.3. The original Lytro camera (the "F01") and the Lytro Illum are supported under Lytro Desktop 4 and 3. Calibration and rectification of Illum imagery is experimental. 12 | 13 | Users upgrading directly from LFToolbox 0.2 will need to re-run calibration and decoding and update some parameter names. 14 | 15 | ---Contributing / Feedback--- 16 | Suggestions, bug reports, code improvements and new functionality are welcome -- email Donald.Dansereau+LFToolbox {at} gmail dot com. 17 | 18 | ---Acknowledgements--- 19 | Parts of the code were taken with permission from the Camera Calibration Toolbox for Matlab by Jean-Yves Bouguet, with contributions from Pietro Perona and others; and from the JSONlab Toolbox by Qianqian Fang and others. LFFigure was originally by Daniel Eaton. The LFP reader is based in part on Nirav Patel and Doug Kelley's LFP readers. Thanks to Michael Tao for help and samples for decoding Illum imagery. 20 | 21 | ---Citing--- 22 | The appropriate citations for decoding, calibration and rectification and the volumetric focus (hyperfan) filter are: 23 | 24 | @inproceedings{dansereau2013decoding, 25 | title={Decoding, Calibration and Rectification for lenselet-Based Plenoptic Cameras}, 26 | author={Donald G. Dansereau and Oscar Pizarro and Stefan B. Williams}, 27 | booktitle={Computer Vision and Pattern Recognition (CVPR), IEEE Conference on}, 28 | year={2013}, 29 | month={Jun}, 30 | organization={IEEE} 31 | } 32 | 33 | @article{dansereau2015linear, 34 | title={Linear Volumetric Focus for Light Field Cameras}, 35 | author={Donald G. Dansereau and Oscar Pizarro and Stefan B. Williams}, 36 | journal={ACM Transactions on Graphics (TOG)}, 37 | volume={34}, 38 | number={2}, 39 | month={Feb.}, 40 | year={2015} 41 | } 42 | 43 | ---Future Plans--- 44 | A way to keep calibrations reverse-compatible, a more direct decode procedure with user control over output resolution, 4D-to-2D rendering, spatial- and hybrid-domain filter implementations, more filtering demos including use of aliased filter components and denoising. 45 | 46 | 47 | ---Changes--- 48 | v0.4 : 49 | Features: 50 | - Building, applying 2D & 4D frequency-domain filters LFBuild*.m, LFFilt*.m, LFDemoBasicFilt*.m 51 | - Spatial-domain shift-sum filter LFFiltShiftSum.m 52 | - Quick 2D display convenience function LFDisp.m 53 | 54 | v0.3 : 55 | Features : 56 | - LFReadGantryArray: Loading gantry light fields 57 | - LFReadLFP: Loading Lytro lfp / lfr files 58 | - Compatibility with Lytro Desktop 4 and Illum files 59 | 60 | Bug Fixes : 61 | - Fixed incorrect hex grid phase on some cameras 62 | - Various compatibility updates for recent Matlab versions 63 | 64 | Performance and behaviour changes : 65 | - Replaced corner finder with Matlab version -- slower but more robust 66 | - Decoded light field size more closely matches individual camera characteristics 67 | - Faster triangulation-based resampling 68 | - Lower memory utilization in decode, rectification, histogram equalization 69 | - Figures no longer steal focus -- see SupportFunctions/LFFigure 70 | - Smarter input path interpretation -- see SupportFunction/LFFindFilesRecursive 71 | - LFDispMousePan works over a wider range of input types 72 | - LFHistEqualize converts colour images to HSV and operates on value 73 | - Colour correction no longer applies LFHistEqualize 74 | 75 | Name changes : 76 | - Lenselet -> lenslet 77 | - DecodeOptions.DehexMethod -> DecodeOptions.ResampMethod 78 | - Added DecodeOptions.DoDehex and DecodeOptions.DoSquarST options 79 | - Moved LevelLimits to DecodeOptions.LevelLimits 80 | - LFLytroDecodeImage -> LFLytroDecodeImage 81 | - Reorganized some functions into/out of "SupportFunctions" 82 | 83 | v0.2 : 84 | - Calibration of lenslet cameras from checkerboard images 85 | - LFUtilDecodeLytroFolder: decoding, colour correction and rectification 86 | - Management of multiple cameras, white images and calibrations 87 | - Organized code into a folder structure, see LFMatlabPathSetup 88 | - Organized light fields / cameras into a folder structure 89 | - Code and usability improvements throughout 90 | 91 | v0.1 : Initial release 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/CameraCal/compute_extrinsic_init.m: -------------------------------------------------------------------------------- 1 | function [omckk,Tckk,Rckk] = compute_extrinsic_init(x_kk,X_kk,fc,cc,kc,alpha_c), 2 | 3 | %compute_extrinsic 4 | % 5 | %[omckk,Tckk,Rckk] = compute_extrinsic_init(x_kk,X_kk,fc,cc,kc,alpha_c) 6 | % 7 | %Computes the extrinsic parameters attached to a 3D structure X_kk given its projection 8 | %on the image plane x_kk and the intrinsic camera parameters fc, cc and kc. 9 | %Works with planar and non-planar structures. 10 | % 11 | %INPUT: x_kk: Feature locations on the images 12 | % X_kk: Corresponding grid coordinates 13 | % fc: Camera focal length 14 | % cc: Principal point coordinates 15 | % kc: Distortion coefficients 16 | % alpha_c: Skew coefficient 17 | % 18 | %OUTPUT: omckk: 3D rotation vector attached to the grid positions in space 19 | % Tckk: 3D translation vector attached to the grid positions in space 20 | % Rckk: 3D rotation matrices corresponding to the omc vectors 21 | % 22 | %Method: Computes the normalized point coordinates, then computes the 3D pose 23 | % 24 | %Important functions called within that program: 25 | % 26 | %normalize_pixel: Computes the normalize image point coordinates. 27 | % 28 | %pose3D: Computes the 3D pose of the structure given the normalized image projection. 29 | % 30 | %project_points.m: Computes the 2D image projections of a set of 3D points 31 | 32 | 33 | 34 | if nargin < 6, 35 | alpha_c = 0; 36 | if nargin < 5, 37 | kc = zeros(5,1); 38 | if nargin < 4, 39 | cc = zeros(2,1); 40 | if nargin < 3, 41 | fc = ones(2,1); 42 | if nargin < 2, 43 | error('Need 2D projections and 3D points (in compute_extrinsic.m)'); 44 | return; 45 | end; 46 | end; 47 | end; 48 | end; 49 | end; 50 | 51 | 52 | %keyboard; 53 | 54 | % Compute the normalized coordinates: 55 | 56 | xn = normalize_pixel(x_kk,fc,cc,kc,alpha_c); 57 | 58 | 59 | 60 | Np = size(xn,2); 61 | 62 | %% Check for planarity of the structure: 63 | %keyboard; 64 | 65 | X_mean = mean(X_kk')'; 66 | 67 | Y = X_kk - (X_mean*ones(1,Np)); 68 | 69 | YY = Y*Y'; 70 | 71 | [U,S,V] = svd(YY); 72 | 73 | r = S(3,3)/S(2,2); 74 | 75 | %keyboard; 76 | 77 | 78 | if (r < 1e-3)|(Np < 5), %1e-3, %1e-4, %norm(X_kk(3,:)) < eps, % Test of planarity 79 | 80 | %fprintf(1,'Planar structure detected: r=%f\n',r); 81 | 82 | % Transform the plane to bring it in the Z=0 plane: 83 | 84 | R_transform = V'; 85 | 86 | %norm(R_transform(1:2,3)) 87 | 88 | if norm(R_transform(1:2,3)) < 1e-6, 89 | R_transform = eye(3); 90 | end; 91 | 92 | if det(R_transform) < 0, R_transform = -R_transform; end; 93 | 94 | T_transform = -(R_transform)*X_mean; 95 | 96 | X_new = R_transform*X_kk + T_transform*ones(1,Np); 97 | 98 | 99 | % Compute the planar homography: 100 | 101 | H = compute_homography(xn,X_new(1:2,:)); 102 | 103 | % De-embed the motion parameters from the homography: 104 | 105 | sc = mean([norm(H(:,1));norm(H(:,2))]); 106 | 107 | H = H/sc; 108 | 109 | % Extra normalization for some reasons... 110 | %H(:,1) = H(:,1)/norm(H(:,1)); 111 | %H(:,2) = H(:,2)/norm(H(:,2)); 112 | 113 | if 0, %%% Some tests for myself... the opposite sign solution leads to negative depth!!! 114 | 115 | % Case#1: no opposite sign: 116 | 117 | omckk1 = rodrigues([H(:,1:2) cross(H(:,1),H(:,2))]); 118 | Rckk1 = rodrigues(omckk1); 119 | Tckk1 = H(:,3); 120 | 121 | Hs1 = [Rckk1(:,1:2) Tckk1]; 122 | xn1 = Hs1*[X_new(1:2,:);ones(1,Np)]; 123 | xn1 = [xn1(1,:)./xn1(3,:) ; xn1(2,:)./xn1(3,:)]; 124 | e1 = xn1 - xn; 125 | 126 | % Case#2: opposite sign: 127 | 128 | omckk2 = rodrigues([-H(:,1:2) cross(H(:,1),H(:,2))]); 129 | Rckk2 = rodrigues(omckk2); 130 | Tckk2 = -H(:,3); 131 | 132 | Hs2 = [Rckk2(:,1:2) Tckk2]; 133 | xn2 = Hs2*[X_new(1:2,:);ones(1,Np)]; 134 | xn2 = [xn2(1,:)./xn2(3,:) ; xn2(2,:)./xn2(3,:)]; 135 | e2 = xn2 - xn; 136 | 137 | if 1, %norm(e1) < norm(e2), 138 | omckk = omckk1; 139 | Tckk = Tckk1; 140 | Rckk = Rckk1; 141 | else 142 | omckk = omckk2; 143 | Tckk = Tckk2; 144 | Rckk = Rckk2; 145 | end; 146 | 147 | else 148 | 149 | u1 = H(:,1); 150 | u1 = u1 / norm(u1); 151 | u2 = H(:,2) - dot(u1,H(:,2)) * u1; 152 | u2 = u2 / norm(u2); 153 | u3 = cross(u1,u2); 154 | RRR = [u1 u2 u3]; 155 | omckk = rodrigues(RRR); 156 | 157 | %omckk = rodrigues([H(:,1:2) cross(H(:,1),H(:,2))]); 158 | Rckk = rodrigues(omckk); 159 | Tckk = H(:,3); 160 | 161 | end; 162 | 163 | 164 | 165 | %If Xc = Rckk * X_new + Tckk, then Xc = Rckk * R_transform * X_kk + Tckk + T_transform 166 | 167 | Tckk = Tckk + Rckk* T_transform; 168 | Rckk = Rckk * R_transform; 169 | 170 | omckk = rodrigues(Rckk); 171 | Rckk = rodrigues(omckk); 172 | 173 | 174 | else 175 | 176 | %fprintf(1,'Non planar structure detected: r=%f\n',r); 177 | 178 | % Computes an initial guess for extrinsic parameters (works for general 3d structure, not planar!!!): 179 | % The DLT method is applied here!! 180 | 181 | J = zeros(2*Np,12); 182 | 183 | xX = (ones(3,1)*xn(1,:)).*X_kk; 184 | yX = (ones(3,1)*xn(2,:)).*X_kk; 185 | 186 | J(1:2:end,[1 4 7]) = -X_kk'; 187 | J(2:2:end,[2 5 8]) = X_kk'; 188 | J(1:2:end,[3 6 9]) = xX'; 189 | J(2:2:end,[3 6 9]) = -yX'; 190 | J(1:2:end,12) = xn(1,:)'; 191 | J(2:2:end,12) = -xn(2,:)'; 192 | J(1:2:end,10) = -ones(Np,1); 193 | J(2:2:end,11) = ones(Np,1); 194 | 195 | JJ = J'*J; 196 | [U,S,V] = svd(JJ); 197 | 198 | RR = reshape(V(1:9,12),3,3); 199 | 200 | if det(RR) < 0, 201 | V(:,12) = -V(:,12); 202 | RR = -RR; 203 | end; 204 | 205 | [Ur,Sr,Vr] = svd(RR); 206 | 207 | Rckk = Ur*Vr'; 208 | 209 | sc = norm(V(1:9,12)) / norm(Rckk(:)); 210 | Tckk = V(10:12,12)/sc; 211 | 212 | omckk = rodrigues(Rckk); 213 | Rckk = rodrigues(omckk); 214 | 215 | end; 216 | -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/CameraCal/compute_extrinsic_refine.m: -------------------------------------------------------------------------------- 1 | function [omckk,Tckk,Rckk,JJ] = compute_extrinsic_refine(omc_init,Tc_init,x_kk,X_kk,fc,cc,kc,alpha_c,MaxIter,thresh_cond), 2 | 3 | %compute_extrinsic 4 | % 5 | %[omckk,Tckk,Rckk] = compute_extrinsic_refine(omc_init,x_kk,X_kk,fc,cc,kc,alpha_c,MaxIter) 6 | % 7 | %Computes the extrinsic parameters attached to a 3D structure X_kk given its projection 8 | %on the image plane x_kk and the intrinsic camera parameters fc, cc and kc. 9 | %Works with planar and non-planar structures. 10 | % 11 | %INPUT: x_kk: Feature locations on the images 12 | % X_kk: Corresponding grid coordinates 13 | % fc: Camera focal length 14 | % cc: Principal point coordinates 15 | % kc: Distortion coefficients 16 | % alpha_c: Skew coefficient 17 | % MaxIter: Maximum number of iterations 18 | % 19 | %OUTPUT: omckk: 3D rotation vector attached to the grid positions in space 20 | % Tckk: 3D translation vector attached to the grid positions in space 21 | % Rckk: 3D rotation matrices corresponding to the omc vectors 22 | 23 | % 24 | %Method: Computes the normalized point coordinates, then computes the 3D pose 25 | % 26 | %Important functions called within that program: 27 | % 28 | %normalize_pixel: Computes the normalize image point coordinates. 29 | % 30 | %pose3D: Computes the 3D pose of the structure given the normalized image projection. 31 | % 32 | %project_points.m: Computes the 2D image projections of a set of 3D points 33 | 34 | 35 | if nargin < 10, 36 | thresh_cond = inf; 37 | end; 38 | 39 | 40 | if nargin < 9, 41 | MaxIter = 20; 42 | end; 43 | 44 | if nargin < 8, 45 | alpha_c = 0; 46 | if nargin < 7, 47 | kc = zeros(5,1); 48 | if nargin < 6, 49 | cc = zeros(2,1); 50 | if nargin < 5, 51 | fc = ones(2,1); 52 | if nargin < 4, 53 | error('Need 2D projections and 3D points (in compute_extrinsic_refine.m)'); 54 | return; 55 | end; 56 | end; 57 | end; 58 | end; 59 | end; 60 | 61 | 62 | % Initialization: 63 | 64 | omckk = omc_init; 65 | Tckk = Tc_init; 66 | 67 | 68 | % Final optimization (minimize the reprojection error in pixel): 69 | % through Gradient Descent: 70 | 71 | param = [omckk;Tckk]; 72 | 73 | change = 1; 74 | 75 | iter = 0; 76 | 77 | %keyboard; 78 | 79 | %fprintf(1,'Gradient descent iterations: '); 80 | 81 | while (change > 1e-10)&(iter < MaxIter), 82 | 83 | %fprintf(1,'%d...',iter+1); 84 | 85 | [x,dxdom,dxdT] = project_points2(X_kk,omckk,Tckk,fc,cc,kc,alpha_c); 86 | 87 | ex = x_kk - x; 88 | 89 | %keyboard; 90 | 91 | JJ = [dxdom dxdT]; 92 | 93 | if cond(JJ) > thresh_cond, 94 | change = 0; 95 | else 96 | 97 | JJ2 = JJ'*JJ; 98 | 99 | param_innov = inv(JJ2)*(JJ')*ex(:); 100 | param_up = param + param_innov; 101 | change = norm(param_innov)/norm(param_up); 102 | param = param_up; 103 | iter = iter + 1; 104 | 105 | omckk = param(1:3); 106 | Tckk = param(4:6); 107 | 108 | end; 109 | 110 | end; 111 | 112 | %fprintf(1,'\n'); 113 | 114 | Rckk = rodrigues(omckk); 115 | -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/CameraCal/compute_homography.m: -------------------------------------------------------------------------------- 1 | function [H,Hnorm,inv_Hnorm] = compute_homography(m,M); 2 | 3 | %compute_homography 4 | % 5 | %[H,Hnorm,inv_Hnorm] = compute_homography(m,M) 6 | % 7 | %Computes the planar homography between the point coordinates on the plane (M) and the image 8 | %point coordinates (m). 9 | % 10 | %INPUT: m: homogeneous coordinates in the image plane (3xN matrix) 11 | % M: homogeneous coordinates in the plane in 3D (3xN matrix) 12 | % 13 | %OUTPUT: H: Homography matrix (3x3 homogeneous matrix) 14 | % Hnorm: Normalization matrix used on the points before homography computation 15 | % (useful for numerical stability is points in pixel coordinates) 16 | % inv_Hnorm: The inverse of Hnorm 17 | % 18 | %Definition: m ~ H*M where "~" means equal up to a non zero scalar factor. 19 | % 20 | %Method: First computes an initial guess for the homography through quasi-linear method. 21 | % Then, if the total number of points is larger than 4, optimize the solution by minimizing 22 | % the reprojection error (in the least squares sense). 23 | % 24 | % 25 | %Important functions called within that program: 26 | % 27 | %comp_distortion_oulu: Undistorts pixel coordinates. 28 | % 29 | %compute_homography.m: Computes the planar homography between points on the grid in 3D, and the image plane. 30 | % 31 | %project_points.m: Computes the 2D image projections of a set of 3D points, and also returns te Jacobian 32 | % matrix (derivative with respect to the intrinsic and extrinsic parameters). 33 | % This function is called within the minimization loop. 34 | 35 | 36 | 37 | 38 | Np = size(m,2); 39 | 40 | if size(m,1)<3, 41 | m = [m;ones(1,Np)]; 42 | end; 43 | 44 | if size(M,1)<3, 45 | M = [M;ones(1,Np)]; 46 | end; 47 | 48 | 49 | m = m ./ (ones(3,1)*m(3,:)); 50 | M = M ./ (ones(3,1)*M(3,:)); 51 | 52 | % Prenormalization of point coordinates (very important): 53 | % (Affine normalization) 54 | 55 | ax = m(1,:); 56 | ay = m(2,:); 57 | 58 | mxx = mean(ax); 59 | myy = mean(ay); 60 | ax = ax - mxx; 61 | ay = ay - myy; 62 | 63 | scxx = mean(abs(ax)); 64 | scyy = mean(abs(ay)); 65 | 66 | 67 | Hnorm = [1/scxx 0 -mxx/scxx;0 1/scyy -myy/scyy;0 0 1]; 68 | inv_Hnorm = [scxx 0 mxx ; 0 scyy myy; 0 0 1]; 69 | 70 | mn = Hnorm*m; 71 | 72 | % Compute the homography between m and mn: 73 | 74 | % Build the matrix: 75 | 76 | L = zeros(2*Np,9); 77 | 78 | L(1:2:2*Np,1:3) = M'; 79 | L(2:2:2*Np,4:6) = M'; 80 | L(1:2:2*Np,7:9) = -((ones(3,1)*mn(1,:)).* M)'; 81 | L(2:2:2*Np,7:9) = -((ones(3,1)*mn(2,:)).* M)'; 82 | 83 | if Np > 4, 84 | L = L'*L; 85 | end; 86 | 87 | [U,S,V] = svd(L); 88 | 89 | hh = V(:,9); 90 | hh = hh/hh(9); 91 | 92 | Hrem = reshape(hh,3,3)'; 93 | %Hrem = Hrem / Hrem(3,3); 94 | 95 | 96 | % Final homography: 97 | 98 | H = inv_Hnorm*Hrem; 99 | 100 | if 0, 101 | m2 = H*M; 102 | m2 = [m2(1,:)./m2(3,:) ; m2(2,:)./m2(3,:)]; 103 | merr = m(1:2,:) - m2; 104 | end; 105 | 106 | %keyboard; 107 | 108 | %%% Homography refinement if there are more than 4 points: 109 | 110 | if Np > 4, 111 | 112 | % Final refinement: 113 | hhv = reshape(H',9,1); 114 | hhv = hhv(1:8); 115 | 116 | for iter=1:10, 117 | 118 | 119 | 120 | mrep = H * M; 121 | 122 | J = zeros(2*Np,8); 123 | 124 | MMM = (M ./ (ones(3,1)*mrep(3,:))); 125 | 126 | J(1:2:2*Np,1:3) = -MMM'; 127 | J(2:2:2*Np,4:6) = -MMM'; 128 | 129 | mrep = mrep ./ (ones(3,1)*mrep(3,:)); 130 | 131 | m_err = m(1:2,:) - mrep(1:2,:); 132 | m_err = m_err(:); 133 | 134 | MMM2 = (ones(3,1)*mrep(1,:)) .* MMM; 135 | MMM3 = (ones(3,1)*mrep(2,:)) .* MMM; 136 | 137 | J(1:2:2*Np,7:8) = MMM2(1:2,:)'; 138 | J(2:2:2*Np,7:8) = MMM3(1:2,:)'; 139 | 140 | MMM = (M ./ (ones(3,1)*mrep(3,:)))'; 141 | 142 | hh_innov = inv(J'*J)*J'*m_err; 143 | 144 | hhv_up = hhv - hh_innov; 145 | 146 | H_up = reshape([hhv_up;1],3,3)'; 147 | 148 | %norm(m_err) 149 | %norm(hh_innov) 150 | 151 | hhv = hhv_up; 152 | H = H_up; 153 | 154 | end; 155 | 156 | 157 | end; 158 | 159 | if 0, 160 | m2 = H*M; 161 | m2 = [m2(1,:)./m2(3,:) ; m2(2,:)./m2(3,:)]; 162 | merr = m(1:2,:) - m2; 163 | end; 164 | 165 | return; 166 | 167 | %test of Jacobian 168 | 169 | mrep = H*M; 170 | mrep = mrep ./ (ones(3,1)*mrep(3,:)); 171 | 172 | m_err = mrep(1:2,:) - m(1:2,:); 173 | figure(8); 174 | plot(m_err(1,:),m_err(2,:),'r+'); 175 | std(m_err') 176 | -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/CameraCal/normalize_pixel.m: -------------------------------------------------------------------------------- 1 | function [xn] = normalize_pixel(x_kk,fc,cc,kc,alpha_c) 2 | 3 | %normalize 4 | % 5 | %[xn] = normalize_pixel(x_kk,fc,cc,kc,alpha_c) 6 | % 7 | %Computes the normalized coordinates xn given the pixel coordinates x_kk 8 | %and the intrinsic camera parameters fc, cc and kc. 9 | % 10 | %INPUT: x_kk: Feature locations on the images 11 | % fc: Camera focal length 12 | % cc: Principal point coordinates 13 | % kc: Distortion coefficients 14 | % alpha_c: Skew coefficient 15 | % 16 | %OUTPUT: xn: Normalized feature locations on the image plane (a 2XN matrix) 17 | % 18 | %Important functions called within that program: 19 | % 20 | %comp_distortion_oulu: undistort pixel coordinates. 21 | 22 | if nargin < 5, 23 | alpha_c = 0; 24 | if nargin < 4; 25 | kc = [0;0;0;0;0]; 26 | if nargin < 3; 27 | cc = [0;0]; 28 | if nargin < 2, 29 | fc = [1;1]; 30 | end; 31 | end; 32 | end; 33 | end; 34 | 35 | 36 | % First: Subtract principal point, and divide by the focal length: 37 | x_distort = [(x_kk(1,:) - cc(1))/fc(1);(x_kk(2,:) - cc(2))/fc(2)]; 38 | 39 | % Second: undo skew 40 | x_distort(1,:) = x_distort(1,:) - alpha_c * x_distort(2,:); 41 | 42 | if norm(kc) ~= 0, 43 | % Third: Compensate for lens distortion: 44 | xn = comp_distortion_oulu(x_distort,kc); 45 | else 46 | xn = x_distort; 47 | end; 48 | -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/CameraCal/rigid_motion.m: -------------------------------------------------------------------------------- 1 | function [Y,dYdom,dYdT] = rigid_motion(X,om,T); 2 | 3 | %rigid_motion.m 4 | % 5 | %[Y,dYdom,dYdT] = rigid_motion(X,om,T) 6 | % 7 | %Computes the rigid motion transformation Y = R*X+T, where R = rodrigues(om). 8 | % 9 | %INPUT: X: 3D structure in the world coordinate frame (3xN matrix for N points) 10 | % (om,T): Rigid motion parameters between world coordinate frame and camera reference frame 11 | % om: rotation vector (3x1 vector); T: translation vector (3x1 vector) 12 | % 13 | %OUTPUT: Y: 3D coordinates of the structure points in the camera reference frame (3xN matrix for N points) 14 | % dYdom: Derivative of Y with respect to om ((3N)x3 matrix) 15 | % dYdT: Derivative of Y with respect to T ((3N)x3 matrix) 16 | % 17 | %Definitions: 18 | %Let P be a point in 3D of coordinates X in the world reference frame (stored in the matrix X) 19 | %The coordinate vector of P in the camera reference frame is: Y = R*X + T 20 | %where R is the rotation matrix corresponding to the rotation vector om: R = rodrigues(om); 21 | % 22 | %Important function called within that program: 23 | % 24 | %rodrigues.m: Computes the rotation matrix corresponding to a rotation vector 25 | 26 | 27 | 28 | if nargin < 3, 29 | T = zeros(3,1); 30 | if nargin < 2, 31 | om = zeros(3,1); 32 | if nargin < 1, 33 | error('Need at least a 3D structure as input (in rigid_motion.m)'); 34 | return; 35 | end; 36 | end; 37 | end; 38 | 39 | 40 | [R,dRdom] = rodrigues(om); 41 | 42 | [m,n] = size(X); 43 | 44 | Y = R*X + repmat(T,[1 n]); 45 | 46 | if nargout > 1, 47 | 48 | 49 | dYdR = zeros(3*n,9); 50 | dYdT = zeros(3*n,3); 51 | 52 | dYdR(1:3:end,1:3:end) = X'; 53 | dYdR(2:3:end,2:3:end) = X'; 54 | dYdR(3:3:end,3:3:end) = X'; 55 | 56 | dYdT(1:3:end,1) = ones(n,1); 57 | dYdT(2:3:end,2) = ones(n,1); 58 | dYdT(3:3:end,3) = ones(n,1); 59 | 60 | dYdom = dYdR * dRdom; 61 | 62 | end; 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/CameraCal/rodrigues.m: -------------------------------------------------------------------------------- 1 | function [out,dout]=rodrigues(in) 2 | 3 | % RODRIGUES Transform rotation matrix into rotation vector and viceversa. 4 | % 5 | % Sintax: [OUT]=RODRIGUES(IN) 6 | % If IN is a 3x3 rotation matrix then OUT is the 7 | % corresponding 3x1 rotation vector 8 | % if IN is a rotation 3-vector then OUT is the 9 | % corresponding 3x3 rotation matrix 10 | % 11 | 12 | %% 13 | %% Copyright (c) March 1993 -- Pietro Perona 14 | %% California Institute of Technology 15 | %% 16 | 17 | %% ALL CHECKED BY JEAN-YVES BOUGUET, October 1995. 18 | %% FOR ALL JACOBIAN MATRICES !!! LOOK AT THE TEST AT THE END !! 19 | 20 | %% BUG when norm(om)=pi fixed -- April 6th, 1997; 21 | %% Jean-Yves Bouguet 22 | 23 | %% Add projection of the 3x3 matrix onto the set of special ortogonal matrices SO(3) by SVD -- February 7th, 2003; 24 | %% Jean-Yves Bouguet 25 | 26 | % BUG FOR THE CASE norm(om)=pi fixed by Mike Burl on Feb 27, 2007 27 | 28 | 29 | [m,n] = size(in); 30 | %bigeps = 10e+4*eps; 31 | bigeps = 10e+20*eps; 32 | 33 | if ((m==1) & (n==3)) | ((m==3) & (n==1)) %% it is a rotation vector 34 | theta = norm(in); 35 | if theta < eps 36 | R = eye(3); 37 | 38 | %if nargout > 1, 39 | 40 | dRdin = [0 0 0; 41 | 0 0 1; 42 | 0 -1 0; 43 | 0 0 -1; 44 | 0 0 0; 45 | 1 0 0; 46 | 0 1 0; 47 | -1 0 0; 48 | 0 0 0]; 49 | 50 | %end; 51 | 52 | else 53 | if n==length(in) in=in'; end; %% make it a column vec. if necess. 54 | 55 | %m3 = [in,theta] 56 | 57 | dm3din = [eye(3);in'/theta]; 58 | 59 | omega = in/theta; 60 | 61 | %m2 = [omega;theta] 62 | 63 | dm2dm3 = [eye(3)/theta -in/theta^2; zeros(1,3) 1]; 64 | 65 | alpha = cos(theta); 66 | beta = sin(theta); 67 | gamma = 1-cos(theta); 68 | omegav=[[0 -omega(3) omega(2)];[omega(3) 0 -omega(1)];[-omega(2) omega(1) 0 ]]; 69 | A = omega*omega'; 70 | 71 | %m1 = [alpha;beta;gamma;omegav;A]; 72 | 73 | dm1dm2 = zeros(21,4); 74 | dm1dm2(1,4) = -sin(theta); 75 | dm1dm2(2,4) = cos(theta); 76 | dm1dm2(3,4) = sin(theta); 77 | dm1dm2(4:12,1:3) = [0 0 0 0 0 1 0 -1 0; 78 | 0 0 -1 0 0 0 1 0 0; 79 | 0 1 0 -1 0 0 0 0 0]'; 80 | 81 | w1 = omega(1); 82 | w2 = omega(2); 83 | w3 = omega(3); 84 | 85 | dm1dm2(13:21,1) = [2*w1;w2;w3;w2;0;0;w3;0;0]; 86 | dm1dm2(13: 21,2) = [0;w1;0;w1;2*w2;w3;0;w3;0]; 87 | dm1dm2(13:21,3) = [0;0;w1;0;0;w2;w1;w2;2*w3]; 88 | 89 | R = eye(3)*alpha + omegav*beta + A*gamma; 90 | 91 | dRdm1 = zeros(9,21); 92 | 93 | dRdm1([1 5 9],1) = ones(3,1); 94 | dRdm1(:,2) = omegav(:); 95 | dRdm1(:,4:12) = beta*eye(9); 96 | dRdm1(:,3) = A(:); 97 | dRdm1(:,13:21) = gamma*eye(9); 98 | 99 | dRdin = dRdm1 * dm1dm2 * dm2dm3 * dm3din; 100 | 101 | 102 | end; 103 | out = R; 104 | dout = dRdin; 105 | 106 | %% it is prob. a rot matr. 107 | elseif ((m==n) & (m==3) & (norm(in' * in - eye(3)) < bigeps)... 108 | & (abs(det(in)-1) < bigeps)) 109 | R = in; 110 | 111 | % project the rotation matrix to SO(3); 112 | [U,S,V] = svd(R); 113 | R = U*V'; 114 | 115 | tr = (trace(R)-1)/2; 116 | dtrdR = [1 0 0 0 1 0 0 0 1]/2; 117 | theta = real(acos(tr)); 118 | 119 | 120 | if sin(theta) >= 1e-4, 121 | 122 | dthetadtr = -1/sqrt(1-tr^2); 123 | 124 | dthetadR = dthetadtr * dtrdR; 125 | % var1 = [vth;theta]; 126 | vth = 1/(2*sin(theta)); 127 | dvthdtheta = -vth*cos(theta)/sin(theta); 128 | dvar1dtheta = [dvthdtheta;1]; 129 | 130 | dvar1dR = dvar1dtheta * dthetadR; 131 | 132 | 133 | om1 = [R(3,2)-R(2,3), R(1,3)-R(3,1), R(2,1)-R(1,2)]'; 134 | 135 | dom1dR = [0 0 0 0 0 1 0 -1 0; 136 | 0 0 -1 0 0 0 1 0 0; 137 | 0 1 0 -1 0 0 0 0 0]; 138 | 139 | % var = [om1;vth;theta]; 140 | dvardR = [dom1dR;dvar1dR]; 141 | 142 | % var2 = [om;theta]; 143 | om = vth*om1; 144 | domdvar = [vth*eye(3) om1 zeros(3,1)]; 145 | dthetadvar = [0 0 0 0 1]; 146 | dvar2dvar = [domdvar;dthetadvar]; 147 | 148 | 149 | out = om*theta; 150 | domegadvar2 = [theta*eye(3) om]; 151 | 152 | dout = domegadvar2 * dvar2dvar * dvardR; 153 | 154 | 155 | else 156 | if tr > 0; % case norm(om)=0; 157 | 158 | out = [0 0 0]'; 159 | 160 | dout = [0 0 0 0 0 1/2 0 -1/2 0; 161 | 0 0 -1/2 0 0 0 1/2 0 0; 162 | 0 1/2 0 -1/2 0 0 0 0 0]; 163 | else 164 | 165 | % case norm(om)=pi; 166 | if(0) 167 | 168 | %% fixed April 6th by Bouguet -- not working in all cases! 169 | out = theta * (sqrt((diag(R)+1)/2).*[1;2*(R(1,2:3)>=0)'-1]); 170 | %keyboard; 171 | 172 | else 173 | 174 | % Solution by Mike Burl on Feb 27, 2007 175 | % This is a better way to determine the signs of the 176 | % entries of the rotation vector using a hash table on all 177 | % the combinations of signs of a pairs of products (in the 178 | % rotation matrix) 179 | 180 | % Define hashvec and Smat 181 | hashvec = [0; -1; -3; -9; 9; 3; 1; 13; 5; -7; -11]; 182 | Smat = [1,1,1; 1,0,-1; 0,1,-1; 1,-1,0; 1,1,0; 0,1,1; 1,0,1; 1,1,1; 1,1,-1; 183 | 1,-1,-1; 1,-1,1]; 184 | 185 | M = (R+eye(3,3))/2; 186 | uabs = sqrt(M(1,1)); 187 | vabs = sqrt(M(2,2)); 188 | wabs = sqrt(M(3,3)); 189 | 190 | mvec = [M(1,2), M(2,3), M(1,3)]; 191 | syn = ((mvec > 1e-4) - (mvec < -1e-4)); % robust sign() function 192 | hash = syn * [9; 3; 1]; 193 | idx = find(hash == hashvec); 194 | svec = Smat(idx,:)'; 195 | 196 | out = theta * [uabs; vabs; wabs] .* svec; 197 | 198 | end; 199 | 200 | if nargout > 1, 201 | fprintf(1,'WARNING!!!! Jacobian domdR undefined!!!\n'); 202 | dout = NaN*ones(3,9); 203 | end; 204 | end; 205 | end; 206 | 207 | else 208 | error('Neither a rotation matrix nor a rotation vector were provided'); 209 | end; 210 | 211 | return; 212 | 213 | %% test of the Jacobians: 214 | 215 | %%%% TEST OF dRdom: 216 | om = randn(3,1); 217 | dom = randn(3,1)/1000000; 218 | 219 | [R1,dR1] = rodrigues(om); 220 | R2 = rodrigues(om+dom); 221 | 222 | R2a = R1 + reshape(dR1 * dom,3,3); 223 | 224 | gain = norm(R2 - R1)/norm(R2 - R2a) 225 | 226 | %%% TEST OF dOmdR: 227 | om = randn(3,1); 228 | R = rodrigues(om); 229 | dom = randn(3,1)/10000; 230 | dR = rodrigues(om+dom) - R; 231 | 232 | [omc,domdR] = rodrigues(R); 233 | [om2] = rodrigues(R+dR); 234 | 235 | om_app = omc + domdR*dR(:); 236 | 237 | gain = norm(om2 - omc)/norm(om2 - om_app) 238 | 239 | 240 | %%% OTHER BUG: (FIXED NOW!!!) 241 | 242 | omu = randn(3,1); 243 | omu = omu/norm(omu) 244 | om = pi*omu; 245 | [R,dR]= rodrigues(om); 246 | [om2] = rodrigues(R); 247 | [om om2] 248 | 249 | %%% NORMAL OPERATION 250 | 251 | om = randn(3,1); 252 | [R,dR]= rodrigues(om); 253 | [om2] = rodrigues(R); 254 | [om om2] 255 | 256 | return 257 | 258 | % Test: norm(om) = pi 259 | 260 | u = randn(3,1); 261 | u = u / sqrt(sum(u.^2)); 262 | om = pi*u; 263 | R = rodrigues(om); 264 | 265 | R2 = rodrigues(rodrigues(R)); 266 | 267 | norm(R - R2) -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/CameraCal/source.txt: -------------------------------------------------------------------------------- 1 | The code in this folder was taken, with permission, from the Camera Calibration Toolbox for Matlab by Jean-Yves Bouguet. For more information please visit http://www.vision.caltech.edu/bouguetj/calib_doc/ . 2 | -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFCalFindCheckerCorners.m: -------------------------------------------------------------------------------- 1 | % LFCalFindCheckerCorners - locates corners in checkerboard images, called by LFUtilCalLensletCam 2 | % 3 | % Usage: 4 | % CalOptions = LFCalFindCheckerCorners( InputPath, CalOptions ) 5 | % CalOptions = LFCalFindCheckerCorners( InputPath ) 6 | % 7 | % This function is called by LFUtilCalLensletCam to identify the corners in a set of checkerboard 8 | % images. 9 | % 10 | % Inputs: 11 | % 12 | % InputPath : Path to folder containing decoded checkerboard images. 13 | % 14 | % [optional] CalOptions : struct controlling calibration parameters, all fields are optional 15 | % .CheckerCornersFnamePattern : Pattern for building output checkerboard corner files; %s is 16 | % used as a placeholder for the base filename 17 | % .LFFnamePattern : Filename pattern for locating input light fields 18 | % .ForceRedoCornerFinding : Forces the function to run, overwriting existing results 19 | % .ShowDisplay : Enables display, allowing visual verification of results 20 | % 21 | % Outputs : 22 | % 23 | % CalOptions struct as applied, including any default values as set up by the function 24 | % 25 | % Checker corner files are the key outputs of this function -- one file is generated fore each 26 | % input file, containing the list of extracted checkerboard corners. 27 | % 28 | % See also: LFUtilCalLensletCam, LFCalInit, LFCalRefine 29 | 30 | % Part of LF Toolbox v0.4 released 12-Feb-2015 31 | % Copyright (c) 2013-2015 Donald G. Dansereau 32 | 33 | function CalOptions = LFCalFindCheckerCorners( InputPath, CalOptions ) 34 | 35 | %---Defaults--- 36 | CalOptions = LFDefaultField( 'CalOptions', 'ForceRedoCornerFinding', false ); 37 | CalOptions = LFDefaultField( 'CalOptions', 'LFFnamePattern', '%s__Decoded.mat' ); 38 | CalOptions = LFDefaultField( 'CalOptions', 'CheckerCornersFnamePattern', '%s__CheckerCorners.mat' ); 39 | CalOptions = LFDefaultField( 'CalOptions', 'ShowDisplay', true ); 40 | CalOptions = LFDefaultField( 'CalOptions', 'MinSubimageWeight', 0.2 * 2^16 ); % for fast rejection of dark frames 41 | 42 | %---Build a regular expression for stripping the base filename out of the full raw filename--- 43 | BaseFnamePattern = regexp(CalOptions.LFFnamePattern, '%s', 'split'); 44 | BaseFnamePattern = cell2mat({BaseFnamePattern{1}, '(.*)', BaseFnamePattern{2}}); 45 | 46 | %---Tagged onto all saved files--- 47 | TimeStamp = datestr(now,'ddmmmyyyy_HHMMSS'); 48 | GeneratedByInfo = struct('mfilename', mfilename, 'time', TimeStamp, 'VersionStr', LFToolboxVersion); 49 | 50 | %---Crawl folder structure locating raw lenslet images--- 51 | fprintf('\n===Locating light fields in %s===\n', InputPath); 52 | [FileList, BasePath] = LFFindFilesRecursive( InputPath, sprintf(CalOptions.LFFnamePattern, '*') ); 53 | if( isempty(FileList) ) 54 | error(['No files found... are you running from the correct folder?\n'... 55 | ' Current folder: %s\n'], pwd); 56 | end; 57 | fprintf('Found :\n'); 58 | disp(FileList) 59 | 60 | %---Check zoom / focus and serial number settings across light fields--- 61 | fprintf('Checking zoom / focus / serial number across all files...\n'); 62 | for( iFile = 1:length(FileList) ) 63 | CurFname = FileList{iFile}; 64 | load(fullfile(BasePath, CurFname), 'LFMetadata'); 65 | CamSettings(iFile).Fname = CurFname; 66 | CamSettings(iFile).ZoomStep = LFMetadata.devices.lens.zoomStep; 67 | CamSettings(iFile).FocusStep = LFMetadata.devices.lens.focusStep; 68 | CamSettings(iFile).CamSerial = LFMetadata.SerialData.camera.serialNumber; 69 | end 70 | 71 | % Find the most frequent serial number 72 | [UniqueSerials,~,SerialIdx]=unique({CamSettings.CamSerial}); 73 | NumSerials = size(UniqueSerials,2); 74 | MostFreqSerialIdx = median(SerialIdx); 75 | CamInfo.CamSerial = UniqueSerials{MostFreqSerialIdx}; 76 | CamInfo.CamModel = LFMetadata.camera.model; 77 | 78 | % Finding the most frequent zoom / focus is easier 79 | CamInfo.FocusStep = median([CamSettings.FocusStep]); 80 | CamInfo.ZoomStep = median([CamSettings.ZoomStep]); 81 | fprintf( 'Serial: %s, ZoomStep: %d, FocusStep: %d\n', CamInfo.CamSerial, CamInfo.ZoomStep, CamInfo.FocusStep ); 82 | InvalidIdx = find( ... 83 | ([CamSettings.ZoomStep] ~= CamInfo.ZoomStep) | ... 84 | ([CamSettings.FocusStep] ~= CamInfo.FocusStep) | ... 85 | (SerialIdx ~= MostFreqSerialIdx)' ); 86 | 87 | if( ~isempty(InvalidIdx) ) 88 | warning('Some files mismatch'); 89 | for( iInvalid = InvalidIdx ) 90 | fprintf('Serial: %s, ZoomStep: %d, FocusStep: %d -- %s\n', CamSettings(iInvalid).CamSerial, CamSettings(iInvalid).ZoomStep, CamSettings(iInvalid).FocusStep, CamSettings(iInvalid).Fname); 91 | end 92 | fprintf('For significant deviations, it is recommended that these files be removed and the program restarted.'); 93 | else 94 | fprintf('...all files match\n'); 95 | end 96 | 97 | %---enable warning to display it once; gets disabled after first call to detectCheckerboardPoints-- 98 | warning('on','vision:calibrate:boardShouldBeAsymmetric'); 99 | fprintf('Skipping subimages with mean weight below MinSubimageWeight %g\n', CalOptions.MinSubimageWeight); 100 | 101 | %---Process each folder--- 102 | SkippedFileCount = 0; 103 | ProcessedFileCount = 0; 104 | TotFileTime = 0; 105 | %---Process each raw lenslet file--- 106 | for( iFile = 1:length(FileList) ) 107 | CurFname = FileList{iFile}; 108 | CurFname = fullfile(BasePath, CurFname); 109 | 110 | %---Build the base filename--- 111 | CurBaseFname = regexp(CurFname, BaseFnamePattern, 'tokens'); 112 | CurBaseFname = CurBaseFname{1}{1}; 113 | [~,ShortFname] = fileparts(CurBaseFname); 114 | fprintf(' --- %s [%d / %d]', ShortFname, iFile, length(FileList)); 115 | 116 | %---Check for already-decoded file--- 117 | SaveFname = sprintf(CalOptions.CheckerCornersFnamePattern, CurBaseFname); 118 | if( ~CalOptions.ForceRedoCornerFinding ) 119 | if( exist(SaveFname, 'file') ) 120 | fprintf( ' already done, skipping\n' ); 121 | SkippedFileCount = SkippedFileCount + 1; 122 | continue; 123 | end 124 | end 125 | ProcessedFileCount = ProcessedFileCount + 1; 126 | fprintf('\n'); 127 | 128 | %---Load the LF--- 129 | tic % track time 130 | load( CurFname, 'LF', 'LensletGridModel', 'DecodeOptions' ); 131 | LFSize = size(LF); 132 | 133 | if( CalOptions.ShowDisplay ) 134 | LFFigure(1); 135 | clf 136 | end 137 | 138 | fprintf('Processing all subimages'); 139 | for( TIdx = 1:LFSize(1) ) 140 | fprintf('.'); 141 | for( SIdx = 1:LFSize(2) ) 142 | % todo[optimization]: once a good set of corners is found, tracking them through s,u 143 | % and t,v would be significantly faster than independently recomputing the corners 144 | % for all u,v slices 145 | CurW = squeeze(LF(TIdx, SIdx, :,:, 4)); 146 | CurW = mean(CurW(:)); 147 | 148 | if( CurW < CalOptions.MinSubimageWeight ) 149 | CurCheckerCorners = []; 150 | else 151 | CurImg = squeeze(LF(TIdx, SIdx, :,:, 1:3)); 152 | CurImg = rgb2gray(CurImg); 153 | 154 | [CurCheckerCorners,CheckBoardSize] = detectCheckerboardPoints( CurImg ); 155 | warning('off','vision:calibrate:boardShouldBeAsymmetric'); % display once (at most) 156 | 157 | % Matlab's detectCheckerboardPoints sometimes expresses the grid in different orders, especially for 158 | % symmetric checkerbords. It's up to the consumer of this data to treat the points in the correct order. 159 | end 160 | 161 | HitCount(TIdx,SIdx) = numel(CurCheckerCorners); 162 | CheckerCorners{TIdx,SIdx} = CurCheckerCorners; 163 | end 164 | 165 | %---Display results--- 166 | if( CalOptions.ShowDisplay ) 167 | clf 168 | for( SIdx = 1:LFSize(2) ) 169 | if( HitCount(TIdx,SIdx) > 0 ) 170 | CurImg = squeeze(LF(TIdx, SIdx, :,:, 1:3)); 171 | CurImg = rgb2gray(CurImg); 172 | 173 | NImages = LFSize(2); 174 | NCols = ceil(sqrt(NImages)); 175 | NRows = ceil(NImages / NCols); 176 | subplot(NRows, NCols, SIdx); 177 | imshow(CurImg); 178 | colormap gray 179 | hold on; 180 | cx = CheckerCorners{TIdx,SIdx}(:,1); 181 | cy = CheckerCorners{TIdx,SIdx}(:,2); 182 | plot(cx(:),cy(:),'r.', 'markersize',15) 183 | axis off 184 | axis image 185 | axis tight 186 | end 187 | end 188 | %truesize([150,150]); % bigger display 189 | drawnow 190 | end 191 | end 192 | fprintf('\n'); 193 | 194 | 195 | %---Save--- 196 | fprintf('Saving result to %s...\n', SaveFname); 197 | save(SaveFname, 'GeneratedByInfo', 'CheckerCorners', 'LFSize', 'CamInfo', 'LensletGridModel', 'DecodeOptions'); 198 | 199 | TotFileTime = TotFileTime + toc; 200 | MeanFileTime = TotFileTime / ProcessedFileCount; 201 | fprintf( 'Mean time per file: %.1f min\n', MeanFileTime/60 ); 202 | TimeRemain_s = MeanFileTime * (length(FileList) - ProcessedFileCount - SkippedFileCount); 203 | fprintf( 'Est time remain: ~%d min\n', ceil(TimeRemain_s/60) ); 204 | end 205 | 206 | 207 | fprintf(' ---Finished finding checkerboard corners---\n'); -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFConvertToFloat.m: -------------------------------------------------------------------------------- 1 | % LFConvertToFloat - Helper function to convert light fields to floating-point representation 2 | % 3 | % Integer inputs get normalized to a max value of 1. 4 | 5 | % Part of LF Toolbox v0.4 released 12-Feb-2015 6 | % Copyright (c) 2013-2015 Donald G. Dansereau 7 | 8 | function LF = LFConvertToFloat( LF, Precision ) 9 | 10 | Precision = LFDefaultVal('Precision', 'single'); 11 | 12 | OrigClass = class(LF); 13 | IsInt = isinteger(LF); 14 | 15 | LF = cast(LF, Precision); 16 | 17 | if( IsInt ) 18 | LF = LF ./ cast(intmax(OrigClass), Precision); 19 | end 20 | -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFDefaultField.m: -------------------------------------------------------------------------------- 1 | % LFDefaultField - Convenience function to set up structs with default field values 2 | % 3 | % Usage: 4 | % 5 | % ParentStruct = LFDefaultField( ParentStruct, FieldName, DefaultVal ) 6 | % 7 | % This provides an elegant way to establish default field values in a struct. See LFDefaultValue for 8 | % setting up non-struct variables with default values. 9 | % 10 | % Inputs: 11 | % 12 | % ParentStruct: string giving the name of the struct; the struct need not already exist 13 | % FieldName: string giving the name of the field 14 | % DefaultVal: default value for the field 15 | % 16 | % Outputs: 17 | % 18 | % ParentStruct: if the named struct and field already existed, the output matches the struct's 19 | % original value; otherwise the output is a struct with an additional field taking 20 | % on the specified default value 21 | % 22 | % Example: 23 | % 24 | % clearvars 25 | % ExistingStruct.ExistingField = 42; 26 | % ExistingStruct = LFDefaultField( 'ExistingStruct', 'ExistingField', 3 ) 27 | % ExistingStruct = LFDefaultField( 'ExistingStruct', 'NewField', 36 ) 28 | % OtherStruct = LFDefaultField( 'OtherStruct', 'Cheese', 'Indeed' ) 29 | % 30 | % 31 | % Results in : 32 | % ExistingStruct = 33 | % ExistingField: 42 34 | % NewField: 36 35 | % OtherStruct = 36 | % Cheese: 'Indeed' 37 | % 38 | % Usage for setting up default function arguments is demonstrated in most of the LF Toolbox 39 | % functions. 40 | % 41 | % See also: LFDefaultVal 42 | 43 | % Part of LF Toolbox v0.4 released 12-Feb-2015 44 | % Copyright (c) 2013-2015 Donald G. Dansereau 45 | 46 | function ParentStruct = LFDefaultField( ParentStruct, FieldName, DefaultVal ) 47 | 48 | %---First make sure the struct exists--- 49 | CheckIfExists = sprintf('exist(''%s'', ''var'') && ~isempty(%s)', ParentStruct, ParentStruct); 50 | VarExists = evalin( 'caller', CheckIfExists ); 51 | if( ~VarExists ) 52 | ParentStruct = []; 53 | else 54 | ParentStruct = evalin( 'caller', ParentStruct ); 55 | end 56 | 57 | %---Now make sure the field exists--- 58 | if( ~isfield( ParentStruct, FieldName ) ) 59 | ParentStruct.(FieldName) = DefaultVal; 60 | end 61 | 62 | end -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFDefaultIntrinsics.m: -------------------------------------------------------------------------------- 1 | % LFDefaultIntrinsics - Initializes a set of intrinsics for use in rectifying light fields 2 | % 3 | % Usage: 4 | % 5 | % RectCamIntrinsicsH = LFDefaultIntrinsics( LFSize, CalInfo ) 6 | % 7 | % This gets called by LFCalDispRectIntrinsics to set up a default set of intrinsics for rectification. Based on the 8 | % calibration information and the dimensions of the light field, a set of intrinsics is selected which yields square 9 | % pixels in ST and UV. Ideally the values will use the hypercube-shaped light field space efficiently, leaving few black 10 | % pixels at the edges, and bumping as little information /outside/ the hypercube as possible. 11 | % 12 | % The sampling pattern yielded by the resulting intrinsics can be visualized using LFCalDispRectIntrinsics. 13 | % 14 | % Inputs : 15 | % 16 | % LFSize : Size of the light field to rectify 17 | % 18 | % CalInfo : Calibration info as loaded by LFFindCalInfo, for example. 19 | % 20 | % Outputs: 21 | % 22 | % RectCamIntrinsicsH : The resulting intrinsics. 23 | % 24 | % See also: LFCalDispRectIntrinsics, LFRecenterIntrinsics, LFFindCalInfo, LFUtilDecodeLytroFolder 25 | 26 | % Part of LF Toolbox v0.4 released 12-Feb-2015 27 | % Copyright (c) 2013-2015 Donald G. Dansereau 28 | 29 | function RectCamIntrinsicsH = LFDefaultIntrinsics( LFSize, CalInfo ) 30 | 31 | RectCamIntrinsicsH = CalInfo.EstCamIntrinsicsH; 32 | 33 | ST_ST_Slope = mean([CalInfo.EstCamIntrinsicsH(1,1), CalInfo.EstCamIntrinsicsH(2,2)]); 34 | ST_UV_Slope = mean([CalInfo.EstCamIntrinsicsH(1,3), CalInfo.EstCamIntrinsicsH(2,4)]); 35 | UV_ST_Slope = mean([CalInfo.EstCamIntrinsicsH(3,1), CalInfo.EstCamIntrinsicsH(4,2)]); 36 | UV_UV_Slope = mean([CalInfo.EstCamIntrinsicsH(3,3), CalInfo.EstCamIntrinsicsH(4,4)]); 37 | 38 | RectCamIntrinsicsH(1,1) = ST_ST_Slope; 39 | RectCamIntrinsicsH(2,2) = ST_ST_Slope; 40 | RectCamIntrinsicsH(1,3) = ST_UV_Slope; 41 | RectCamIntrinsicsH(2,4) = ST_UV_Slope; 42 | 43 | RectCamIntrinsicsH(3,1) = UV_ST_Slope; 44 | RectCamIntrinsicsH(4,2) = UV_ST_Slope; 45 | RectCamIntrinsicsH(3,3) = UV_UV_Slope; 46 | RectCamIntrinsicsH(4,4) = UV_UV_Slope; 47 | 48 | %---force s,t translation to CENTER--- 49 | RectCamIntrinsicsH = LFRecenterIntrinsics( RectCamIntrinsicsH, LFSize ); -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFDefaultVal.m: -------------------------------------------------------------------------------- 1 | % LFDefaultVal - Convenience function to set up default parameter values 2 | % 3 | % Usage: 4 | % 5 | % Var = LFDefaultVal( Var, DefaultVal ) 6 | % 7 | % 8 | % This provides an elegant way to establish default parameter values. See LFDefaultField for setting 9 | % up structs with default field values. 10 | % 11 | % Inputs: 12 | % 13 | % Var: string giving the name of the parameter 14 | % DefaultVal: default value for the parameter 15 | % 16 | % 17 | % Outputs: 18 | % 19 | % Var: if the parameter already existed, the output matches its original value, otherwise the 20 | % output takes on the specified default value 21 | % 22 | % Example: 23 | % 24 | % clearvars 25 | % ExistingVar = 42; 26 | % ExistingVar = LFDefaultVal( 'ExistingVar', 3 ) 27 | % OtherVar = LFDefaultVal( 'OtherVar', 3 ) 28 | % 29 | % Results in : 30 | % ExistingVar = 31 | % 42 32 | % OtherVar = 33 | % 3 34 | % 35 | % Usage for setting up default function arguments is demonstrated in most of the LF Toolbox 36 | % functions. 37 | % 38 | % See also: LFDefaultField 39 | 40 | % Part of LF Toolbox v0.4 released 12-Feb-2015 41 | % Copyright (c) 2013-2015 Donald G. Dansereau 42 | 43 | function Var = LFDefaultVal( Var, DefaultVal ) 44 | 45 | CheckIfExists = sprintf('exist(''%s'', ''var'') && ~isempty(%s)', Var, Var); 46 | VarExists = evalin( 'caller', CheckIfExists ); 47 | 48 | if( ~VarExists ) 49 | Var = DefaultVal; 50 | else 51 | Var = evalin( 'caller', Var ); 52 | end 53 | 54 | end -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFDispSetup.m: -------------------------------------------------------------------------------- 1 | % LFDispSetup - helper function used to set up a light field display 2 | % 3 | % Usage: 4 | % 5 | % [ImageHandle, FigureHandle] = LFDispSetup( InitialFrame ) 6 | % [ImageHandle, FigureHandle] = LFDispSetup( InitialFrame, ScaleFactor ) 7 | % 8 | % 9 | % This sets up a figure for LFDispMousePan and LFDispVidCirc. The figure is configured for 10 | % high-performance display, and subsequent calls will reuse the same figure, rather than creating a 11 | % new window on each call. The function should handle both mono and colour images. 12 | % 13 | % 14 | % Inputs: 15 | % 16 | % InitialFrame : a 2D image with which to start the display 17 | % 18 | % Optional Inputs: 19 | % 20 | % ScaleFactor : Adjusts the size of the display -- 1 means no change, 2 means twice as big, etc. 21 | % Integer values are recommended to avoid scaling artifacts. Note that the scale 22 | % factor is only applied the first time a figure is created -- i.e. the figure 23 | % must be closed to make a change to scale. 24 | % 25 | % Outputs: 26 | % 27 | % FigureHandle, ImageHandle : handles of the created objects 28 | % 29 | % 30 | % See also: LFDispVidCirc, LFDispMousePan 31 | 32 | % Part of LF Toolbox v0.4 released 12-Feb-2015 33 | % Copyright (c) 2013-2015 Donald G. Dansereau 34 | 35 | function [ImageHandle, FigureHandle] = LFDispSetup( InitialFrame, ScaleFactor ) 36 | 37 | FigureHandle = findobj('tag','LFDisplay'); 38 | if( isempty(FigureHandle) ) 39 | 40 | % Get screen size 41 | set( 0, 'units','pixels' ); 42 | ScreenSize = get( 0, 'screensize' ); 43 | ScreenSize = ScreenSize(3:4); 44 | 45 | % Get LF display size 46 | FrameSize = [size(InitialFrame,2),size(InitialFrame,1)]; 47 | 48 | % Create the figure 49 | FigureHandle = figure(... 50 | 'doublebuffer','on',... 51 | 'backingstore','off',... 52 | ...%'menubar','none',... 53 | ...%'toolbar','none',... 54 | 'tag','LFDisplay'); 55 | 56 | % Set the window's position and size 57 | WindowPos = get( FigureHandle, 'Position' ); 58 | WindowPos(3:4) = FrameSize; 59 | WindowPos(1:2) = floor( (ScreenSize - FrameSize)./2 ); 60 | set( FigureHandle, 'Position', WindowPos ); 61 | 62 | % Set the axis position and size within the figure 63 | AxesPos = [0,0,size(InitialFrame,2),size(InitialFrame,1)]; 64 | axes('units','pixels',... 65 | 'Position', AxesPos,... 66 | 'xlimmode','manual',... 67 | 'ylimmode','manual',... 68 | 'zlimmode','manual',... 69 | 'climmode','manual',... 70 | 'alimmode','manual',... 71 | 'layer','bottom'); 72 | 73 | ImageHandle = imshow(InitialFrame); 74 | % If a scaling factor is requested, apply it 75 | if( exist('ScaleFactor','var') ) 76 | truesize(floor(ScaleFactor*size(InitialFrame(:,:,1)))); 77 | end 78 | else 79 | ImageHandle = findobj(FigureHandle,'type','image'); 80 | set(ImageHandle,'cdata', InitialFrame); 81 | end 82 | 83 | -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFFindCalInfo.m: -------------------------------------------------------------------------------- 1 | % LFFindCalInfo - Find and load the calibration info file appropriate for a specific camera, zoom and focus 2 | % 3 | % Usage: 4 | % 5 | % [CalInfo, RectOptions] = LFFindCalInfo( LFMetadata, RectOptions ) 6 | % 7 | % This uses a calibration info database to locate a calibration appropriate to a given camera under a given set of zoom 8 | % and focus settings. It is called during rectification. 9 | % 10 | % Inputs: 11 | % 12 | % LFMetadata : loaded from a decoded light field, this contains the camera's serial number and zoom and focus settings. 13 | % RectOptions : struct controlling rectification 14 | % .CalibrationDatabaseFname : name of the calibration file database 15 | % 16 | % 17 | % Outputs: 18 | % 19 | % CalInfo: The resulting calibration info, or an empty array if no appropriate calibration found 20 | % RectOptions : struct controlling rectification, the following fields are added 21 | % .CalInfoFname : Name of the calibration file that was loaded 22 | % 23 | % See also: LFUtilProcessCalibrations, LFSelectFromDatabase 24 | 25 | % Part of LF Toolbox v0.4 released 12-Feb-2015 26 | % Copyright (c) 2013-2015 Donald G. Dansereau 27 | 28 | function [CalInfo, RectOptions] = LFFindCalInfo( LFMetadata, RectOptions ) 29 | 30 | CalInfo = []; 31 | 32 | DesiredCam = struct('CamSerial', LFMetadata.SerialData.camera.serialNumber, ... 33 | 'ZoomStep', LFMetadata.devices.lens.zoomStep, ... 34 | 'FocusStep', LFMetadata.devices.lens.focusStep ); 35 | CalFileInfo = LFSelectFromDatabase( DesiredCam, RectOptions.CalibrationDatabaseFname ); 36 | 37 | if( isempty(CalFileInfo) ) 38 | return; 39 | end 40 | 41 | PathToDatabase = fileparts( RectOptions.CalibrationDatabaseFname ); 42 | RectOptions.CalInfoFname = CalFileInfo.Fname; 43 | CalInfo = LFReadMetadata( fullfile(PathToDatabase, RectOptions.CalInfoFname) ); 44 | fprintf('Loading %s\n', RectOptions.CalInfoFname); 45 | 46 | %---Check that the decode options and calibration info are a good match--- 47 | fprintf('\nCalibration / LF Picture (ideally these match exactly):\n'); 48 | fprintf('Serial:\t%s\t%s\n', CalInfo.CamInfo.CamSerial, LFMetadata.SerialData.camera.serialNumber); 49 | fprintf('Zoom:\t%d\t\t%d\n', CalInfo.CamInfo.ZoomStep, LFMetadata.devices.lens.zoomStep); 50 | fprintf('Focus:\t%d\t\t%d\n\n', CalInfo.CamInfo.FocusStep, LFMetadata.devices.lens.focusStep); 51 | 52 | if( ~strcmp(CalInfo.CamInfo.CamSerial, LFMetadata.SerialData.camera.serialNumber) ) 53 | warning('Calibration is for a different camera, rectification may be invalid.'); 54 | end 55 | if( CalInfo.CamInfo.ZoomStep ~= LFMetadata.devices.lens.zoomStep || ... 56 | CalInfo.CamInfo.FocusStep ~= LFMetadata.devices.lens.focusStep ) 57 | warning('Zoom / focus mismatch -- for significant deviations rectification may be invalid.'); 58 | end 59 | 60 | -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFFindLytroPartnerFile.m: -------------------------------------------------------------------------------- 1 | % LFFindLytroPartnerFile - Finds metadata / raw data file partner for Lytro white images 2 | % 3 | % Usage: 4 | % 5 | % PartnerFilename = LFFindLytroPartnerFile( OrigFilename, PartnerFilenameExtension ) 6 | % 7 | % The LF Reader tool prepends filenames extracted from LFP storage files, complicating .txt / .raw 8 | % file association as the prefix can vary between two files in a pair. This function finds a file's 9 | % partner based on a known filename pattern (using underscores to separate the base filename), and a 10 | % know partner filename extension. Note this is set up to work specifically with the naming 11 | % conventions used by the LFP Reader tool. 12 | % 13 | % Inputs: 14 | % OrigFilename is the known filename 15 | % PartnerFilenameExtension is the extension of the file to find 16 | % 17 | % Output: 18 | % PartnerFilename is the name of the first file found matching the specified extension 19 | % 20 | % See also: LFUtilProcessWhiteImages, LFUtilProcessCalibrations 21 | 22 | % Part of LF Toolbox v0.4 released 12-Feb-2015 23 | % Copyright (c) 2013-2015 Donald G. Dansereau 24 | 25 | function PartnerFilename = LFFindLytroPartnerFile( OrigFilename, PartnerFilenameExtension ) 26 | 27 | [CurFnamePath, CurFnameBase] = fileparts( OrigFilename ); 28 | PrependIdx = find(CurFnameBase == '_', 1); 29 | CurFnamePattern = strcat('*', CurFnameBase(PrependIdx:end), PartnerFilenameExtension); 30 | DirResult = dir(fullfile(CurFnamePath, CurFnamePattern)); 31 | DirResult = DirResult(1).name; 32 | PartnerFilename = fullfile(CurFnamePath, DirResult); 33 | 34 | end -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFGatherCamInfo.m: -------------------------------------------------------------------------------- 1 | % LFGatherCamInfo - collect metadata from a folder of processed white images or calibrations 2 | % 3 | % Usage: 4 | % 5 | % CamInfo = LFGatherCamInfo( FilePath, FilenamePattern ) 6 | % 7 | % 8 | % This function is designed to work with one of two sources of information: a folder of Lytro white 9 | % images, as extracted from the calibration data using an LFP tool; or a folder of calibrations, as 10 | % generated by LFUtilCalLensletCam. 11 | % 12 | % Inputs: 13 | % 14 | % FilePath is a path to the folder containing either the white images or the calibration files. 15 | % 16 | % FilenamePattern is a pattern, with wildcards, identifying the metadata files to process. Typical 17 | % values are 'CalInfo*.json' for calibration info, and '*T1CALIB__MOD_*.TXT' for white images. 18 | % 19 | % Outputs: 20 | % 21 | % CamInfo is a struct array containing zoom, focus and filename info for each file. Exposure info 22 | % is also included for white images. 23 | % 24 | % See LFUtilProcessCalibrations and LFUtilProcessWhiteImages for example usage. 25 | % 26 | % See also: LFUtilProcessWhiteImages, LFUtilProcessCalibrations 27 | 28 | % Part of LF Toolbox v0.4 released 12-Feb-2015 29 | % Copyright (c) 2013-2015 Donald G. Dansereau 30 | 31 | function CamInfo = LFGatherCamInfo( FilePath, FilenamePattern ) 32 | 33 | %---Locate all input files--- 34 | [FileNames, BasePath] = LFFindFilesRecursive( FilePath, FilenamePattern ); 35 | if( isempty(FileNames) ) 36 | error('No files found'); 37 | end 38 | fprintf('Found :\n'); 39 | disp(FileNames) 40 | 41 | %---Process each--- 42 | fprintf('Filename, Camera Model / Serial, ZoomStep, FocusStep\n'); 43 | for( iFile = 1:length(FileNames) ) 44 | CurFname = FileNames{iFile}; 45 | CurFileInfo = LFReadMetadata( fullfile(BasePath, CurFname) ); 46 | 47 | CurCamInfo = []; 48 | if( isfield( CurFileInfo, 'CamInfo' ) ) 49 | 50 | %---Calibration file--- 51 | CurCamInfo = CurFileInfo.CamInfo; 52 | 53 | elseif( isfield( CurFileInfo, 'master' ) ) 54 | 55 | %---Lytro TXT metadata file associated with white image--- 56 | CurCamInfo.ZoomStep = CurFileInfo.master.picture.frameArray.frame.metadata.devices.lens.zoomStep; 57 | CurCamInfo.FocusStep = CurFileInfo.master.picture.frameArray.frame.metadata.devices.lens.focusStep; 58 | CurCamInfo.ExposureDuration = CurFileInfo.master.picture.frameArray.frame.metadata.devices.shutter.frameExposureDuration; 59 | CurCamInfo.CamSerial = CurFileInfo.master.picture.frameArray.frame.privateMetadata.camera.serialNumber; 60 | CurCamInfo.CamModel = CurFileInfo.master.picture.frameArray.frame.metadata.camera.model; 61 | 62 | else 63 | 64 | error('Unrecognized file format reading metadata\n'); 65 | 66 | end 67 | 68 | fprintf(' %s :\t%s / %s, %d, %d\n', CurFname, CurCamInfo.CamModel, CurCamInfo.CamSerial, CurCamInfo.ZoomStep, CurCamInfo.FocusStep); 69 | 70 | CurCamInfo.Fname = CurFname; 71 | CamInfo(iFile) = CurCamInfo; 72 | end 73 | -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFHelperBuild2DFreq.m: -------------------------------------------------------------------------------- 1 | % LFHelperBuild2DFreq - Helper function used to construct 2D frequency-domain filters 2 | % 3 | % Much of the complexity in constructing MD frequency-domain filters, especially around including aliased components and 4 | % controlling the filter rolloff, is common between filter shapes. This function wraps much of this complexity. 5 | % 6 | % This gets called by the LFBuild2DFreq* functions. 7 | 8 | % Part of LF Toolbox v0.4 released 12-Feb-2015 9 | % Copyright (c) 2013-2015 Donald G. Dansereau 10 | 11 | function [H, FiltOptions] = LFHelperBuild2DFreq( LFSize, BW, FiltOptions, DistFunc ) 12 | 13 | FiltOptions = LFDefaultField('FiltOptions', 'Precision', 'single'); 14 | FiltOptions = LFDefaultField('FiltOptions', 'Rolloff', 'Gaussian'); %Gaussian or Butter 15 | FiltOptions = LFDefaultField('FiltOptions', 'Aspect2D', 1); 16 | FiltOptions = LFDefaultField('FiltOptions', 'Window', false); 17 | FiltOptions = LFDefaultField('FiltOptions', 'Extent2D', 1.0); 18 | FiltOptions = LFDefaultField('FiltOptions', 'IncludeAliased', false); 19 | 20 | FiltOptions.Extent2D = cast(FiltOptions.Extent2D, FiltOptions.Precision); % avoid rounding error during comparisons 21 | FiltOptions.Aspect2D = cast(FiltOptions.Aspect2D, FiltOptions.Precision); % avoid rounding error during comparisons 22 | 23 | if( length(LFSize) == 1 ) 24 | LFSize = LFSize .* [1,1]; 25 | end 26 | if( length(FiltOptions.Extent2D) == 1 ) 27 | FiltOptions.Extent2D = FiltOptions.Extent2D .* [1,1]; 28 | end 29 | if( length(FiltOptions.Aspect2D) == 1 ) 30 | FiltOptions.Aspect2D = FiltOptions.Aspect2D .* [1,1]; 31 | end 32 | ExtentWithAspect = FiltOptions.Extent2D.*FiltOptions.Aspect2D / 2; 33 | 34 | s = LFNormalizedFreqAxis( LFSize(1), FiltOptions.Precision ) .* FiltOptions.Aspect2D(1); 35 | u = LFNormalizedFreqAxis( LFSize(2), FiltOptions.Precision ) .* FiltOptions.Aspect2D(2); 36 | [ss,uu] = ndgrid(s,u); 37 | P = [ss(:),uu(:)]'; 38 | clear s u ss uu 39 | 40 | if( ~FiltOptions.IncludeAliased ) 41 | Tiles = [0,0]; 42 | else 43 | Tiles = ceil(ExtentWithAspect); 44 | end 45 | 46 | if( FiltOptions.IncludeAliased ) 47 | AADist = inf(LFSize, FiltOptions.Precision); 48 | end 49 | WinDist = 0; 50 | 51 | % Tiling proceeds only in positive directions, symmetry is enforced afterward, saving some computation overall 52 | for( STile = 0:Tiles(1) ) 53 | for( UTile = 0:Tiles(2) ) 54 | Dist = inf(LFSize, FiltOptions.Precision); 55 | 56 | if( FiltOptions.Window ) 57 | ValidIdx = ':'; 58 | WinDist = bsxfun(@minus, abs(P)', ExtentWithAspect); 59 | WinDist = sum(max(0,WinDist).^2, 2); 60 | WinDist = reshape(WinDist, LFSize); 61 | else 62 | ValidIdx = find(all(bsxfun(@le, abs(P), ExtentWithAspect'))); 63 | end 64 | 65 | Dist(ValidIdx) = DistFunc(P(:,ValidIdx), FiltOptions); 66 | Dist = Dist + WinDist; 67 | 68 | if( FiltOptions.IncludeAliased ) 69 | AADist(:) = min(AADist(:), Dist(:)); 70 | end 71 | 72 | P(2,:) = P(2,:) + FiltOptions.Aspect2D(2); 73 | end 74 | P(2,:) = P(2,:) - (Tiles(2)+1) .* FiltOptions.Aspect2D(2); 75 | P(1,:) = P(1,:) + FiltOptions.Aspect2D(1); 76 | end 77 | 78 | if( FiltOptions.IncludeAliased ) 79 | Dist = AADist; 80 | clear AADist 81 | end 82 | 83 | H = zeros(LFSize, FiltOptions.Precision); 84 | 85 | switch lower(FiltOptions.Rolloff) 86 | case 'gaussian' 87 | BW = BW.^2 / log(sqrt(2)); 88 | H(:) = exp( -Dist / BW ); % Gaussian rolloff 89 | 90 | case 'butter' 91 | FiltOptions = LFDefaultField('FiltOptions', 'Order', 3); 92 | Dist = sqrt(Dist) ./ BW; 93 | H(:) = sqrt( 1.0 ./ (1.0 + Dist.^(2*FiltOptions.Order)) ); % Butterworth-like rolloff 94 | 95 | otherwise 96 | error('unrecognized rolloff method'); 97 | 98 | end 99 | 100 | H = ifftshift(H); 101 | 102 | % force symmetric 103 | H = max(H, H(mod(LFSize(1):-1:1,LFSize(1))+1, mod(LFSize(2):-1:1,LFSize(2))+1)); 104 | 105 | -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFHelperBuild4DFreq.m: -------------------------------------------------------------------------------- 1 | % LFHelperBuild4DFreq - Helper function used to construct 4D frequency-domain filters 2 | % 3 | % Much of the complexity in constructing MD frequency-domain filters, especially around including aliased components and 4 | % controlling the filter rolloff, is common between filter shapes. This function wraps much of this complexity. 5 | % 6 | % This gets called by the LFBuild4DFreq* functions. 7 | 8 | % Part of LF Toolbox v0.4 released 12-Feb-2015 9 | % Copyright (c) 2013-2015 Donald G. Dansereau 10 | 11 | function [H, FiltOptions] = LFHelperBuild4DFreq( LFSize, BW, FiltOptions, DistFunc ) 12 | 13 | FiltOptions = LFDefaultField('FiltOptions', 'Precision', 'single'); 14 | FiltOptions = LFDefaultField('FiltOptions', 'Rolloff', 'Gaussian'); %Gaussian or Butter 15 | FiltOptions = LFDefaultField('FiltOptions', 'Aspect4D', 1); 16 | FiltOptions = LFDefaultField('FiltOptions', 'Window', false); 17 | FiltOptions = LFDefaultField('FiltOptions', 'Extent4D', 1.0); 18 | FiltOptions = LFDefaultField('FiltOptions', 'IncludeAliased', false); 19 | 20 | FiltOptions.Extent4D = cast(FiltOptions.Extent4D, FiltOptions.Precision); % avoid rounding error during comparisons 21 | FiltOptions.Aspect4D = cast(FiltOptions.Aspect4D, FiltOptions.Precision); % avoid rounding error during comparisons 22 | 23 | if( length(LFSize) == 1 ) 24 | LFSize = LFSize .* [1,1,1,1]; 25 | end 26 | if( length(LFSize) == 5 ) 27 | LFSize = LFSize(1:4); 28 | end 29 | if( length(FiltOptions.Extent4D) == 1 ) 30 | FiltOptions.Extent4D = FiltOptions.Extent4D .* [1,1,1,1]; 31 | end 32 | if( length(FiltOptions.Aspect4D) == 1 ) 33 | FiltOptions.Aspect4D = FiltOptions.Aspect4D .* [1,1,1,1]; 34 | end 35 | ExtentWithAspect = FiltOptions.Extent4D.*FiltOptions.Aspect4D / 2; 36 | 37 | t = LFNormalizedFreqAxis( LFSize(1), FiltOptions.Precision ) .* FiltOptions.Aspect4D(1); 38 | s = LFNormalizedFreqAxis( LFSize(2), FiltOptions.Precision ) .* FiltOptions.Aspect4D(2); 39 | v = LFNormalizedFreqAxis( LFSize(3), FiltOptions.Precision ) .* FiltOptions.Aspect4D(3); 40 | u = LFNormalizedFreqAxis( LFSize(4), FiltOptions.Precision ) .* FiltOptions.Aspect4D(4); 41 | [tt,ss,vv,uu] = ndgrid(cast(t,FiltOptions.Precision),cast(s,FiltOptions.Precision),cast(v,FiltOptions.Precision),cast(u,FiltOptions.Precision)); 42 | P = [tt(:),ss(:),vv(:),uu(:)]'; 43 | clear s t u v ss tt uu vv 44 | 45 | if( ~FiltOptions.IncludeAliased ) 46 | Tiles = [0,0,0,0]; 47 | else 48 | Tiles = ceil(ExtentWithAspect); 49 | end 50 | 51 | if( FiltOptions.IncludeAliased ) 52 | AADist = inf(LFSize, FiltOptions.Precision); 53 | end 54 | WinDist = 0; 55 | 56 | % Tiling proceeds only in positive directions, symmetry is enforced afterward, saving some computation overall 57 | for( TTile = 0:Tiles(1) ) 58 | for( STile = 0:Tiles(2) ) 59 | for( VTile = 0:Tiles(3) ) 60 | for( UTile = 0:Tiles(4) ) 61 | Dist = inf(LFSize, FiltOptions.Precision); 62 | 63 | if( FiltOptions.Window ) 64 | ValidIdx = ':'; 65 | WinDist = bsxfun(@minus, abs(P)', ExtentWithAspect); 66 | WinDist = sum(max(0,WinDist).^2, 2); 67 | WinDist = reshape(WinDist, LFSize); 68 | else 69 | ValidIdx = find(all(bsxfun(@le, abs(P), ExtentWithAspect'))); 70 | end 71 | 72 | Dist(ValidIdx) = DistFunc(P(:,ValidIdx), FiltOptions); 73 | Dist = Dist + WinDist; 74 | 75 | if( FiltOptions.IncludeAliased ) 76 | AADist(:) = min(AADist(:), Dist(:)); 77 | end 78 | 79 | P(4,:) = P(4,:) + FiltOptions.Aspect4D(4); 80 | end 81 | P(4,:) = P(4,:) - (Tiles(4)+1) .* FiltOptions.Aspect4D(4); 82 | P(3,:) = P(3,:) + FiltOptions.Aspect4D(3); 83 | end 84 | P(3,:) = P(3,:) - (Tiles(3)+1) .* FiltOptions.Aspect4D(3); 85 | P(2,:) = P(2,:) + FiltOptions.Aspect4D(2); 86 | end 87 | P(2,:) = P(2,:) - (Tiles(2)+1) .* FiltOptions.Aspect4D(2); 88 | P(1,:) = P(1,:) + FiltOptions.Aspect4D(1); 89 | end 90 | 91 | if( FiltOptions.IncludeAliased ) 92 | Dist = AADist; 93 | clear AADist 94 | end 95 | 96 | H = zeros(LFSize, FiltOptions.Precision); 97 | 98 | switch lower(FiltOptions.Rolloff) 99 | case 'gaussian' 100 | BW = BW.^2 / log(sqrt(2)); 101 | H(:) = exp( -Dist / BW ); % Gaussian rolloff 102 | 103 | case 'butter' 104 | FiltOptions = LFDefaultField('FiltOptions', 'Order', 3); 105 | Dist = sqrt(Dist) ./ BW; 106 | H(:) = sqrt( 1.0 ./ (1.0 + Dist.^(2*FiltOptions.Order)) ); % Butterworth-like rolloff 107 | 108 | otherwise 109 | error('unrecognized rolloff method'); 110 | 111 | end 112 | 113 | H = ifftshift(H); 114 | 115 | % force symmetric 116 | H = max(H, H(mod(LFSize(1):-1:1,LFSize(1))+1, mod(LFSize(2):-1:1,LFSize(2))+1,mod(LFSize(3):-1:1,LFSize(3))+1,mod(LFSize(4):-1:1,LFSize(4))+1)); 117 | -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFMapRectifiedToMeasured.m: -------------------------------------------------------------------------------- 1 | % LFMapRectifiedToMeasured - Applies a calibrated camera model to map desired samples to measured samples 2 | % 3 | % Usage: 4 | % 5 | % InterpIdx = LFMapRectifiedToMeasured( InterpIdx, CalInfo, RectOptions ) 6 | % 7 | % Helper function used by LFCalRectifyLF. Based on a calibrated camera model, including distortion parameters and a 8 | % desired intrinsic matrix, the indices of a set of desired sample is mapped to the indices of corresponding measured 9 | % samples. 10 | % 11 | % Inputs : 12 | % 13 | % InterpIdx : Set of desired indices, in homogeneous coordinates 14 | % CalInfo : Calibration info as returned by LFFindCalInfo 15 | % RectOptions : struct controlling the rectification process, see LFCalRectify 16 | % 17 | % Outputs: 18 | % 19 | % InterpIdx : continuous-domain indices for interpolating from the measured light field 20 | % 21 | % See also: LFCalRectifyLF 22 | 23 | % Part of LF Toolbox v0.4 released 12-Feb-2015 24 | % Copyright (c) 2013-2015 Donald G. Dansereau 25 | 26 | function InterpIdx = LFMapRectifiedToMeasured( InterpIdx, CalInfo, RectOptions ) 27 | 28 | RectOptions = LFDefaultField( 'RectOptions', 'Precision', 'single' ); 29 | 30 | %---Cast the to the required precision--- 31 | InterpIdx = cast(InterpIdx, RectOptions.Precision); 32 | 33 | %---Convert the index of the desired ray to a ray representation using ideal intrinsics--- 34 | InterpIdx = RectOptions.RectCamIntrinsicsH * InterpIdx; 35 | 36 | %---Apply inverse lens distortion to yield the undistorted ray--- 37 | k1 = CalInfo.EstCamDistortionV(1); % r^2 38 | k2 = CalInfo.EstCamDistortionV(2); % r^4 39 | k3 = CalInfo.EstCamDistortionV(3); % r^6 40 | b1 = CalInfo.EstCamDistortionV(4); % decentering of lens distortion 41 | b2 = CalInfo.EstCamDistortionV(5); % decentering of lens distortion 42 | 43 | InterpIdx(3:4,:) = bsxfun(@minus, InterpIdx(3:4,:), [b1; b2]); % decentering of lens distortion 44 | 45 | %---Iteratively estimate the undistorted direction---- 46 | DesiredDirection = InterpIdx(3:4,:); 47 | for( InverseIters = 1:RectOptions.NInverse_Distortion_Iters ) 48 | R2 = sum(InterpIdx(3:4,:).^2); % compute radius^2 for the current estimate 49 | % update estimate based on inverse of distortion model 50 | InterpIdx(3:4,:) = DesiredDirection ./ repmat((1 + k1.*R2 + k2.*R2.^2 + k3.*R2.^4),2,1); 51 | end 52 | clear R2 DesiredDirection 53 | 54 | InterpIdx(3:4,:) = bsxfun(@plus, InterpIdx(3:4,:), [b1; b2]); % decentering of lens distortion 55 | 56 | %---Convert the undistorted ray to the corresponding index using the calibrated intrinsics--- 57 | % todo[optimization]: The variable InterpIdx could be precomputed and saved with the calibration 58 | InterpIdx = CalInfo.EstCamIntrinsicsH^-1 * InterpIdx; 59 | 60 | %---Interpolate the required values--- 61 | InterpIdx = InterpIdx(1:4,:); % drop homogeneous coordinates 62 | -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFNormalizedFreqAxis.m: -------------------------------------------------------------------------------- 1 | % LFNormalizedFreqAxis - Helper function to construct a frequency axis 2 | % 3 | % Output range is from -0.5 to 0.5. This is designed so that the zero frequency matches the fftshifted output of the 4 | % fft algorithm. 5 | 6 | % Part of LF Toolbox v0.4 released 12-Feb-2015 7 | % Copyright (c) 2013-2015 Donald G. Dansereau 8 | 9 | function f = LFNormalizedFreqAxis( NSamps, Precision ) 10 | 11 | Precision = LFDefaultVal( 'Precision', 'double' ); 12 | 13 | if( NSamps == 1 ) 14 | f = 0; 15 | elseif( mod(NSamps,2) ) 16 | f = [-(NSamps-1)/2:(NSamps-1)/2]/(NSamps-1); 17 | else 18 | f = [-NSamps/2:(NSamps/2-1)]/NSamps; 19 | end 20 | 21 | f = cast(f, Precision); -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFRotz.m: -------------------------------------------------------------------------------- 1 | % LFRotz - simple 3D rotation matrix, rotation about z 2 | % 3 | % Usage: 4 | % R = LFRotz( psi ) 5 | % 6 | 7 | % Part of LF Toolbox v0.4 released 12-Feb-2015 8 | % Copyright (c) 2013-2015 Donald G. Dansereau 9 | 10 | function R = LFRotz(psi) 11 | 12 | c = cos(psi); 13 | s = sin(psi); 14 | 15 | R = [ c, -s, 0; ... 16 | s, c, 0; ... 17 | 0, 0, 1 ]; 18 | -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFSelectFromDatabase.m: -------------------------------------------------------------------------------- 1 | % LFSelectFromDatabase - support function for selecting white image/calibration by matching serial/zoom/focus 2 | % 3 | % Usage: 4 | % 5 | % SelectedCamInfo = LFSelectFromDatabase( DesiredCamInfo, DatabaseFname ) 6 | % 7 | % This helper function is used when decoding a light field to select an appropriate white image, 8 | % and when rectifying a light field to select the appropriate calibration. It works by parsing a 9 | % database (white image or calibration), and searching its CamInfo structure for the best match to 10 | % the requested DesiredCamInfo. DesiredCamInfo is set based on the camera settings used in 11 | % measuring the light field. See LFUtilDecodeLytroFolder / LFLytroDecodeImage for example usage. 12 | % 13 | % Selection prioritizes the camera serial number, then zoom, then focus. It is unclear whether this 14 | % is the optimal approach. 15 | % 16 | % The output SelectedCamInfo includes all fields in the database's CamInfo struct, including the 17 | % filename of the selected calibration or white image. This facilitates decoding / rectification. 18 | % 19 | % See also: LFUtilProcessWhiteImages, LFUtilProcessCalibrations, LFUtilDecodeLytroFolder, LFLytroDecodeImage 20 | 21 | % Part of LF Toolbox v0.4 released 12-Feb-2015 22 | % Copyright (c) 2013-2015 Donald G. Dansereau 23 | 24 | function SelectedCamInfo = LFSelectFromDatabase( DesiredCamInfo, DatabaseFname ) 25 | 26 | %---Load the database--- 27 | load(DatabaseFname, 'CamInfo'); 28 | 29 | %---Find the closest to the desired settings, prioritizing serial, then zoom, then focus--- 30 | ValidSerial = find( ismember({CamInfo.CamSerial}, {DesiredCamInfo.CamSerial}) ); 31 | 32 | % Discard non-matching serials 33 | CamInfo = CamInfo(ValidSerial); 34 | OrigIdx = ValidSerial; 35 | 36 | % Find closest zoom 37 | ZoomDiff = abs([CamInfo.ZoomStep] - DesiredCamInfo.ZoomStep); 38 | BestZoomDiff = min(ZoomDiff); 39 | BestZoomIdx = find( ZoomDiff == BestZoomDiff ); % generally multiple hits 40 | 41 | % Retain the (possibly multiple) matches for the best zoom setting 42 | % CamInfo.ZoomStep = CamInfo(BestZoomIdx).ZoomStep; 43 | CamInfo = CamInfo(BestZoomIdx); 44 | OrigIdx = OrigIdx(BestZoomIdx); 45 | 46 | % Of those that are closest in zoom, find the one that's closest in focus 47 | FocusDiff = abs([CamInfo.FocusStep] - DesiredCamInfo.FocusStep); 48 | [~,BestFocusIdx] = min(FocusDiff); 49 | 50 | % Retrieve the index into the original 51 | BestOriglIdx = OrigIdx(BestFocusIdx); 52 | SelectedCamInfo = CamInfo(BestFocusIdx); 53 | 54 | 55 | -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFSign.m: -------------------------------------------------------------------------------- 1 | % LFSign - Like Matlab's sign, but never returns 0, treating 0 as positive 2 | 3 | % Part of LF Toolbox v0.4 released 12-Feb-2015 4 | % Copyright (c) 2013-2015 Donald G. Dansereau 5 | 6 | function s = LFSign(i) 7 | 8 | s = ones(size(i)); 9 | s(i<0) = -1; -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFStruct2Var.m: -------------------------------------------------------------------------------- 1 | % LFStruct2Var - Convenience function to break a subset of variables out of a struct 2 | % 3 | % Usage: 4 | % [var1, var2, ...] = LFStruct2Var( StructIn, 'var1', 'var2', ... ) 5 | % 6 | % This would ideally exclude the named variables in the argument list, but there was no elegant way 7 | % to do this given the absence of an `outputname' function to match Matlab's `inputname'. 8 | % 9 | % Example: 10 | % FruitCount = struct('Apples', 3, 'Bacon', 42, 'Oranges', 4); 11 | % [Apples, Oranges] = LFStruct2Var( FruitCount, 'Apples', 'Oranges' ) 12 | % 13 | % Results in 14 | % Apples = 15 | % 3 16 | % Oranges = 17 | % 4 18 | % 19 | % See also: LFStruct2Var 20 | 21 | % Part of LF Toolbox v0.4 released 12-Feb-2015 22 | % Copyright (c) 2013-2015 Donald G. Dansereau 23 | 24 | function varargout = LFStruct2Var( StructIn, varargin ) 25 | 26 | for( i=1:length(varargin) ) 27 | varargout{i} = StructIn.(varargin{i}); 28 | end 29 | 30 | end -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFToolboxVersion.m: -------------------------------------------------------------------------------- 1 | % LFToolboxVersion - returns a string describing the current toolbox version 2 | 3 | % Part of LF Toolbox v0.4 released 12-Feb-2015 4 | % Copyright (c) 2013-2015 Donald G. Dansereau 5 | 6 | function VersionStr = LFToolboxVersion 7 | VersionStr = 'v0.4 released 12-Feb-2015'; -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFUnpackRawBuffer.m: -------------------------------------------------------------------------------- 1 | % LFUnpackRawBuffer - Unpack a buffer of packed raw binary data into an image 2 | % 3 | % Usage: 4 | % 5 | % ImgOut = LFUnpackRawBuffer( Buff, BitPacking, ImgSize ) 6 | % 7 | % Used by LFReadRaw and LFReadLFP, this helper function unpacks a raw binary data buffer in one of several formats. 8 | % 9 | % Inputs : 10 | % 11 | % Buff : Buffer of chars to be unpacked 12 | % BitPacking : one of '12bit', '10bit' or '16bit'; default is '12bit' 13 | % ImgSize : size of the output image 14 | % 15 | % Outputs: 16 | % 17 | % Img : an array of uint16 gray levels. No demosaicing (decoding Bayer pattern) is performed. 18 | % 19 | % See also: LFDecodeLensletImageSimple, demosaic 20 | 21 | % Part of LF Toolbox v0.4 released 12-Feb-2015 22 | % Copyright (c) 2013-2015 Donald G. Dansereau 23 | 24 | function ImgOut = LFUnpackRawBuffer( Buff, BitPacking, ImgSize ) 25 | 26 | switch( BitPacking ) 27 | case '8bit' 28 | ImgOut = reshape(Buff, ImgSize); 29 | 30 | case '10bit' 31 | t0 = uint16(Buff(1:5:end)); 32 | t1 = uint16(Buff(2:5:end)); 33 | t2 = uint16(Buff(3:5:end)); 34 | t3 = uint16(Buff(4:5:end)); 35 | lsb = uint16(Buff(5:5:end)); 36 | 37 | t0 = bitshift(t0,2); 38 | t1 = bitshift(t1,2); 39 | t2 = bitshift(t2,2); 40 | t3 = bitshift(t3,2); 41 | 42 | t0 = t0 + bitand(lsb,bin2dec('00000011')); 43 | t1 = t1 + bitshift(bitand(lsb,bin2dec('00001100')),-2); 44 | t2 = t2 + bitshift(bitand(lsb,bin2dec('00110000')),-4); 45 | t3 = t3 + bitshift(bitand(lsb,bin2dec('11000000')),-6); 46 | 47 | ImgOut = zeros(ImgSize, 'uint16'); 48 | ImgOut(1:4:end) = t0; 49 | ImgOut(2:4:end) = t1; 50 | ImgOut(3:4:end) = t2; 51 | ImgOut(4:4:end) = t3; 52 | 53 | case '12bit' 54 | t0 = uint16(Buff(1:3:end)); 55 | t1 = uint16(Buff(2:3:end)); 56 | t2 = uint16(Buff(3:3:end)); 57 | 58 | a0 = bitshift(t0,4) + bitshift(bitand(t1,bin2dec('11110000')),-4); 59 | a1 = bitshift(bitand(t1,bin2dec('00001111')),8) + t2; 60 | 61 | ImgOut = zeros(ImgSize, 'uint16'); 62 | ImgOut(1:2:end) = a0; 63 | ImgOut(2:2:end) = a1; 64 | 65 | case '16bit' 66 | t0 = uint16(Buff(1:2:end)); 67 | t1 = uint16(Buff(2:2:end)); 68 | a0 = bitshift(t1, 8) + t0; 69 | ImgOut = zeros(ImgSize, 'uint16'); 70 | ImgOut(:) = a0; 71 | 72 | otherwise 73 | error('Unrecognized bit packing'); 74 | end -------------------------------------------------------------------------------- /LFToolbox0.4/SupportFunctions/LFVar2Struct.m: -------------------------------------------------------------------------------- 1 | % LFVar2Struct - Convenience function to build a struct from a set of variables 2 | % 3 | % Usage: 4 | % StructOut = LFVar2Struct( var1, var2, ... ) 5 | % 6 | % Example: 7 | % Apples = 3; 8 | % Oranges = 4; 9 | % FruitCount = LFVar2Struct( Apples, Oranges ) 10 | % 11 | % Results in a struct FruitCount: 12 | % FruitCount = 13 | % Apples: 3 14 | % Oranges: 4 15 | % 16 | % See also: LFStruct2Var 17 | 18 | % Part of LF Toolbox v0.4 released 12-Feb-2015 19 | % Copyright (c) 2013-2015 Donald G. Dansereau 20 | 21 | function StructOut = LFVar2Struct( varargin ) 22 | 23 | VarNames = arrayfun( @inputname, 1:nargin, 'UniformOutput', false ); 24 | StructOut = cell2struct( varargin, VarNames, 2 ); 25 | 26 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # light-field-toolbox 2 | Light Field Toolbox v0.4 3 | by Donald Dansereau 4 | 5 | 12 Feb 2015 (Updated 12 Feb 2015) 6 | A set of tools for working with light field (aka plenoptic) imagery in Matlab. 7 | 8 | Please see [the link]. 9 | [the link]:https://www.mathworks.com/matlabcentral/fileexchange/49683-light-field-toolbox-v0-4 10 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Donald Dansereau 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the distribution 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | --------------------------------------------------------------------------------