-
Notifications
You must be signed in to change notification settings - Fork 2
/
LFFilt2DFFT.m
124 lines (107 loc) · 4.36 KB
/
LFFilt2DFFT.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
% LFFilt2DFFT - Apply a 2D frequency-domain filter to a 4D light field using the FFT
%
% Usage:
%
% [LF, FiltOptions] = LFFilt2DFFT( LF, H, FiltDims, FiltOptions )
% LF = LFFilt2DFFT( LF, H, FiltDims )
%
%
% This filter works on 2D slices of the input light field, applying the 2D filter H to each in turn. It takes the FFT
% of each slice of the input light field, multiplies by the provided magnitude response H, then calls the inverse FFT.
%
% The FiltDims input specifies the two dimensions along which H should be applied. The frequency-domain filter H should
% match or exceed the size of the light field LF in these dimensions. If H is larger than the input light field, LF is
% zero-padded to match the filter's size. If a weight channel is present in the light field it gets used during
% normalization.
%
% See LFDemoBasicFiltLytro for example usage.
%
%
% Inputs
%
% LF : The light field to be filtered
%
% H : The frequency-domain filter to apply, as constructed by one of the LFBuild4DFreq* functions
%
% FiltDims : The dimensions along which H should be applied
%
% [optional] FiltOptions : struct controlling filter operation
% Precision : 'single' or 'double', default 'single'
% Normalize : default true; when enabled the output is normalized so that darkening near image edges is
% removed
% MinWeight : during normalization, pixels for which the output value is not well defined (i.e. for
% which the filtered weight is very low) get set to 0. MinWeight sets the threshold at which
% this occurs, default is 10 * the numerical precision of the output, as returned by eps
%
% Outputs:
%
% LF : The filtered 4D light field
% FiltOptions : The filter options including defaults, with an added FilterInfo field detailing the function and
% time of filtering.
%
% See also: LFDemoBasicFiltGantry, LFDemoBasicFiltIllum, LFDemoBasicFiltLytroF01, LFBuild2DFreqFan, LFBuild2DFreqLine,
% LFBuild4DFreqDualFan, LFBuild4DFreqHypercone, LFBuild4DFreqHyperfan, LFBuild4DFreqPlane, LFFilt2DFFT, LFFilt4DFFT,
% LFFiltShiftSum
% Part of LF Toolbox v0.4 released 12-Feb-2015
% Copyright (c) 2013-2015 Donald G. Dansereau
function [LF, FiltOptions] = LFFilt2DFFT( LF, H, FiltDims, FiltOptions )
FiltOptions = LFDefaultField('FiltOptions', 'Precision', 'single');
FiltOptions = LFDefaultField('FiltOptions', 'Normalize', true);
FiltOptions = LFDefaultField('FiltOptions', 'MinWeight', 10*eps(FiltOptions.Precision));
%---
NColChans = size(LF,5);
HasWeight = ( NColChans == 4 || NColChans == 2 );
if( HasWeight )
NColChans = NColChans-1;
end
%---
IterDims = 1:4;
IterDims(FiltDims) = 0;
IterDims = find(IterDims~=0);
PermuteOrder = [IterDims, FiltDims, 5];
LF = permute(LF, PermuteOrder);
LF = LFConvertToFloat(LF, FiltOptions.Precision);
%---
LFSize = size(LF);
SlicePaddedSize = size(H);
for( IterDim1 = 1:LFSize(1) )
fprintf('.');
for( IterDim2 = 1:LFSize(2) )
CurSlice = squeeze(LF(IterDim1,IterDim2,:,:,:));
if( FiltOptions.Normalize )
if( HasWeight )
for( iColChan = 1:NColChans )
CurSlice(:,:,iColChan) = CurSlice(:,:,iColChan) .* CurSlice(:,:,end);
end
else % add a weight channel
CurSlice(:,:,end+1) = ones(size(CurSlice(:,:,1)), FiltOptions.Precision);
end
end
SliceSize = size(CurSlice);
for( iColChan = 1:SliceSize(end) )
X = fftn(CurSlice(:,:,iColChan), SlicePaddedSize);
X = X .* H;
x = ifftn(X,'symmetric');
x = x(1:LFSize(3), 1:LFSize(4));
CurSlice(:,:,iColChan) = x;
end
if( FiltOptions.Normalize )
WeightChan = CurSlice(:,:,end);
InvalidIdx = find(WeightChan < FiltOptions.MinWeight);
ChanSize = numel(CurSlice(:,:,1));
for( iColChan = 1:NColChans )
CurSlice(:,:,iColChan) = CurSlice(:,:,iColChan) ./ WeightChan;
CurSlice( InvalidIdx + ChanSize.*(iColChan-1) ) = 0;
end
end
% record channel
LF(IterDim1,IterDim2,:,:,:) = CurSlice(:,:,1:LFSize(5));
end
end
LF = max(0,LF);
LF = min(1,LF);
LF = ipermute(LF, PermuteOrder);
%---
TimeStamp = datestr(now,'ddmmmyyyy_HHMMSS');
FiltOptions.FilterInfo = struct('mfilename', mfilename, 'time', TimeStamp, 'VersionStr', LFToolboxVersion);
fprintf(' Done\n');