Кажется, что в уравнении для фильтра Габора найдена опечатка. Фильтр Габора является преобразованным гауссовым в частотной области. Следовательно, оно должно иметь u²
и v²
в показателе степени.
Уравнение (2) в вашей ссылке кажется более разумным, , но все еще пропускает 2 :
exp( -2(πσ)² (u-f₀)² )
Это 1D случай, это фильтр, который мы хотим использовать в направлении & theta ;. Теперь умножим в перпендикулярном направлении, v
, на несмещенный гауссов. Я устанавливаю α
и β
как инверсию двух сигм:
exp( -2(π/α)² (u-f₀)² ) exp( -2(π/β)² v² ) = exp( -2π²((u-f₀)/α)² + -2π²(v/β)² )
Вы должны реализовать вышеприведенное уравнение с поворотом u
и v
на & theta;, как вы уже сделали.
Кроме того, u
и v
должны работать от -0,5 до 0,5, а не от -sizeX/2
до sizeX/2
. И это при условии, что ваше БПФ устанавливает источник в середине изображения, что не является распространенным явлением. Обычно алгоритмы БПФ устанавливают начало координат в углу изображения. Таким образом, вы, вероятно, должны вместо этого использовать u
и v
от 0 до (sizeX-1)/sizeX
.
При исправленной реализации, как указано выше, вы должны установить f₀
в диапазоне от 0 до 0,5 (попробуйте 0,2 для начала), а α
и β
должны быть достаточно малы, чтобы гауссиан не достиг частота 0 (вы хотите, чтобы фильтр там был 0)
В частотной области ваш фильтр будет выглядеть как повернутый гауссиан от начала координат.
В пространственной области величина вашего фильтра снова должна выглядеть как гауссовская. Мнимый компонент должен выглядеть следующим образом (изображение ссылки на страницу Википедии, на которой я его нашел):
![Gabor, real part](https://i.stack.imgur.com/ng8OW.png)
(т.е. это антисимметрично (нечетно) в направлении & theta;), возможно, с большим количеством лепестков в зависимости от α
, β
и f₀
. Реальный компонент должен быть похожим, но симметричным (четным) с максимумом посередине. Обратите внимание, что после IFFT вам может понадобиться сместить начало координат из верхнего левого угла в середину изображения (Google "fftshift").
Обратите внимание, что если вы установите α
и β
равными, вращение плоскости u
- v
не имеет значения. В этом случае вы можете использовать декартовы координаты вместо полярных координат для определения частоты. То есть вместо определения f₀ и θ в качестве параметров вы определяете u₀ и v₀. В показателе степени вы затем заменяете u-f₀ на u-u₀, а v на v-v₀.
Код после редактирования вопроса снова пропускает квадрат. Я бы написал код следующим образом:
private double Gabor(double u, double v, double u0, double v0, double a, double b)
{
double p = (-2) * Math.PI * Math.PI;
double q = (u-u0)/a;
double r = (v - v0)/b;
return Math.Exp(p * (q*q + r*r));
}
public Array2d<Complex> GaborKernelFft(int sizeX, int sizeY, double u0, double v0, double a, double b)
{
double halfX = sizeX / 2;
double halfY = sizeY / 2;
Array2d<Complex> kernel = new Array2d<Complex>(sizeX, sizeY);
for (double y = 0; y < sizeY; y++)
{
double v = y / sizeY;
// v -= HalfY; // whether this is necessary or not depends on your FFT
for (double x = 0; x < sizeX; x++)
{
double u = x / sizeX;
// u -= HalfX; // whether this is necessary or not depends on your FFT
double g = Gabor(u, v, u0, v0, a, b);
kernel[(int)x, (int)y] = new Complex(g, 0);
}
}
return kernel;
}