【翻譯:OpenCV-Python教程】影象的幾何變換
⚠️這個系列是自己瞎翻的,文法很醜,主要靠意會,跳著跳著撿重要的部分翻,翻錯了不負責,就這樣哈。
⚠️基於3.4.3,Geometric Transformations of Images,附原文。
目標
- 學會對影象應用不同的幾何變換,比如平移、旋轉、仿射變換等等。
- 你會遇到這些方法: cv.getPerspectiveTransform
變換
OpenCV提供了兩個轉換方法,cv.warpAffine 和 cv.warpPerspective,用他們你可以完成所有型別的轉換。cv.warpAffine 用了 2x3 轉換矩陣作為引數,而
放縮
縮放只是調整影象大小。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) #OR height, width = img.shape[:2] res = cv.resize(img,(2*width, 2*height), interpolation = cv.INTER_CUBIC)
平移對映
平移對映就是在改變物體的位置,比如你知道 (x,y) ,要把它偏移到 (tx,ty) 的位置,你就要創造一個對映矩陣 M 如下:
你可以把它裝成一個 np.float32 型的Numpy陣列,並且傳入 cv.warpAffine() 方法中,看以下的程式碼(把(0,0))轉換到(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() 方法的第三個引數是以**(寬, 高)**格式表示的輸出影象的大小,記住寬等於列數,高等於行數。
看以下結果
旋轉
要旋轉一個影象 θ 角度,要通過這種格式的一個對映矩陣:
但 OpenCV 提供了擴充套件過的旋轉,通過可調整的旋轉中心,你可以在你想要的任意地點開始旋轉。修改過的對映矩陣給出如下:
其中
α=scale⋅cosθ,β=scale⋅sinθ
要找出這個對映矩陣,OpenCV 提供了一個方法,cv.getRotationMatrix2D 。檢視以下例子,以影象中心旋轉影象90度,並且不做任何拉伸。
img = cv.imread('messi5.jpg',0)
rows,cols = img.shape
# cols-1 and rows-1 are the coordinate limits.
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')
plt.show()
看結果:
透視變換
要完成透視變換,你需要一個 3x3 的對映矩陣,直線會在對映之後保持筆直。要找到這個對映矩陣,你需要四個原圖上的點,以及它們在轉換後圖像上對應的位置。在這四個點中,其中任意三個不能共線。
然後這個對映矩陣可以通過方法 cv.getPerspectiveTransform 來拿到,然後再把這個 3x3 對映矩陣應用於 cv.warpPerspective 方法上。
看以下程式碼:
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()
結果:
額外資源
- "Computer Vision: Algorithms and Applications", Richard Szeliski (計算機視覺:演算法和應用)
Exercises
翻譯OpenCV-Python教程 影象閾值 Translate OpenCV-Python tutorial image threshold 輕靈劃譯 資料來源: