常見的2D圖像變換從原理上講主要包括基於2×3矩陣的仿射變換和基於3×3矩陣透視變換。
仿射變換
原理
基本的圖像變換就是二維坐標的變換:從一種二維坐標(x,y)到另一種二維坐標(u,v)的線性變換:
如果寫成矩陣的形式,就是:
作如下定義:
矩陣T(2×3)就稱為仿射變換的變換矩陣,R為線性變換矩陣,t為平移矩陣,簡單來說,仿射變換就是線性變換+平移。變換后直線依然是直線,平行線依然是平行線,直線間的相對位置關系不變,因此非共線的三個對應點便可確定唯一的一個仿射變換,線性變換4個自由度+平移2個自由度→仿射變換自由度為6。
opencv中實現仿射變換
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread('drawing.jpg')
rows, cols = img.shape[:2]
# 變換前的三個點
pts1 = np.float32([[50, 65], [150, 65], [210, 210]])
# 變換后的三個點
pts2 = np.float32([[50, 100], [150, 65], [100, 250]])
# 生成變換矩陣
M = cv.getAffineTransform(pts1, pts2)
# 第三個參數為dst的大小
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()
實驗結果

應用opencv中現成的圖像平移、旋轉、縮放、翻轉
請參考 opencv實現圖像幾何變換
平移
平移就是x和y方向上的直接移動,可以上下/左右移動,自由度為2,變換矩陣可以表示為:
旋轉
旋轉是坐標軸方向饒原點旋轉一定的角度θ,自由度為1,不包含平移,如順時針旋轉可以表示為:
翻轉
翻轉是x或y某個方向或全部方向上取反,自由度為2,比如這里以垂直翻轉為例:
剛體變換
旋轉+平移也稱剛體變換(Rigid Transform),就是說如果圖像變換前后兩點間的距離仍然保持不變,那么這種變化就稱為剛體變換。剛體變換包括了平移、旋轉和翻轉,自由度為3。由於只是旋轉和平移,剛體變換保持了直線間的長度不變,所以也稱歐式變換(變化前后保持歐氏距離)。變換矩陣可以表示為:
縮放
縮放是x和y方向的尺度(倍數)變換,在有些資料上非等比例的縮放也稱為拉伸/擠壓,等比例縮放自由度為1,非等比例縮放自由度為2,矩陣可以表示為:
相似變換
相似變換又稱縮放旋轉,相似變換包含了旋轉、等比例縮放和平移等變換,自由度為4。在OpenCV中,旋轉就是用相似變換實現的:
若縮放比例為scale,旋轉角度為θ,旋轉中心是(centerx,centery),則仿射變換可以表示為:
其中:
相似變換相比剛體變換加了縮放,所以並不會保持歐氏距離不變,但直線間的夾角依然不變。
透視變換
前面仿射變換后依然是平行四邊形,並不能做到任意的變換。
原理
透視變換(Perspective Transformation)是將二維的圖片投影到一個三維視平面上,然后再轉換到二維坐標下,所以也稱為投影映射(Projective Mapping)。簡單來說就是二維→三維→二維的一個過程。
透視變換公式:
透視變換矩陣表示:
仿射變換是透視變換的子集。接下來再通過除以Z軸轉換成二維坐標:
透視變換相比仿射變換更加靈活,變換后會產生一個新的四邊形,但不一定是平行四邊形,所以需要非共線的四個點才能唯一確定,原圖中的直線變換后依然是直線。因為四邊形包括了所有的平行四邊形,所以透視變換包括了所有的仿射變換。
opencv中實現透視變換
OpenCV中首先根據變換前后的四個點用cv.getPerspectiveTransform()生成3×3的變換矩陣,然后再用cv.warpPerspective()進行透視變換。
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
img = cv.imread('card.jpg')
# 原圖中卡片的四個角點
pts1 = np.float32([[148, 80], [437, 114], [94, 247], [423, 288]])
# 變換后分別在左上、右上、左下、右下四個點
pts2 = np.float32([[0, 0], [320, 0], [0, 178], [320, 178]])
# 生成透視變換矩陣
M = cv.getPerspectiveTransform(pts1, pts2)
# 進行透視變換,參數3是目標圖像大小
dst = cv.warpPerspective(img, M, (320, 178))
plt.subplot(121), plt.imshow(img[:, :, ::-1]), plt.title('input')
plt.subplot(122), plt.imshow(dst[:, :, ::-1]), plt.title('output')
plt.show()
實驗結果

總結
圖解圖像各種變換










縮放是x和y方向的尺度(倍數)變換,在有些資料上非等比例的縮放也稱為拉伸/擠壓,等比例縮放自由度為1,非等比例縮放自由度為2,矩陣可以表示為:







