代码拉取完成,页面将自动刷新
% LFUtilDecodeLytroFolder - decode and optionally colour correct and rectify Lytro light fields
%
% Usage:
%
% LFUtilDecodeLytroFolder
% LFUtilDecodeLytroFolder( InputPath )
% LFUtilDecodeLytroFolder( InputPath, FileOptions, DecodeOptions, RectOptions )
% LFUtilDecodeLytroFolder( InputPath, [], [], RectOptions )
%
% All parameters are optional and take on default values as set in the "Defaults" section at the top
% of the implementation. As such, this can be called as a function or run directly by editing the
% code. When calling as a function, pass an empty array "[]" to omit a parameter.
%
% As released, the default values are set up to match the naming conventions of LFP Reader v2.0.0.
%
% This function demonstrates decoding and optionally colour-correction and rectification of 2D
% lenslet images into 4D light fields. It recursively crawls through a prescribed folder and its
% subfolders, operating on each light field. It can be used incrementally: previously-decoded light
% fields can be subsequently colour-corected, rectified, or both. Previously-completed tasks will
% not be re-applied. A filename pattern can be provided to work on individual files. All paths and
% naming are configurable.
%
% Decoding and rectification follow the process described in:
%
% [1] D. G. Dansereau, O. Pizarro, and S. B. Williams, "Decoding, calibration and rectification for
% lenslet-based plenoptic cameras," in Computer Vision and Pattern Recognition (CVPR), IEEE
% Conference on. IEEE, Jun 2013.
%
% Decoding requires that an appropriate database of white images be created using
% LFUtilProcessWhiteImages. Rectification similarly requires a calibration database be created using
% LFUtilProcessCalibrations.
%
% To decode a single light field, it is simplest to include a file specification in InputPath (see
% below). It is also possible to call LFLytroDecodeImage directly.
%
% Colour correction employs the metadata associated with each Lytro picture. It also applies
% histogram-based contrast adjustment. It calls the functions LFColourCorrect and LFHistEqualize.
%
% Rectification employs a calibration info file to rectify the light field, correcting for lens
% distortion, making pixels square, and yielding an intrinsics matrix which allows easy conversion
% from a pixel index [i,j,k,l] to a ray [s,t,u,v]. A calibration info file is generated by
% processing a series of checkeboard images, following the calibration procedure described in
% LFToolbox.pdf. A calibration only applies to one specific camera at one specific zoom and focus
% setting, and decoded using one specific lenslet grid model. The tool LFUtilProcessCalibrations is
% used to build a database of rectifications, and LFSelectFromDatabase isused to select a
% calibration appropriate to a given light field.
%
% This function was written to deal with Lytro imagery, but adapting it to operate with other
% lenslet-based cameras should be straightforward. For more information on the decoding process,
% refer to LFDecodeLensletImageDirect, [1], and LFToolbox.pdf.
%
% Some optional parameters are not used or documented at this level -- see each of LFCalRectifyLF,
% LFLytroDecodeImage, LFDecodeLensletImageDirect, and LFColourCorrect for further information.
%
%
% Inputs -- all are optional, see code below for default values :
%
% InputPath : Path to folder containing light fields, or to a specific light field, optionally including one or
% more wildcard filename specifications. In case wildcards are used, this searches sub-folders recursively. See
% LFFindFilesRecursive.m for more information and examples of how InputPath is interpreted.
%
% FileOptions : struct controlling file naming and saving
% .SaveResult : Set to false to perform a "dry run"
% .ForceRedo : If true previous results are ignored and decoding starts from scratch
% .SaveFnamePattern : String defining the pattern used in generating the output filename;
% sprintf is used to complete this pattern, such that %s gets replaced
% with the base name of the input light field
% .ThumbFnamePattern : As with SaveFnamePattern, defines the name of the output thumbnail
% image
%
% DecodeOptions : struct controlling the decoding process, see LFDecodeLensletImageDirect for more info
% .OptionalTasks : Cell array containing any combination of 'ColourCorrect' and
% 'Rectify'; an empty array "{}" means no additional tasks are
% requested; case sensitive
% .LensletImageFnamePattern : Pattern used to locate input files -- the pattern %s stands in
% for the base filename
% .ColourHistThresh : Threshold used by LFHistEqualize in optional colour correction
% .WhiteImageDatabasePath : Full path to the white images database, as created by
% LFUtilProcessWhiteImages
% .DoDehex : Controls whether hexagonal sampling is converted to rectangular, default true
% .DoSquareST : Controls whether s,t dimensions are resampled to square pixels, default true
% .ResampMethod : 'fast'(default) or 'triangulation'
% .LevelLimits : a two-element vector defining the black and white levels
% .Precision : 'single'(default) or 'double'
%
% RectOptions : struct controlling the optional rectification process
% .CalibrationDatabaseFname : Full path to the calibration file database, as created by
% LFUtilProcessCalibrations;
%
% Example:
%
% LFUtilDecodeLytroFolder
%
% Run from the top level of the 'Samples' folder will decode all the light fields in all the
% sub-folders, with default settings as set up in the opening section of the code. The
% calibration database created by LFUtilProcessWhiteImages is expected to be in
% 'Cameras/CaliCalibrationDatabase.mat' by default.
%
% LFUtilDecodeLytroFolder('Images', [], struct('OptionalTasks', 'ColourCorrect'))
%
% Run from the top level of the 'Samples' folder will decode and colour correct all light fields in the Images
% folder and its sub-folders.
%
% DecodeOptions.OptionalTasks = {'ColourCorrect', 'Rectify'};
% LFUtilDecodeLytroFolder([], [], DecodeOptions)
%
% Will perform both colour correction and rectification in the Images folder.
%
% LFUtilDecodeLytroFolder('Images/Illum/Lorikeet.lfp')
% LFUtilDecodeLytroFolder('Lorikeet.lfp')
% LFUtilDecodeLytroFolder({'Images', '*Hiding*', 'Jacaranda*'})
% LFUtilDecodeLytroFolder('*.raw')
% LFUtilDecodeLytroFolder({'*0002*', '*0003*'})
%
% Any of these, run from the top level of the 'Samples' folder, will decode the matching files. See
% LFFindFilesRecursive.
%
% User guide: <a href="matlab:which LFToolbox.pdf; open('LFToolbox.pdf')">LFToolbox.pdf</a>
% See also: LFUtilExtractLFPThumbs, LFUtilProcessWhiteImages, LFUtilProcessCalibrations, LFUtilCalLensletCam,
% LFColourCorrect, LFHistEqualize, LFFindFilesRecursive, LFLytroDecodeImage, LFDecodeLensletImageDirect,
% LFSelectFromDatabase
% Copyright (c) 2013-2020 Donald G. Dansereau
function LFUtilDecodeLytroFolder( InputPath, FileOptions, DecodeOptions, RectOptions )
%---Defaults---
InputPath = LFDefaultVal( 'InputPath', 'Images' );
FileOptions = LFDefaultField('FileOptions', 'SaveResult', true);
FileOptions = LFDefaultField('FileOptions', 'ForceRedo', false);
FileOptions = LFDefaultField('FileOptions', 'SaveFnamePattern', '%s__Decoded.mat');
FileOptions = LFDefaultField('FileOptions', 'ThumbFnamePattern', '%s__Decoded_Thumb.png');
DecodeOptions = LFDefaultField('DecodeOptions', 'OptionalTasks', {}); % 'ColourCorrect', 'Rectify'
DecodeOptions = LFDefaultField('DecodeOptions', 'ColourHistThresh', 0.01);
DecodeOptions = LFDefaultField(...
'DecodeOptions', 'WhiteImageDatabasePath', fullfile('Cameras','WhiteImageDatabase.mat'));
RectOptions = LFDefaultField(...
'RectOptions', 'CalibrationDatabaseFname', fullfile('Cameras','CalibrationDatabase.mat'));
% Used to decide if two lenslet grid models are "close enough"... if they're not a warning is raised
RectOptions = LFDefaultField( 'RectOptions', 'MaxGridModelDiff', 1e-5 );
% Massage a single-element OptionalTasks list to behave as a cell array
while( ~iscell(DecodeOptions.OptionalTasks) )
DecodeOptions.OptionalTasks = {DecodeOptions.OptionalTasks};
end
%---Crawl folder structure locating raw lenslet images---
DefaultFileSpec = {'*.lfr', '*.lfp', '*.LFR', '*.raw'}; % gets overriden below, if a file spec is provided
DefaultPath = 'Images';
[FileList, BasePath] = LFFindFilesRecursive( InputPath, DefaultFileSpec, DefaultPath );
fprintf('Found :\n');
disp(FileList)
%---Process each raw lenslet file---
% Store options so we can reset them for each file
OrigDecodeOptions = DecodeOptions;
OrigRectOptions = RectOptions;
for( iFile = 1:length(FileList) )
SaveRequired = false;
%---Start from orig options, avoids values bleeding between iterations---
DecodeOptions = OrigDecodeOptions;
RectOptions = OrigRectOptions;
%---Find current / base filename---
CurFname = FileList{iFile};
CurFname = fullfile(BasePath, CurFname);
% Build filename base without extension, auto-remove '__frame' for legacy .raw format
LFFnameBase = CurFname;
[~,~,Extension] = fileparts(LFFnameBase);
LFFnameBase = LFFnameBase(1:end-length(Extension));
CullIdx = strfind(LFFnameBase, '__frame');
if( ~isempty(CullIdx) )
LFFnameBase = LFFnameBase(1:CullIdx-1);
end
fprintf('\n---%s [%d / %d]...\n', CurFname, iFile, length(FileList));
%---Decode---
fprintf('Decoding...\n');
% First check if a decoded file already exists
[SDecoded, FileExists, CompletedTasks, TasksRemaining, SaveFname] = CheckIfExists( ...
LFFnameBase, DecodeOptions, FileOptions.SaveFnamePattern, FileOptions.ForceRedo );
if( ~FileExists )
% No previous result, decode
[LF, LFMetadata, WhiteImageMetadata, LensletGridModel, DecodeOptions] = ...
LFLytroDecodeImage( CurFname, DecodeOptions );
if( isempty(LF) )
continue;
end
fprintf('Decode complete\n');
SaveRequired = true;
elseif( isempty(TasksRemaining) )
% File exists, and nothing more to do
continue;
else
% File exists and tasks remain: unpack previous decoding results
[LF, LFMetadata, WhiteImageMetadata, LensletGridModel, DecodeOptions] = LFStruct2Var( ...
SDecoded, 'LF', 'LFMetadata', 'WhiteImageMetadata', 'LensletGridModel', 'DecodeOptions' );
clear SDecoded
end
%---Display thumbnail---
Thumb = DispThumb(LF, CurFname, CompletedTasks);
%---Optionally colour correct---
if( ismember( 'ColourCorrect', TasksRemaining ) )
LF = ColourCorrect( LF, LFMetadata, DecodeOptions );
CompletedTasks = [CompletedTasks, 'ColourCorrect'];
SaveRequired = true;
fprintf('Done\n');
%---Display thumbnail---
Thumb = DispThumb(LF, CurFname, CompletedTasks);
end
%---Optionally rectify---
if( ismember( 'Rectify', TasksRemaining ) )
[LF, RectOptions, Success] = Rectify( LF, LFMetadata, DecodeOptions, RectOptions, LensletGridModel );
if( Success )
CompletedTasks = [CompletedTasks, 'Rectify'];
SaveRequired = true;
end
%---Display thumbnail---
Thumb = DispThumb(LF, CurFname, CompletedTasks);
end
%---Check that all tasks are completed---
UncompletedTaskIdx = find(~ismember(TasksRemaining, CompletedTasks));
if( ~isempty(UncompletedTaskIdx) )
UncompletedTasks = [];
for( i=UncompletedTaskIdx )
UncompletedTasks = [UncompletedTasks, ' ', TasksRemaining{UncompletedTaskIdx}];
end
warning(['Could not complete all tasks requested in DecodeOptions.OptionalTasks: ', UncompletedTasks]);
end
DecodeOptions.OptionalTasks = CompletedTasks;
%---Optionally save---
if( SaveRequired && FileOptions.SaveResult )
if( isfloat(LF) )
LF = uint16( LF .* double(intmax('uint16')) );
end
ThumbFname = sprintf(FileOptions.ThumbFnamePattern, LFFnameBase);
fprintf('Saving to:\n\t%s,\n\t%s...\n', SaveFname, ThumbFname);
TimeStamp = datestr(now,'ddmmmyyyy_HHMMSS');
GeneratedByInfo = struct('mfilename', mfilename, 'time', TimeStamp, 'VersionStr', LFToolboxVersion);
save('-v7.3', SaveFname, 'GeneratedByInfo', 'LF', 'LFMetadata', 'WhiteImageMetadata', 'LensletGridModel', 'DecodeOptions', 'RectOptions');
imwrite(Thumb, ThumbFname);
end
end
end
%---------------------------------------------------------------------------------------------------
function [SDecoded, FileExists, CompletedTasks, TasksRemaining, SaveFname] = ...
CheckIfExists( LFFnameBase, DecodeOptions, SaveFnamePattern, ForceRedo )
SDecoded = [];
FileExists = false;
SaveFname = sprintf(SaveFnamePattern, LFFnameBase);
if( ~ForceRedo && exist(SaveFname, 'file') )
%---Task previously completed, check if there's more to do---
FileExists = true;
fprintf( ' %s already exists\n', SaveFname );
PrevDecodeOptions = load( SaveFname, 'DecodeOptions' );
PrevOptionalTasks = PrevDecodeOptions.DecodeOptions.OptionalTasks;
CompletedTasks = PrevOptionalTasks;
TasksRemaining = find(~ismember(DecodeOptions.OptionalTasks, PrevOptionalTasks));
if( ~isempty(TasksRemaining) )
%---Additional tasks remain---
TasksRemaining = {DecodeOptions.OptionalTasks{TasksRemaining}}; % by name
fprintf(' Additional tasks remain, loading existing file...\n');
SDecoded = load( SaveFname );
AllTasks = [SDecoded.DecodeOptions.OptionalTasks, TasksRemaining];
SDecoded.DecodeOptions.OptionalTasks = AllTasks;
%---Convert to float as this is what subsequent operations require---
OrigClass = class(SDecoded.LF);
SDecoded.LF = cast( SDecoded.LF, SDecoded.DecodeOptions.Precision ) ./ ...
cast( intmax(OrigClass), SDecoded.DecodeOptions.Precision );
fprintf('Done\n');
else
%---No further tasks... move on---
fprintf( ' No further tasks requested\n');
TasksRemaining = {};
end
else
%---File doesn't exist, all tasks remain---
TasksRemaining = DecodeOptions.OptionalTasks;
CompletedTasks = {};
end
end
%---------------------------------------------------------------------------------------------------
function Thumb = DispThumb( LF, CurFname, CompletedTasks)
Thumb = squeeze(LF(round(end/2),round(end/2),:,:,:)); % including weight channel for hist equalize
Thumb = uint8(LFHistEqualize(Thumb).*double(intmax('uint8')));
Thumb = Thumb(:,:,1:3); % strip off weight channel
LFDispSetup(Thumb);
Title = CurFname;
for( i=1:length(CompletedTasks) )
Title = [Title, ', ', CompletedTasks{i}];
end
title(Title, 'Interpreter', 'none');
drawnow
end
%---------------------------------------------------------------------------------------------------
function LF = ColourCorrect( LF, LFMetadata, DecodeOptions )
fprintf('Applying colour correction... ');
%---Weight channel is not used by colour correction, so strip it out---
LFWeight = LF(:,:,:,:,4);
LF = LF(:,:,:,:,1:3);
%---Apply the color conversion and saturate---
LF = LFColourCorrect( LF, DecodeOptions.ColourMatrix, DecodeOptions.ColourBalance, DecodeOptions.Gamma );
%---Put the weight channel back---
LF(:,:,:,:,4) = LFWeight;
end
%---------------------------------------------------------------------------------------------------
function [LF, RectOptions, Success] = Rectify( LF, LFMetadata, DecodeOptions, RectOptions, LensletGridModel )
Success = false;
fprintf('Applying rectification... ');
%---Load cal info---
fprintf('Selecting calibration...\n');
[CalInfo, RectOptions] = LFFindCalInfo( LFMetadata, RectOptions );
if( isempty( CalInfo ) )
warning('No suitable calibration found, skipping');
return;
end
%---Compare structs
a = CalInfo.LensletGridModel;
b = LensletGridModel;
a.Orientation = strcmp(a.Orientation, 'horz');
b.Orientation = strcmp(b.Orientation, 'horz');
FractionalDiff = abs( (struct2array(a) - struct2array(b)) ./ struct2array(a) );
if( ~all( FractionalDiff < RectOptions.MaxGridModelDiff ) )
warning(['Lenslet grid models differ -- ideally the same grid model and white image are ' ...
' used to decode during calibration and rectification']);
end
%---Perform rectification---
[LF, RectOptions] = LFCalRectifyLF( LF, CalInfo, RectOptions );
Success = true;
end
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。