【问题标题】:Low pass filter with unit integral单位积分低通滤波器
【发布时间】:2014-05-18 02:32:15
【问题描述】:

在图像处理中,特别是在指纹识别中,我必须应用具有单位积分的二维低通滤波器。

这个单位积分是什么意思?另外,如果我选择高斯滤波器,使用什么 sigma?

【问题讨论】:

    标签: image image-processing filter gaussian


    【解决方案1】:

    单位积分意味着掩码或内核的总面积应为 1。例如,3 x 3 平均滤波器意味着掩码中的每个系数都应为 1/9。当您将掩码中的所有元素相加时,它会加到 1。

    高斯滤波器固有的单位积分/单位面积为 1。如果您使用 MATLAB,带有gaussian 标志的fspecial 命令将对其掩码进行归一化处理。

    但是,如果您想自己创建高斯蒙版,可以使用以下公式:

    请记住,(x,y) 是蒙版内相对于中心的位置。因此,如果您有一个 5 x 5 的面具,那么在 row = 2, col = 2x = 0y = 0。但是,上述等式不会生成单位面积 1。如果在整个 2D 平面上积分,理论上它等于 1。因为我们截断了高斯函数,所以面积不是 1。因此,一旦生成了所有系数,就需要通过对掩码中的每个元素求和来确保总面积为 1。然后,您将这个数字除以掩码中的每个元素。事实上,当您生成高斯掩码时,将指数项乘以等式中的比例因子并不重要。通过确保掩码之和等于1,可以有效去除刻度。您可以只使用指数项来减少一些计算。

    sigma 而言,这完全取决于您。通常人们使用3*sigma 规则的半宽度,因此一维中从左到右的总宽度为6*sigma + 1(包括中心)。为了弄清楚你具体想要什么 sigma,人们会找出图像中 最小特征 的宽度,将其设置为宽度,然后从那里找出 sigma。例如,如果最大宽度为 13,则在等式中重新排列 sigma 会得到 2。换句话说:

    13 = 6*sigma + 1
    12 = 6*sigma
    sigma = 2
    

    因此,您需要将 sigma 设置为 2 并将掩码设置为 13 x 13。有关 3*sigma 规则的更多信息,请查看我在此处的主题帖子:By which measures should I set the size of my Gaussian filter in MATLAB?

    创建该蒙版后,使用您希望对图像进行高斯过滤的任何卷积方法。

    如果您可以使用 MATLAB,这里还有一篇文章可能会对您有所帮助。

    How to make a Gaussian filter in Matlab


    如果您需要使用其他语言,如 C 或 Java,则可以通过以下方式创建高斯掩码:

    C/C++

    #define WIDTH 13
    
    float sigma = ((float)WIDTH - 1.0f) / 6.0f;
    int half_width = (int)(WIDTH / 2.0);
    float mask[WIDTH][WIDTH];
    float scale = 0.0f;
    for (int i = -half_width; i <= half_width; i++) {
        for(int j = -half_width; j <= half_width; j++) {
             mask[i+half_width][j+half_width] = expf( -((float)(i*i + j*j) / (2.0*sigma*sigma)) );
             scale += mask[i+half_width][j+half_width];
        }
    }
    
     for (int i = 0; i < WIDTH; i++)
          for (int j = 0; j < WIDTH; j++)
                mask[i][j] /= scale;
    

    Java

     int WIDTH = 13;     
     float sigma = ((float)WIDTH - 1.0f) / 6.0f);
     int half_width = Math.floor((float)WIDTH / 2.0f);
     float[][] mask = new float[WIDTH][WIDTH];
     float scale = 0.0f;
    
     for (int i = -half_width; i <= half_width; i++) {
         for (int j = -half_width; j <= half_width; j++) {
              mask[i+half_width][j+half_width] = (float) Math.exp( -((double)(i*i + j*j) /  (2.0*sigma*sigma)) );
              scale += mask[i+half_width][j+half_width];
         }
     }
    
     for (int i = 0; i < WIDTH; i++)
          for (int j = 0; j < WIDTH; j++)
                mask[i][j] /= scale;
    

    正如我之前提到的,请注意在代码中我不必除以2*pi*sigma^2。同样,原因是当你对内核进行归一化时,这个常数因子无论如何都会被抵消,所以在计算掩码系数时不需要增加任何额外的开销。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-30
      • 1970-01-01
      • 1970-01-01
      • 2014-07-29
      • 2011-05-29
      • 2019-04-29
      • 2015-05-09
      • 1970-01-01
      相关资源
      最近更新 更多