影象的仿射變換
目錄:
概述
影象基本變換
仿射變換
原理
python實現
一、概述
影象的幾何變換主要包括:平移、縮放、旋轉、仿射、透視等等。影象變換是建立在矩陣運算基礎上的,透過矩陣運算可以很快的找到不同影象的對應關係。理解變換的原理需要理解變換的構造方法以及矩陣的運算方法。
影象的幾何變換主要分為三類:剛性變換、仿射變換和透視變換,如下圖:
仿射變換是從一個二維座標系變換到另一個二維座標系,屬於線性變換。透過已知3對座標點可以求得變換矩陣。
透視變換是從一個二維座標系變換到一個三維座標系,屬於非線性變換。透過已知4對座標點可以求得變換矩陣。
二、影象基本變換
影象的幾何變換包含很多變換,其中有一些基本變換,而仿射變換和透視變換就是對這些基本變換進行組合實現的。
基本變換具體包括:平移(Translation)、縮放(Scale)、旋轉(Rotation)、翻轉(Flip)和錯切(Shear)。
a。 平移
b。 縮放
c。 旋轉
d。 翻轉
e。 錯切
錯切亦稱為剪下或錯位變換,包含水平錯切和垂直錯切,常用於產生彈性物體的變形處理。
下面這張圖可能更形象:
三、仿射變換
3。1、原理
對於二維座標系的一個座標點(x,y),可以使用一個2x2矩陣來調整x,y的值,而透過調整x,y可以實現二維形狀的線性變換(旋轉,縮放),所以整個轉換過程就是對(x,y)調整的過程。
仿射變換(Affine Transformation)是指在向量空間中進行一次線性變換(乘以一個矩陣)和一次平移(加上一個向量),變換到另一個向量空間的過程。
仿射變換代表的是兩幅圖之間的對映關係,仿射變換矩陣為2x3的矩陣,如下圖中的矩陣M,其中的B起著
平移
的作用,而A中的對角線決定
縮放
,反對角線決定
旋轉
或
錯切
。
所以仿射變換可以由一個矩陣A和一個向量B給出:
原畫素點座標(x,y),經過仿射變換後的點的座標是T,則矩陣仿射變換基本演算法原理:
所以仿射變換是一種二維座標(x, y)到二維座標(u, v)的線性變換,其數學表示式如下:
其實到這裡還沒完,我們知道縮放和旋轉透過矩陣乘法來實現,而平移是透過矩陣加法來實現的,為了將這幾個操作都透過一個矩陣來實現,所以構造出了上面那個 2x3 的矩陣。
但是這個會改變影象的尺寸,比如一個 2x2 的影象,乘以 2x3 的矩陣,會得到 2x3 的影象,所以為了解決這個問題,我們就增加一個維度,也就是構造齊次座標矩陣。
關於
齊次座標
的更多內容可以檢視這裡,還有這裡。
最終得到的齊次座標矩陣表示形式為:
仿射變換保持了二維影象的“
平直性
”和“
平行性
”:
平直性:
直線經仿射變換後還是直線
圓弧經仿射變換後還是圓弧
平行性:
直線之間的相對位置關係保持不變
平行線經仿射變換後依然為平行線
直線上點的位置順序不會發生變化
向量間夾角可能會發生變化
3。2、python實現
透過仿射變換將圖片中的每個畫素點按照一定的規律對映到新的位置,仿射變化需要一個轉換矩陣,但是由於仿射變換比較複雜,一般很難直接找到這個矩陣,opencv提供了根據源影象和目標影象上三個對應的點來自動建立變換矩陣,矩陣維度為 2x3。
兩個影象中非共線的三對對應點確定唯一的一個仿射變換。經仿射變換後,影象中的三個關鍵點依然構成三角形,但三角形形狀已經發生變化。
這個函式是
cv2。getAffineTransform(pos1,pos2)
,其中兩個位置就是變換前後的對應位置關係。輸出的就是仿射矩陣M,最後這個矩陣會被傳給函式
cv2。warpAffine()
來實現仿射變換。
原圖為:
import
cv2
import
numpy
as
np
img
=
cv2
。
imread
(
‘image0。jpg’
,
1
)
height
,
width
=
img
。
shape
[:
2
]
# 405x413
# 在原影象和目標影象上各選擇三個點
matSrc
=
np
。
float32
([[
0
,
0
],[
0
,
height
-
1
],[
width
-
1
,
0
]])
matDst
=
np
。
float32
([[
0
,
0
],[
30
,
height
-
30
],[
width
-
30
,
30
]])
# 得到變換矩陣
matAffine
=
cv2
。
getAffineTransform
(
matSrc
,
matDst
)
# 進行仿射變換
dst
=
cv2
。
warpAffine
(
img
,
matAffine
,
(
width
,
height
))
變換矩陣的資料型別是
np。float32
,函式
cv2。warpAffine()
的第三個引數是輸出影象的尺寸(寬,高)。
仿射變換後的圖:
因為平移和縮放的矩陣的比較簡單,我們可以直接手動指定。
# 影象平移
# 移位矩陣,水平方向移動100個畫素,豎直方向移動200個畫素
matShift
=
np
。
float32
([[
1
,
0
,
100
],[
0
,
1
,
200
]])
# 2行3列
dst
=
cv2
。
warpAffine
(
img
,
matShift
,
(
width
,
height
))
# 影象縮放
# 縮放矩陣,長寬各縮放一半
matScale
=
np
。
float32
([[
0。5
,
0
,
0
],[
0
,
0。5
,
0
]])
dst
=
cv2
。
warpAffine
(
img
,
matScale
,
(
int
(
width
/
2
),
int
(
height
/
2
)))
向左下平移:
縮小50%:
要實現影象旋轉,需要透過
cv2。getRotationMatrix2D
來得到二維旋轉變換矩陣(2行3列)。
cv2。getRotationMatrix2D
三個引數分別為:1。旋轉中心,2。旋轉角度,3。縮放比例。角度為正,則影象逆時針旋轉,旋轉後圖像可能會超出邊界。
matRotate
=
cv2
。
getRotationMatrix2D
((
width
*
0。5
,
height
*
0。5
),
45
,
1。0
)
dst
=
cv2
。
warpAffine
(
img
,
matRotate
,
(
width
,
height
))
如果覺得有用,點個贊吧(ง •̀_•́)ง。