首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >频域Gabor滤波器的实现

频域Gabor滤波器的实现
EN

Stack Overflow用户
提问于 2018-08-30 06:37:12
回答 1查看 0关注 0票数 0

这里我们有Gabor过滤器的Spatial域实现。但是,出于性能原因,我需要在频域中实现Gabor滤波器

我找到了Gabor滤波器频域方程

在此处输入图像描述
在此处输入图像描述

我实际上对这个公式的正确性和/或适用性存有疑问。

源代码

所以,我已经实现了以下内容:

代码语言:javascript
复制
public partial class GaborFfftForm : Form
{
    private double Gabor(double u, double v, double f0, double theta, double a, double b)
    {
        double rad = Math.PI / 180 * theta;
        double uDash = u * Math.Cos(rad) + v * Math.Sin(rad);
        double vDash = (-1) * u * Math.Sin(rad) + v * Math.Cos(rad);

        return Math.Exp((-1) * Math.PI * Math.PI * ((uDash - f0) / (a * a)) + (vDash / (b * b)));
    }

    public Complex[,] GaborKernelFft(int sizeX, int sizeY, double f0, double theta, double a, double b)
    {
        int halfX = sizeX / 2;
        int halfY = sizeY / 2;

        Complex[,] kernel = new Complex[sizeX, sizeY];

        for (int u = -halfX; u < halfX; u++)
        {
            for (int v = -halfY; v < halfY; v++)
            {
                double g = Gabor(u, v, f0, theta, a, b);

                kernel[u + halfX, v + halfY] = new Complex(g, 0);
            }
        }

        return kernel;
    }

    public GaborFfftForm()
    {
        InitializeComponent();

        Bitmap image = DataConverter2d.ReadGray(StandardImage.LenaGray);
        Array2d<double> dImage = DataConverter2d.ToDouble(image);

        int newWidth = Tools.ToNextPowerOfTwo(dImage.Width) * 2;
        int newHeight = Tools.ToNextPowerOfTwo(dImage.Height) * 2;

        double f0 = (newWidth+newHeight)/8;
        double theta = 45;
        double alpha = 3.7;
        double beta = 1.3;

        Complex[,] kernel2d = GaborKernelFft(newWidth, newHeight, f0, theta, alpha, beta);

        dImage.PadTo(newWidth, newHeight);
        Array2d<Complex> cImage = DataConverter2d.ToComplex(dImage);
        Array2d<Complex> fImage = FourierTransform.ForwardFft(cImage);

        // FFT convolution .................................................
        Array2d<Complex> fOutput = new Array2d<Complex>(newWidth, newHeight);
        for (int x = 0; x < newWidth; x++)
        {
            for (int y = 0; y < newHeight; y++)
            {
                fOutput[x, y] = fImage[x, y] * kernel2d[x, y];
            }
        }

        Array2d<Complex> cOutput = FourierTransform.InverseFft(fOutput);
        Array2d<double> dOutput = ImageRescaler.Rescale(DataConverter2d.ToDouble(cOutput));

        dOutput.CropBy((newWidth-image.Width)/2, (newHeight - image.Height)/2);

        Bitmap output = DataConverter2d.ToBitmap(dOutput, image.PixelFormat);

        Array2d<Complex> cKernel = FourierTransform.InverseFft(new Array2d<Complex>(kernel2d));
        cKernel = FourierTransform.RemoveFFTShift(cKernel);
        Array2d<double> dKernel = ImageRescaler.Rescale(DataConverter2d.ToDouble(cKernel));
        Bitmap kernel = DataConverter2d.ToBitmap(dKernel, image.PixelFormat);

        pictureBox1.Image = image;
        pictureBox2.Image = kernel;
        pictureBox3.Image = output;
    }
}

现在只关注算法步骤。

我在频域中生成了一个Gabor内核。因为内核已经在频域中,所以我没有对它应用FFT,而图像是FFT编辑的。然后,我将内核与图像相乘以实现FFT-Convolution。然后它们被反FFT并像往常一样转换回位图。

产量

在此处输入图像描述
在此处输入图像描述
  1. 内核看起来没问题。但是,过滤器输出看起来不是很有希望(或者,它呢?)。
  2. 方向(theta)对内核没有任何影响。
  3. 计算/公式经常在变化值的情况下遭受除零异常。

我该如何解决这些问题?

哦,而且,

  • 参数αβ代表什么?
  • 什么应该是f 0的适当值?
EN

回答 1

Stack Overflow用户

发布于 2018-08-30 16:07:04

您找到的Gabor滤波器的等式中似乎存在拼写错误。Gabor滤波器是频域中的平移高斯滤波器。因此,它需要具有在指数中。

链接中的等式(2)似乎更明智,但仍然错过了2

代码语言:javascript
复制
exp( -2(πσ)² (u-f₀)² )

这是1D情况,这是我们想要在θ方向使用的滤波器。我们现在在垂直方向上乘以v非移位高斯。我设置αβ成为两个sigmas的反转:

代码语言:javascript
复制
exp( -2(π/α)² (u-f₀)² ) exp( -2(π/β)² v² ) = exp( -2π²((u-f₀)/α)² + -2π²(v/β)² )

您应该使用上面的公式uv在θ上旋转,就像您已经做的那样。

此外,uv应运行从-0.5到0.5之间,而不是-sizeX/2sizeX/2。这就是假设您的FFT在图像中间设置原点,这并不常见。通常,FFT算法将原点设置在图像的一角。所以你应该拥有你的uv从0开始运行(sizeX-1)/sizeX

使用上面的校正实现,你应该设置f₀在0和0.5之间(尝试0.2开始),α并且β应该足够小,使得高斯不会达到0频率(你希望滤波器在那里为0) )

在频域中,您的滤镜看起来像是远离原点的旋转高斯。

在空间域中,滤镜的幅度应该再次像高斯一样。虚构组件应如下所示(图片链接到我发现的维基百科页面):

Gabor,真正的一部分
Gabor,真正的一部分

(即,它在θ方向上是反对称的(奇数)),可能有更多的波瓣取决于αβf₀。真实组件应该相似但对称(偶数),中间最大。请注意,在IFFT之后,您可能需要将原点从左上角移动到图像的中间(Google“fftshift”)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100008834

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档