Code covered by the BSD License  

Highlights from
Light Field Toolbox v0.2

image thumbnail

Light Field Toolbox v0.2

by

 

26 Apr 2013 (Updated )

A set of tools for working with light field (aka plenoptic) imagery in Matlab

...
% LFDecodeLytroImage - decode a Lytro light field from a raw lenselet image on disk
%
% Usage:
%
%     [LF, LFMetadata, WhiteImageMetadata, LenseletGridModel, DecodeOptions] = ...
%         LFDecodeLytroImage( LFFnameBase, DecodeOptions )
%     [LF, LFMetadata, WhiteImageMetadata, LenseletGridModel, DecodeOptions] = ...
%         LFDecodeLytroImage( LFFnameBase )
%
% This function decodes a raw lenselet image into a 4D light field. Its purpose is to tailor the
% core lenselet decoding function, LFDecodeLenseletImageSimple, for use with Lytro data. It is
% envisioned that other camera formats will be supported by similar functions in future. The
% defaults are set up to work with Lytro data extracted using LFP Reader v2.0.0. See LFToolbox.pdf
% for more information on the expected data organization.
%
% The white image appropriate to a light field is selected based on a white image database, and so
% LFUtilProcessWhiteImages must be run before this function.
% 
% LFUtilDecodeLytroFolder is useful for decoding multiple images.
%
% The optional DecodeOptions argument includes several fields defining filename patterns. These are
% combined with the input LFFnameBase to build complete filenames. Filename patterns include the
% placeholder '%s' to signify the position of the base filename. For example, the defualt filename
% pattern for a raw input file, LenseletImageFnamePattern, is '%s__frame.raw'. So a call of the
% form LFDecodeLytroImage('IMG_0001') will look for the raw input file 'IMG_0001__frame.raw'.
% 
% Inputs:
% 
%     LFFnameBase : 'base' filename of the light field, excluding the raw lenselet image
%                   termination. In the default configuration, 'IMG_0001' is a typical filename
%                   base.
% 
%     [optinal] DecodeOptions : all fields are optional, defaults are for LFP Reader v2.0.0 naming
% 
%                .MetadataFnamePattern : JSON file containing light field metadata
%              .SerialdataFnamePattern : JSON file containing serial numbers
%           .LenseletImageFnamePattern : The raw input lenselet image
%         .WhiteProcDataFnameExtension : Grid model From LFUtilProcessWhiteImages /
%                                        LFBuildLenseletGridModel
%          .WhiteRawDataFnameExtension : White image file extension
%              .WhiteImageDatabasePath : White image database
%
%
% Outputs:
% 
%                     LF : 5D array containing a 4-channel (RGB + Weight) light field, indexed in
%                          the order [j,i,l,k, channel]
%             LFMetadata : Contents of the metadata and serial metadata files
%     WhiteImageMetadata : Conents of the white image metadata file
%      LenseletGridModel : Lenselet grid model used to decode the light field, as constructed from
%                          the white image by LFUtilProcessWhiteImages / LFBuildLenseletGridModel
%          DecodeOptions : The options as applied, including any default values omitted in the input
% 
% 
% Example:
%     
%     LF = LFDecodeLytroImage('Images/IMG_0002');
%     LF = LFHistEqualize(LF);
%     LFDispMousePan(LF, 2)
%     
%     Run from the top level of the light field samples will decode IMG_0002, apply histogram
%     equalization, then display the result in a shifting-perspective display with x2 magnification.
%     LFUtilProcessWhiteImages must be run before decoding will work.
% 
% 
% See also: LFUtilDecodeLytroFolder, LFDecodeLenseletImageSimple, LFSelectFromDatabase,
% LFUtilProcessWhiteImages

% Part of LF Toolbox v0.2 released 27-May-2013
% Copyright (c) 2013, Donald G. Dansereau

function [LF, LFMetadata, WhiteImageMetadata, LenseletGridModel, DecodeOptions] = ...
    LFDecodeLytroImage( LFFnameBase, DecodeOptions )

%---Defaults---
DecodeOptions = LFDefaultField( 'DecodeOptions', 'MetadataFnamePattern', '%s__frame_metadata.json' );
DecodeOptions = LFDefaultField( 'DecodeOptions', 'SerialdataFnamePattern', '%s__frame_private_metadata.json' );
DecodeOptions = LFDefaultField( 'DecodeOptions', 'LenseletImageFnamePattern', '%s__frame.raw' );
DecodeOptions = LFDefaultField( 'DecodeOptions', 'WhiteProcDataFnameExtension', '.grid.mat' );
DecodeOptions = LFDefaultField( 'DecodeOptions', 'WhiteRawDataFnameExtension', '.RAW' );
DecodeOptions = LFDefaultField(...
    'DecodeOptions', 'WhiteImageDatabasePath', fullfile('Cameras','WhiteImageDatabase.mat'));

%---Load raw light field and metadata---
MetadataFname = sprintf(DecodeOptions.MetadataFnamePattern, LFFnameBase);
SerialdataFname = sprintf(DecodeOptions.SerialdataFnamePattern, LFFnameBase);
LenseletImageFname = sprintf(DecodeOptions.LenseletImageFnamePattern, LFFnameBase);
fprintf('Loading lenselet image and metadata:\n\t%s\n', LenseletImageFname);
LFMetadata = LFReadMetadata(MetadataFname);
LFMetadata.SerialData = LFReadMetadata(SerialdataFname);
LenseletImage = LFReadRaw(LenseletImageFname);

%---Select appropriate white image---
DesiredCam = struct('CamSerial', LFMetadata.SerialData.camera.serialNumber, ...
    'ZoomStep', LFMetadata.devices.lens.zoomStep, ...
    'FocusStep', LFMetadata.devices.lens.focusStep );
DecodeOptions.WhiteImageInfo = LFSelectFromDatabase( DesiredCam, DecodeOptions.WhiteImageDatabasePath );
PathToDatabase = fileparts( DecodeOptions.WhiteImageDatabasePath );

%---Load white image, white image metadata, and lenselet grid parameters---
fprintf('Loading white image and metadata:\n\t%s\n', DecodeOptions.WhiteImageInfo.Fname);
WhiteMetadataFname = fullfile(PathToDatabase, DecodeOptions.WhiteImageInfo.Fname);
WhiteProcFname = LFFindLytroPartnerFile(WhiteMetadataFname, DecodeOptions.WhiteProcDataFnameExtension);
WhiteRawFname = LFFindLytroPartnerFile(WhiteMetadataFname, DecodeOptions.WhiteRawDataFnameExtension);

load( WhiteProcFname, 'LenseletGridModel' );
WhiteImageMetadataWhole = LFReadMetadata( WhiteMetadataFname );
WhiteImageMetadata = WhiteImageMetadataWhole.master.picture.frameArray.frame.metadata;
WhiteImageMetadata.SerialData = WhiteImageMetadataWhole.master.picture.frameArray.frame.privateMetadata;
WhiteImage = LFReadRaw( WhiteRawFname );

%---Check serial number---
if( ~strcmp(WhiteImageMetadata.SerialData.camera.serialNumber, LFMetadata.SerialData.camera.serialNumber) )
    warning('White image is for a different camera, decoding is unlikely to work properly\n');
end

%---Decode---
fprintf('Decoding lenselet image :');
LevelLimits = [LFMetadata.image.rawDetails.pixelFormat.black.gr, LFMetadata.image.rawDetails.pixelFormat.white.gr];
[LF, LFWeight, DecodeOptions] = LFDecodeLenseletImageSimple( LenseletImage, WhiteImage, LenseletGridModel, DecodeOptions, LevelLimits );
LF(:,:,:,:,4) = LFWeight;

Contact us