OpenCV 4.12.0
開源計算機視覺
載入中...
搜尋中...
無匹配項
仿射變換

上一個教程: 重對映
下一個教程: 直方圖均衡化

原始作者Ana Huamán
相容性OpenCV >= 3.0

目標

在本教程中,您將學習如何

理論

什麼是仿射變換?

  1. 一種可以透過矩陣乘法(線性變換)然後進行向量加法(平移)來表示的變換。
  2. 由上可知,我們可以使用仿射變換來表達

    1. 旋轉(線性變換)
    2. 平移(向量加法)
    3. 縮放操作(線性變換)

    您可以看到,仿射變換本質上表示了兩個影像之間的關係

  3. 表示仿射變換的常用方法是使用 \(2 \times 3\) 矩陣。

    \[ A = \begin{bmatrix} a_{00} & a_{01} \\ a_{10} & a_{11} \end{bmatrix}_{2 \times 2} B = \begin{bmatrix} b_{00} \\ b_{10} \end{bmatrix}_{2 \times 1} \]

    \[ M = \begin{bmatrix} A & B \end{bmatrix} = \begin{bmatrix} a_{00} & a_{01} & b_{00} \\ a_{10} & a_{11} & b_{10} \end{bmatrix}_{2 \times 3} \]

    考慮到我們想使用 \(A\) 和 \(B\) 變換一個二維向量 \(X = \begin{bmatrix}x \\ y\end{bmatrix}\),我們也可以透過以下方式實現:

    \(T = A \cdot \begin{bmatrix}x \\ y\end{bmatrix} + B\) 或 \(T = M \cdot [x, y, 1]^{T}\)

    \[T = \begin{bmatrix} a_{00}x + a_{01}y + b_{00} \\ a_{10}x + a_{11}y + b_{10} \end{bmatrix}\]

如何獲取仿射變換?

  1. 我們提到仿射變換本質上是兩個影像之間的關係。關於這種關係的資訊大致可以透過兩種方式獲得:
    1. 我們同時知道 \(X\) 和 \(T\),並且知道它們之間存在關係。那麼我們的任務就是找到 \(M\)
    2. 我們知道 \(M\) 和 \(X\)。要獲取 \(T\),我們只需要應用 \(T = M \cdot X\)。關於 \(M\) 的資訊可以是顯式的(即擁有 2x3 矩陣),也可以是點之間的幾何關係。
  2. 讓我們更好地解釋這一點(b)。由於 \(M\) 關聯兩個影像,我們可以分析最簡單的情況,即它關聯兩個影像中的三個點。請看下圖

點1、2和3(在影像1中形成一個三角形)被對映到影像2中,仍然形成一個三角形,但現在它們已經發生了顯著變化。如果我們用這3個點找到仿射變換(您可以隨意選擇它們),那麼我們就可以將這種找到的關係應用於影像中的所有畫素。

程式碼

  • 此程式的作用是什麼?
    • 載入影像
    • 對影像應用仿射變換。此變換是透過三個點之間的關係獲得的。我們為此使用函式 cv::warpAffine
    • 對變換後的影像應用旋轉。此旋轉是相對於影像中心的
    • 等待使用者退出程式

解釋

  • 載入影像

  • 仿射變換:如上所述,我們需要兩組3個點來推導仿射變換關係。請看

    您可能想繪製這些點,以便更好地瞭解它們如何變化。它們的位置與示例圖(在理論部分)中所示的位置大致相同。您可能會注意到由3個點定義的三角形的大小和方向發生了變化。

  • 有了這兩組點,我們使用OpenCV函式 cv::getAffineTransform 計算仿射變換。

    我們得到一個 \(2 \times 3\) 矩陣作為輸出(在本例中為 warp_mat

  • 然後我們將剛剛找到的仿射變換應用於源影像

    引數如下

    • src: 輸入影像
    • warp_dst: 輸出影像
    • warp_mat: 仿射變換
    • warp_dst.size(): 輸出影像的期望尺寸

    我們剛剛得到了第一張變換後的影像!我們將在一會兒顯示它。在此之前,我們還想旋轉它...

  • 旋轉:要旋轉影像,我們需要知道兩件事

    1. 影像將圍繞其旋轉的中心
    2. 要旋轉的角度。在OpenCV中,正角度表示逆時針方向
    3. 可選: 縮放因子

    我們透過以下程式碼片段定義這些引數

  • 我們使用OpenCV函式 cv::getRotationMatrix2D 生成旋轉矩陣,它返回一個 \(2 \times 3\) 矩陣(在本例中為 rot_mat

  • 現在我們將找到的旋轉應用於我們先前變換的輸出影像

  • 最後,我們會在兩個視窗中顯示結果,並額外顯示原始影像以作比較

  • 我們只需等待使用者退出程式

結果

  • 編譯上述程式碼後,我們可以將影像路徑作為引數傳遞。例如,對於一張圖片,如下所示:

應用第一次仿射變換後,我們得到

最後,在應用負旋轉(請記住負值表示順時針)和縮放因子後,我們得到