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

标签 c++ image algorithm opencv image-processing

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

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

enter image description here

enter image description here

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

enter image description here

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

此外,我像这样使用 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. 对每个 block 进行灰度膨胀
  2. 找到膨胀等于原始值的地方

但是,我还是没看清楚。这是否意味着我可以对我的灰度图像采用逐 block 形态膨胀操作(在进一步处理之前,我已经在 OpenCV 中将我的图像从 RGB 转换为灰度)? dilation equals original values 这个词是否意味着形态学膨胀后的像素强度等于其原始值?我在这里迷路了。

最佳答案

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

我想问题的核心是噪声信号中“什么是峰值,什么只是噪声”的区别(因为 RL 输入图像在某种意义上总是有噪声;我认为用于峰值检测的相关输入 vector 您的代码是 xSignature)。确定峰值后,计算平均峰值距离应该相当简单。

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

平滑

如果您知道预期的峰宽w,您可以首先应用一些平滑处理,通过在大约预期峰宽的窗口上求和来消除较小范围内的噪声 (从 x-w/2 到 x+w/2)。您实际上不需要计算滑动窗口的平均值(除以 w),因为对于峰值检测,绝对比例无关紧要,总和与平均值成正比。

最小-最大-识别

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

评估检测到的峰的质量

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

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

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

区分峰和非峰

以递减的质量迭代你的峰值。可能整理出所有不满足最小或最大宽度/高度/质量/到具有更高质量/...要求的最近峰值的距离,以使它们成为您的问题域中的峰值。保留其余部分。完成。

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

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

关于c++ - 如何理解频率图像中描述的平均像素数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28230982/

相关文章:

c++ - 通过索引访问元组元素 c++11

android ndk 和 eclipse 给出了关于 c++ getline() 函数的不同错误信息

c++ - R 和 B 被垂直线分隔时的双色最接近对(继续)

c++ - 这个洗牌算法有什么问题吗?

java - 在 Java 中生成以不同数字开头的数字模式

c++ - 3D 立方体绘图,只有一侧始终在最上面

c++ - 将 C++ 本地字符串返回给另一个函数

PHP上传文件 - 仅检查图像

image - 如何使用imagemagick向图像添加带有一些填充的内边框?

css - 在 mozilla 上使用图像源到 base64 时,使用 css 的背景图像不起作用