OpenCV-Python 圖像的幾何變換 | 十四

2019-12-13   人工智慧遇見磐創

目標

  • 學習將不同的幾何變換應用到圖像上,如平移、旋轉、仿射變換等。
  • 你會看到這些函數: cv.getPerspectiveTransform

變換

OpenCV提供了兩個轉換函數cv.warpAffinecv.warpPerspective,您可以使用它們進行各種轉換。cv.warpAffine採用2x3轉換矩陣,而cv.warpPerspective採用3x3轉換矩陣作為輸入。

縮放

縮放只是調整圖像的大小。為此,OpenCV帶有一個函數cv.resize()。圖像的大小可以手動指定,也可以指定縮放比例。也可使用不同的插值方法。首選的插值方法是cv.INTER_AREA用於縮小,cv.INTER_CUBIC(慢)和cv.INTER_LINEAR用於縮放。默認情況下,出於所有調整大小的目的,使用的插值方法為cv.INTER_LINEAR。您可以使用以下方法調整輸入圖像的大小:

import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg')
res = cv.resize(img,None,fx=2, fy=2, interpolation = cv.INTER_CUBIC)
#或者
height, width = img.shape[:2]
res = cv.resize(img,(2*width, 2*height), interpolation = cv.INTER_CUBIC)

平移

平移是物體位置的移動。如果您知道在(x,y)方向上的位移,則將其設為(t_x,$ty$),你可以創建轉換矩陣M,如下所示:

您可以將其放入np.float32類型的Numpy數組中,並將其傳遞給cv.warpAffine函數。參見下面偏移為(100, 50)的示例:

import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg',0)
rows,cols = img.shape
M = np.float32([[1,0,100],[0,1,50]])
dst = cv.warpAffine(img,M,(cols,rows))
cv.imshow('img',dst)
cv.waitKey(0)
cv.destroyAllWindows()

注意

cv.warpAffine函數的第三個參數是輸出圖像的大小,其形式應為(width,height)。記住width =列數,height =行數。

你將看到下面的結果:

旋轉

圖像旋轉角度為$θ$是通過以下形式的變換矩陣實現的:

但是OpenCV提供了可縮放的旋轉以及可調整的旋轉中心,因此您可以在自己喜歡的任何位置旋轉。修改後的變換矩陣為

其中:

為了找到此轉換矩陣,OpenCV提供了一個函數cv.getRotationMatrix2D。請檢查以下示例,該示例將圖像相對於中心旋轉90度而沒有任何縮放比例。

img = cv.imread('messi5.jpg',0)
rows,cols = img.shape
# cols-1 和 rows-1 是坐標限制
M = cv.getRotationMatrix2D(((cols-1)/2.0,(rows-1)/2.0),90,1)
dst = cv.warpAffine(img,M,(cols,rows))

查看結果:

仿射變換

在仿射變換中,原始圖像中的所有平行線在輸出圖像中仍將平行。為了找到變換矩陣,我們需要輸入圖像中的三個點及其在輸出圖像中的對應位置。然後cv.getAffineTransform將創建一個2x3矩陣,該矩陣將傳遞給cv.warpAffine

查看以下示例,並查看我選擇的點(以綠色標記):

img = cv.imread('drawing.png')
rows,cols,ch = img.shape
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])
M = cv.getAffineTransform(pts1,pts2)
dst = cv.warpAffine(img,M,(cols,rows))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')

查看結果:

透視變換

對於透視變換,您需要3x3變換矩陣。即使在轉換後,直線也將保持直線。要找到此變換矩陣,您需要在輸入圖像上有4個點,在輸出圖像上需要相應的點。在這四個點中,其中三個不應共線。然後可以通過函數cv.getPerspectiveTransform找到變換矩陣。然後將cv.warpPerspective應用於此3x3轉換矩陣。

請參見下面的代碼:

img = cv.imread('sudoku.png')
rows,cols,ch = img.shape
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
M = cv.getPerspectiveTransform(pts1,pts2)
dst = cv.warpPerspective(img,M,(300,300))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()

結果:

其他資源

  1. "Computer Vision: Algorithms and Applications", Richard Szeliski