導讀
在圖像處理中,我們經常需要對圖像進行各種操作如
平移、縮放、旋轉、翻轉等,這些操作都屬於圖像的仿射變換,我們通過一個變換矩陣就能很容易的實現。本篇文章詳細的介紹了各種操作的實現原理,以及代碼的實現和使用仿射變換
仿射變換也稱仿射投影,是指幾何中,對一個向量空間進行線性變換並接上一個平移,變換為另一個向量空間。所以,仿射變換其實也就是在講如何來進行兩個向量空間的變換
假設有一個向量空間k:
和另一個向量空間j:
如果我們想要將向量空間由k變為j,可以通過下面的公式來實現:
將上式進行拆分可得
我們再將上式轉換為矩陣的乘法
上式表明通過一個兩行三列的矩陣M就可以實現兩個向量空間之間的轉換,在進行仿射變換的時候我們也只需要一個矩陣M就可以實現圖像的
平移、縮放、旋轉和翻轉變換。接下來,會先介紹原理然後利用OpenCV來實現相應的例子,這裡主要利用OpenCV的warpAffine函數來實現仿射變換
warpAffine函數參數:
- src:輸入的圖像數組
- M:仿射變換矩陣
- dsize:變換後圖像的大小
- flags:使用的插值算法
- borderValue:邊界的填充值
圖像平移
在平面座標系有點P(x,y)和點P′(x′,y′),如果我們想要將P點移動到P′通過下面的變換就可以實現
其中Δx和Δy就是x方向上和y方向上的偏移量,我們將其轉換為矩陣的形式上面的矩陣MM就是仿射變換的平移參數,接下來我們利用OpenCV中的warpAffine函數來實現
上面的
矩陣M就是仿射變換的平移參數,接下來我們利用OpenCV中的warpAffine函數來實現圖像的平移圖像翻轉
有時候我們我們需要對圖像進行水平翻轉、垂直翻轉、鏡像翻轉(同時進行水平和垂直翻轉),想要實現這個功能並不難,我們可以通過opencv內置的flip方法很容易實現,還可以通過numpy的索引來實現,當然也可以通過仿射變換矩陣來實現這個功能
上圖中的A、B、C、D表示圖像的四個頂點,如果我們需要對圖像進行水平翻轉,那麼我們就需要將A點和B點進行交換,C點和D點進行交換,沿著x軸的中線進行對稱交換位置,通過下面的式子可以實現水平翻轉
上式中的w表示圖像的寬,同理可得垂直翻轉的實現公式
上式中的h表示的是圖像的高
- 利用變換矩陣翻轉圖像
水平翻轉的變換矩陣M:
垂直翻轉的變換矩陣M:
鏡像翻轉的變換矩陣M:
- OpenCV的flip函數翻轉圖像
flip函數參數:
- src:輸入的圖像數組
- flipCode:圖像翻轉參數,1表示水平翻轉,0表示垂直翻轉,-1表示鏡像翻轉
- numpy的索引翻轉圖像
圖像縮放
如果我們想要對座標系的P點進行縮放操作,通過下面的公式就可以實現
通過在x和y前面添加一個縮放係數即可,同樣我們將其轉換為矩陣形式
通過上面的矩陣M我們就可以實現對圖片的縮放
這裡使用仿射變換實現的圖片縮放其實和resize函數的效果是一樣的,縮放時選擇的插值函數不同最終效果會有所偏差
圖像旋轉
- 圍繞原點旋轉
我們先來看看一個二維平面上的點在圍繞原點是如何旋轉的
上圖中點v在圍繞原點旋轉θ度 之後得到了點v′,我們將座標點用極座標的形式來表示可以得到v(rcosϕ,rsinϕ),所以v′(rcos(θ+ϕ),rsin(θ+ϕ))利用正弦和餘弦展開式將其展開可得,對於v點來說:
對於v′來說:
然後我們再將x和y代入上式可得
然後再將上式用矩陣M表示,可得
特別注意:我們在建立直角座標系的時候是以左下角為原點建立的,然而對於圖像而言是以左上角為原點 建立的,所以我們需要對角度θ進行取反,結合三角函數的特性,M矩陣的表達式如下
還需要注意的是這裡的角度都是弧度制,所以我們在使用的時候還需要對其進行轉換,轉換代碼如下
<code>#將角度轉換為弧度制
radian_theta = theta/180 * np.pi#np.pi指的是π/<code>
將圖片圍繞原點進行逆時針旋轉θ度的代碼如下
- 圍繞任意點旋轉
如果我們想圍繞任意座標點旋轉呢?其實也並不難,下圖的v點在圍繞c點(a,b)旋轉90度得到v′ 。其實我們可以將其等價於,先將V點平移到V1點,然後再將V1點圍繞原點旋轉90度得到V2點,最後再將V2點沿著V點平移的反方向平移相同長度,最終得到V'。這樣我們就將圍繞任意座標點旋轉的問題轉換成了圍繞原點旋轉的問題
我們來回顧一下,圍繞原點旋轉座標的變換公式
在圍繞原點旋轉變換公式的基礎上,我們將其改進為圍繞任意點c(a,b)旋轉,我們現在原來的座標進行平移,得到變換後的座標,最後再沿著之前平移的反方向進行平移,就得到圍繞任意點旋轉的變換公式
將其展開可得
將上式用矩陣M表示:
上式中的c(a,b)表示旋轉中心,因為座標系問題需要對θ進行取反,最終M矩陣的表達式如下
細心的同學也許已經發現了,上圖中圍繞圖像中心旋轉後的圖片部分被裁剪掉了,如果我們想讓旋轉之後的圖片仍然是完整,應該如何修改呢?
閱讀更多 機器學習之路 的文章