I have found a good Gabor Filter source code from this link. The code is very clean and well-documented.
My question is here,
for i = 1:u
...............
...............
...............
for j = 1:v
tetav = ((j-1)/v)*pi;
.....................
for x = 1:m
for y = 1:n
xprime = ........
yprime = ........
gFilter(x,y) = ........
end
end
gaborArray{i,j} = gFilter;
end
end
What does it mean by tetav = ((j-1)/v)*pi;
? Is it radian or degree? If it is radian, why wasn't it divided by 180?
Why does the kernel computation go from 1
to m
or n
? Why not from -(m/2)
to (m+1)/2
?
Source Code
gaborFeatures.m
function gaborResult = gaborFeatures(img,gaborArray,d1,d2)
if (nargin ~= 4) % Check correct number of arguments
error('Please use the correct number of input arguments!')
end
if size(img,3) == 3 % Check if the input image is grayscale
warning('The input RGB image is converted to grayscale!')
img = rgb2gray(img);
end
img = double(img);
% Filter input image by each Gabor filter
[u,v] = size(gaborArray);
gaborResult = cell(u,v);
for i = 1:u
for j = 1:v
gaborResult{i,j} = imfilter(img, gaborArray{i,j});
end
end
gaborFilterBank.m
function gaborArray = gaborFilterBank(u,v,m,n)
if (nargin ~= 4) % Check correct number of arguments
error('There must be four input arguments (Number of scales and orientations and the 2-D size of the filter)!')
end
% Create u*v gabor filters each being an m by n matrix
gaborArray = cell(u,v);
fmax = 0.25;
gama = sqrt(2);
eta = sqrt(2);
for i = 1:u
fu = fmax/((sqrt(2))^(i-1));
alpha = fu/gama;
beta = fu/eta;
for j = 1:v
tetav = ((j-1)/v)*pi;
gFilter = zeros(m,n);
for x = 1:m
for y = 1:n
xprime = (x-((m+1)/2))*cos(tetav)+(y-((n+1)/2))*sin(tetav);
yprime = -(x-((m+1)/2))*sin(tetav)+(y-((n+1)/2))*cos(tetav);
gFilter(x,y) = (fu^2/(pi*gama*eta))*exp(-((alpha^2)*(xprime^2)+(beta^2)*(yprime^2)))*exp(1i*2*pi*fu*xprime);
end
end
gaborArray{i,j} = gFilter;
end
end
What does it mean by tetav = ((j-1)/v)*pi;?
This means that tetav
will take on increasingly larger pieces of pi; starting with 0 and increasing to the whole thing (i.e. 3.14159...). There are 180 degrees or pi radians in half a circle. So tetav will be taking on increasingly portions of half a circle.
Is it radian or degree?
It is radians.
If it is radian, why wasn't it divided by 180?
Radians are the desired unit here (for whoever programmed this). They could have instead multiplied by pi if they wanted everything in degrees. If, hypothetically, you were thinking that the expression ((j-1)/v)
was in degrees and needed to be converted to radians by a multiplication of pi/180, well that would mean the function would cover, at most, 1 degree of your circle.
Why does the kernel computation go from 1 to m or n? Why not from -(m/2) to (m+1)/2?
It is because they chose to instead handle the -(m/2) to (m+1)/2 inside the loop. It is in the code you posted for the gaborFilterBank.m file:
xprime = (x-((m+1)/2))*cos(tetav)+(y-((n+1)/2))*sin(tetav);
yprime = -(x-((m+1)/2))*sin(tetav)+(y-((n+1)/2))*cos(tetav);
Since they sin and cosine are being combined, you'll be getting the full circle covered by this Gabor filter. And the offset is adjusted for the x and y center points by the -((m+1)/2) calls. For example, when x = 1 the expression (x-((m+1)/2)) becomes -(m+1)/2+1 or -m/2+0.5 and when x = m, the same expression becomes m/2+0.5, so it is still covering the range you are wondering about.