今天遇到一個問題是關於仿射變換的,但是由於沒有將仿射變換的具體原理型明白,看別人的代碼看的很費解,最后終於在師兄的幫助下將原理弄明白了,我覺得最重要的是理解仿射變換可以看成是幾種簡單變換的復合實現,
具體實現形式即將幾種簡單變換的變換矩陣M相乘,這樣就很容易理解啦
定義:仿射變換的功能是從二維坐標到二維坐標之間的線性變換,且保持二維圖形的“平直性”和“平行性”。仿射變換可以通過一系列的原子變換的復合來實現,包括平移,縮放,翻轉,旋轉和剪切。
這類變換可以用一個3*3的矩陣M來表示,其最后一行為(0,0,1)。該變換矩陣將原坐標為(x,y)變換為新坐標(x',y'),
即
opencv中相應的函數是:
void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())¶
Parameters:
- src – input image.
- dst – output image that has the size dsize and the same type as src .
- M –
transformation matrix,最重要的東東了,本文中着重講M的構造 - dsize – size of the output image.
- flags – combination of interpolation methods (see resize() ) and the optional flag WARP_INVERSE_MAP that means that M is the inverse transformation (
). - borderMode – pixel extrapolation method (see borderInterpolate()); when borderMode=BORDER_TRANSPARENT , it means that the pixels in the destination image corresponding to the “outliers” in the source image are not modified by the function.
- borderValue – value used in case of a constant border; by default, it is 0.
下面介紹一些典型的仿射變換:
(1)平移,將每一點移到到(x+t , y+t),變換矩陣為
(2)縮放變換 將每一點的橫坐標放大或縮小sx倍,縱坐標放大(縮小)到sy倍,變換矩陣為
(3)旋轉變換原點:目標圖形圍繞原點順時針旋轉Θ 弧度,變換矩陣為
(4) 旋轉變換 :目標圖形以(x , y )為軸心順時針旋轉θ弧度,變換矩陣為
相當於兩次平移與一次原點旋轉變換的復合,即先將軸心(x,y)移到到原點,然后做旋轉變換,最后將圖片的左上角置為圖片的原點,即
有的人可能會說為什么這么復雜呢,那是因為在opencv的圖像處理中,所有對圖像的處理都是從原點進行的,而圖像的原點默認為圖像的左上角,而我們對圖像作旋轉處理時一般以圖像的中點為軸心,因此就需要做如下處理
如果你覺得這樣很麻煩,可以使用opencv中自帶的Mat getRotationMatrix2D(Point2f center, double angle, double scale)函數獲得變換矩陣M,
center:旋轉中心
angle:旋轉弧度,一定要將角度轉換成弧度
scale:縮放尺度
它得到的矩陣是:
其中α = scale * cos( angle ) , β = scale * sing( angle ) , ( center.x , center.y ) 表示旋轉軸心
但是不得不說opencv的文檔以及相關書籍中都把這個矩陣寫錯了,如下:
建議大家自己通過下式驗證一下,即首先將軸心(x,y)移到原點,然后做旋轉平綻放變換,最后再將圖像的左上角轉換為原點
沒有去研究該函數的源碼,不曉得源碼中到底怎么寫的,但是在別人的博客中看到這個函數貌似需要修正
opencv中還有一個函數:Mat getAffineTransform(InputArray src, InputArray dst)¶
它通過三組點對就可以獲得它們之間的仿射變換,如果我們在一組圖像變換中知道變換后的三組點,那么我們就可以利用該函數求得變換矩陣,然后對整張圖片進行仿射變換
還有一種與仿射變換經常混淆的變換為透視變換,透視變換需要四組點對才能確定變換矩陣,由於仿射變換保持“平直性”與“平行性”,因此只需要三組點對,而透視變換沒有這種約束,故需要四組點對









