如何理解频率图像中描述的平均像素数?

How to understand the average pixel number described in the frequency image?

我正在尝试实现 Anil Jain et al 提出的广泛使用的指纹图像增强算法。在执行第 2.5 节中脊频率图像计算的步骤时,我在理解某些描述时遇到了困难。步骤说明如下:

  1. 获取归一化图像G.
  2. 将 G 分成大小为 w x w (16 x 16) 的块。
  3. 对于以像素 (i, j) 为中心的每个块,计算在脊坐标系中定义的大小为 l x w (32x16) 的定向 window。
  4. 对于以像素 (i,j) 为中心的每个块,计算脊的 x 签名 X[0]、X1、...、X[l-1] 和定向 window 内的山谷,其中

如果方向window中没有出现细节和奇异点,则x特征形成离散的正弦波,其频率与方向[=中的脊和谷的频率相同58=]。因此,可以从 x 特征估计脊和谷的频率。令 T(i,j) 为 x 特征中两个连续峰值之间的平均像素数,则频率计算为:

我的问题是: 我不明白如何获得两个连续峰之间的平均像素数,因为论文没有提到如何在算法中区分峰。那么,如何确定那些峰值像素来计算它们呢?有人能解释一下我在这里错过了什么吗?

此外,我像这样使用 OpenCV 实现了到这里为止的步骤,如果有人可以完成我的步骤来帮助我仔细检查我是否正确实现,我将不胜感激:

void Enhancement::frequency(cv::Mat inputImage, cv::Mat orientationMat)
{
    int blockSize = 16;
    int windowSize = 32;

    //compute x-signature
    for (int i = blockSize / 2; i < inputImage.rows - blockSize / 2; i += blockSize)
    {
        for (int j = blockSize / 2; j < inputImage.cols - blockSize / 2; j += blockSize)
        {
            int u = 0; 
            int v = 0;
            std::vector<float> xSignature;

            for (int k = 0; k < windowSize; k++)            
            {
                float sum = 0.0;

                for (int d = 0; d < blockSize; d++)
                {
                    float pixel = orientationMat.at<float>(i, j);

                    u = i + (d - 0.5 * blockSize) * cos(pixel) + (k - 0.5 * windowSize) * sin(pixel);
                    v = j + (d - 0.5 * blockSize) * sin(pixel) + (0.5 - windowSize) * cos(pixel);
                    sum += static_cast<float>(inputImage.at<uchar>(u, v));
                }

                xSignature.push_back(sum);
            }
        } // end of j-loop
    } // end of i-loop

}

更新

搜索了一些文章,发现有人提到如何判断一个peak pixel是否像这样:

  1. 对每个块进行灰度膨胀
  2. 找到膨胀等于原始值的地方

但是,我还是没看清楚。这是否意味着我可以对我的灰度图像采用逐块形态膨胀操作(在进一步处理之前,我已经在 OpenCV 中将我的图像从 RGB 转换为灰度)? dilation equals original values 这个词的意思是 the pixel intensity after morphological dilation equals its original value 吗?我在这里迷路了。

我不知道你说的具体算法,但也许我可以提供一些一般性的建议。

我想问题的核心是噪声信号中的区别 "what is a peak, what is just noise"(因为 RL 输入图像在某种意义上总是噪声;我认为代码中峰值检测的相关输入向量是 xSignature ).确定峰值后,计算平均峰值距离应该相当简单。

至于峰值检测,有大量论文描述了相当复杂的算法,但我将概述我在图像处理工作中使用的一些经过验证的真实方法。

平滑

如果您知道预期的峰宽 w,您可以首先应用一些平滑,通过对 window 的预期峰宽(从 x-w/2 到 x+w/2)。您实际上不需要计算滑动的平均值 window(除以 w),因为对于峰值检测,绝对比例无关紧要,总和与平均值。

最小-最大-识别

您可以 运行 在您的(可能平滑的)轮廓矢量上并确定最小和最大索引(例如通过简单的斜率符号更改)。将这些位置存储在 map<int (coordinate), bool (isMax)>map<int (coordinate), double (value at coordinate)> 中。或者使用一个结构作为保存所有相关信息的值(bool isMax,double value,bool isAtBoundary,...)

评估检测到的峰的质量

对于您在上一步中找到的每个最大值,确定高度差以及可能与之前和之后的最小值的斜率,从而产生质量。此步骤取决于您的问题域。也许 "peaks" 不需要在两侧都用最小值框起来(在这种情况下,上面的最小检测必须比斜率变化更复杂)。也许对峰有最小或最大宽度限制。等等。

根据上述问题为每个最高排名计算一个质量值。我经常使用类似 Q_max =(从最大值到相邻最小值的平均高度差)/(配置文件的最大最小值)之类的东西。候选峰的 "quality" 最多为 1,至少为 0.

迭代所有最大值,计算它们的质量并将它们放入多图或其他容器中,可以对其进行排序,以便以后可以按降序迭代峰值。

区分峰值和非峰值

以递减的质量迭代你的峰值。可能将所有不满足最小值或最大值 width/height/quality/distance 的内容分类到具有更高质量/... 要求的最近峰值,以使它们成为您的问题域中的峰值。保留其余部分。完成。

在您的情况下,您将按坐标对峰重新排序并计算它们之间的平均距离。

我知道这很模糊,但峰检测没有普遍正确的答案。也许在你正在使用的论文中某处隐藏了一个特定的处方,但大多数作者都忽略了这样的 "mere technicalities"(通常,如果你通过电子邮件联系他们,他们不记得或以其他方式重现他们是如何做到的,这使他们的结果基本上无法重现)。