OpenCV 4.11.0
开源计算机视觉库
|
上一教程: 改变图像的对比度和亮度!
下一教程: 使用 XML/YAML/JSON 文件进行文件输入和输出
原作者 | Bernát Gábor |
兼容性 | OpenCV >= 3.0 |
我们将寻求以下问题的答案
这是dft() 的示例用法
傅里叶变换将把图像分解成它的正弦和余弦分量。换句话说,它将把图像从空间域转换到频域。其思想是任何函数都可以用无限个正弦和余弦函数之和精确逼近。傅里叶变换是一种实现这种逼近的方法。从数学上讲,二维图像的傅里叶变换是
\[F(k,l) = \displaystyle\sum\limits_{i=0}^{N-1}\sum\limits_{j=0}^{N-1} f(i,j)e^{-i2\pi(\frac{ki}{N}+\frac{lj}{N})}\]
\[e^{ix} = \cos{x} + i\sin {x}\]
这里f是图像在空间域中的值,F是在频域中的值。变换的结果是复数。显示可以通过实数图像和复数图像或通过幅度和相位图像来实现。然而,在整个图像处理算法中,只有幅度图像是有趣的,因为它包含了我们关于图像几何结构所需的所有信息。但是,如果您打算以这些形式对图像进行一些修改,然后需要重新变换它,则需要保留两者。
在这个示例中,我将展示如何计算和显示傅里叶变换的幅度图像。对于数字图像来说是离散的。这意味着它们可以从给定的域值中取一个值。例如,在基本的灰度图像中,值通常在0到255之间。因此,傅里叶变换也需要是离散类型的,从而产生离散傅里叶变换 (DFT)。当您需要从几何角度确定图像的结构时,您将需要使用它。以下是步骤 (对于灰度输入图像I)
离散傅里叶变换 (DFT) 的性能取决于图像大小。对于大小是 2、3 和 5 的倍数的图像,其速度往往最快。因此,为了获得最大性能,通常最好向图像添加边界值以获得具有此类特征的大小。getOptimalDFTSize() 函数返回此最佳大小,我们可以使用 copyMakeBorder() 函数扩展图像的边界(附加像素初始化为零)。
傅里叶变换的结果是复数。这意味着对于每个图像值,结果是两个图像值(每个分量一个)。此外,频域范围远大于其空间对应部分。因此,我们通常至少以float格式存储这些值。因此,我们将输入图像转换为这种类型,并扩展它以添加另一个通道来保存复数值。
可以进行就地计算(输入与输出相同)。
复数具有实部 (Re) 和虚部 (Im)。DFT 的结果是复数。DFT 的幅度为
\[M = \sqrt[2]{ {Re(DFT(I))}^2 + {Im(DFT(I))}^2}\]
转换为 OpenCV 代码
事实证明,傅里叶系数的动态范围太大,无法在屏幕上显示。我们有一些变化很小和变化很大的值,我们无法这样观察到。因此,较大的值将全部显示为白色点,而较小的值则显示为黑色点。为了将灰度值用于可视化,我们可以将线性尺度转换为对数尺度。
\[M_1 = \log{(1 + M)}\]
转换为 OpenCV 代码
记住,在第一步中,我们扩展了图像?现在是时候丢弃新引入的值了。为了可视化目的,我们还可以重新排列结果的象限,以便原点 (零,零) 与图像中心对应。
这同样是为了可视化目的。我们现在有了幅度,但是这些仍然超出了我们图像显示范围(零到一)。我们使用 cv::normalize() 函数将我们的值归一化到此范围。
一个应用想法是确定图像中存在的几何方向。例如,让我们找出文本是否是水平的?观察一些文本,你会注意到文本行也形成水平线,字母也形成垂直线。文本片段的这两个主要组成部分也可以在傅里叶变换中看到。让我们使用这张水平的图像和这张旋转的图像(关于文本)。
对于水平文本的情况
对于旋转文本的情况
您可以看到频域中最有影响的成分(幅度图像上最亮的点)遵循图像上对象的几何旋转。由此,我们可以计算偏移量并执行图像旋转以纠正可能的错位。