I have implemented in Matlab a bandpass filter for a 4D image (4D matrix). The first three dimensions are spatial dimensions, the last dimension is a temporal one. Here is the code:
function bandpass_img = bandpass_filter(img)
% Does bandpass filtering on input image
%
% Input:
% img: 4D image
%
% Output:
% bandpass_img: Bandpass filtered image
TR = 1; % Repetition time
n_vols = size(img,3);
X = [];
% Create matrix (voxels x time points)
for z = 1:size(img,3)
for y = 1:size(img,2)
for x = 1:size(img,1)
X = [X; squeeze(img(x,y,z,:))']; %#ok<AGROW>
end
end
end
Fs = 1/TR;
nyquist = 0.5*Fs;
% Pass bands
F = [0.01/nyquist, 0.1/nyquist];
type = 'bandpass';
% Filter order
n = floor(n_vols/3.5);
% Ensure filter order is odd for bandpass
if (mod(n,2) ~= 0), n=n+1; end
fltr = fir1(n, F, type);
% Looking at frequency response
% freqz(fltr)
% Store plot to file
% set(gcf, 'Color', 'w');
% export_fig('freq_response', '-png', '-r100');
% Apply to image
X = filter(fltr, 1, X);
% Reconstructing image
i = 1;
bandpass_img = zeros(size(img));
for z = 1:size(img,3)
for y = 1:size(img,2)
for x = 1:size(img,1)
bandpass_img(x,y,z,:) = X(i,:)';
i = i + 1;
end
end
end
end
I'm not sure if the implementation is correct. Could somebody verify it or does somebody find a failure?
Edit: Thanks to SleuthEye it now kind of works when I'm using bandpass_img = filter(fltr, 1, img, [], 4);
. But there is still a minor problem. My images are of size 80x35x12x350, i.e. there are 350 time points. I have plotted the average time series before and after applying the bandpass filter.
Before bandpass filtering:
After bandpass filtering:
Why is this peak at the very beginning of the filtered image?
Edit 2: There is now a peak at the beginning and at the end. See:
I have made a second plot where I marked each point with a *. See:
So the first and last two time points seem to be lower.
It seems that I have to remove 2 time points at the beginning and also 2 time points at the end, so in total I will loose 4 time points.
What do you think?
Filtering a concatenation of all the elements using the 1-D
filter
function as you are doing is likely going to result in a distorted image as the smoothing makes the end of each row blend into the beginning of the next one. Unless you are trying to obtain a psychedelic rendition of your 4D data, this is unlikely to do what you are expecting it to.Now, according to Matlab's filter documentation:
So, to smooth out the 3D images over time (which you indicated is the fourth dimension of you matrix
img
), you should useUsed as such, the signal would starts a 0 because that's the default initial state of the filter and the filter takes a few samples to ramp up. If you know the value of the initial state you can specify that with the
zi
argument (the 4th argument):Otherwise, a typical order
N
linear FIR filter has a delay ofN/2
samples. To get rid of the initial ramp up you can thus just discard thoseN/2
initial samples:Similarly, if you want to see the output corresponding to the last
N/2
input values, you'd have to pad your input withN/2
extra samples (zeros will do):