OpenCV 4.12.0
開源計算機視覺
載入中...
搜尋中...
無匹配項
離散傅立葉變換

上一個教程: 改變影像的對比度和亮度!
下一個教程: 使用XML / YAML / JSON檔案進行檔案輸入和輸出

原始作者Bernát Gábor
相容性OpenCV >= 3.0

目標

我們將尋找以下問題的答案

  • 什麼是傅立葉變換,為什麼要使用它?
  • 如何在OpenCV中實現?
  • 使用以下函式: copyMakeBorder()merge()dft()getOptimalDFTSize()log()normalize()

原始碼

以下是 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() 函式來擴充套件影像的邊界(附加的畫素用零初始化)

為複數值和實數值騰出空間

傅立葉變換的結果是複數。這意味著對於每個影像值,結果是兩個影像值(每個分量一個)。此外,頻率域的範圍比其空間域對應物大得多。因此,我們通常至少以*浮點*格式儲存這些值。因此,我們會將輸入影像轉換為此型別,並用另一個通道來儲存複數值。

進行離散傅立葉變換

可以進行原地計算(輸入和輸出相同)

將實數值和複數值轉換為幅度

複數有一個實部(Re)和一個復(虛部 - Im)部分。DFT的結果是複數。DFT的幅度是

\[M = \sqrt[2]{ {Re(DFT(I))}^2 + {Im(DFT(I))}^2}\]

轉換為OpenCV程式碼

切換到對數尺度

傅立葉係數的動態範圍太大,無法在螢幕上顯示。我們有一些小值和一些變化大的值,無法這樣觀察。因此,高值將全部顯示為白點,而小值將顯示為黑點。為了使用灰度值進行視覺化,我們可以將線性尺度轉換為對數尺度

\[M_1 = \log{(1 + M)}\]

轉換為OpenCV程式碼

裁剪和重排

還記得第一步中我們擴充套件了影像嗎?現在是時候丟棄新引入的值了。為了視覺化目的,我們還可以重新排列結果的象限,以便原點(零,零)與影像中心對應。

歸一化

再次這樣做是為了視覺化目的。我們現在有了幅度,但這些值仍然超出我們影像顯示範圍(0到1)。我們使用 cv::normalize() 函式將我們的值歸一化到此範圍。

結果

一個應用想法是確定影像中存在的幾何方向。例如,我們能否判斷一段文字是水平的還是傾斜的?觀察一些文字,你會發現文字行會形成水平線,而字母會形成垂直線。文字片段的這兩個主要組成部分也可以在傅立葉變換中看到。讓我們使用這張水平文字影像和這張旋轉文字影像

對於水平文字

對於旋轉文字

你可以看到頻率域中最具影響力的分量(幅度影像上最亮點)遵循影像上物體的幾何旋轉。由此我們可以計算偏移量並執行影像旋轉以糾正最終的未對齊。