【发布时间】:2014-05-18 02:32:15
【问题描述】:
在图像处理中,特别是在指纹识别中,我必须应用具有单位积分的二维低通滤波器。
这个单位积分是什么意思?另外,如果我选择高斯滤波器,使用什么 sigma?
【问题讨论】:
标签: image image-processing filter gaussian
在图像处理中,特别是在指纹识别中,我必须应用具有单位积分的二维低通滤波器。
这个单位积分是什么意思?另外,如果我选择高斯滤波器,使用什么 sigma?
【问题讨论】:
标签: image image-processing filter gaussian
单位积分意味着掩码或内核的总面积应为 1。例如,3 x 3 平均滤波器意味着掩码中的每个系数都应为 1/9。当您将掩码中的所有元素相加时,它会加到 1。
高斯滤波器固有的单位积分/单位面积为 1。如果您使用 MATLAB,带有gaussian 标志的fspecial 命令将对其掩码进行归一化处理。
但是,如果您想自己创建高斯蒙版,可以使用以下公式:
请记住,(x,y) 是蒙版内相对于中心的位置。因此,如果您有一个 5 x 5 的面具,那么在 row = 2, col = 2、x = 0 和 y = 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,则可以通过以下方式创建高斯掩码:
#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;
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。同样,原因是当你对内核进行归一化时,这个常数因子无论如何都会被抵消,所以在计算掩码系数时不需要增加任何额外的开销。
【讨论】: