前言
上一篇文章 ,我們講解了圖像金字塔,這篇文章我們來了解仿射變換。
?
仿射?!
任何仿射變換都可以轉換成,乘以一個矩陣(線性變化),再加上一個向量(平移變化)。
實際上仿射是兩幅圖片的變換關系。
例如我們可以通過仿射變換對圖片進行:縮放、旋轉、平移等操作。
?
一個數學問題
在解決仿射問題前,我們來做一個數學題。
如圖,對于點(x1, y1),相對于原點旋轉一個角度a,那么這個點到哪里了呢?
我們將坐標系變成極坐標系,則點(x1, y1)就變成了(r, β ),而旋轉后變成(r, α ?+ β )。
轉回直角坐標系,則旋轉后的點變成了(cos( α + β ) * r,?sin( α + β ) * r)。
然后利用公式:
cos(α+β)=cosαcosβ-sinαsinβ
sin(α+β)=sinαcosβ+cosαsinβ
以及原來點為(cosβ?* r, sinβ ?* r ),于是很容易得出新的點為(x1 * cos α - y1 * sin α,?x1 * sinaα + y1 * cosα )。
我們可以從中推導出旋轉變換公式:
那么平移就相對簡單很多了,就相當于加上一個向量(c, d)就行了。
?
獲得變換矩陣函數實現
通常我們使用矩陣來表示仿射變換。
其中A是旋轉縮放變換,B是平移變換。則結果T滿足:
?或者?
即:
var getRotationArray2D = function (__angle, __x, __y){ var sin = Math.sin(__angle) || 0 , cos = Math.cos(__angle) || 1 , x = __x || 0 , y = __y || 0 ; return [cos, -sin, - x, sin, cos, - y ]; };
這樣我們就得到了一個仿射變換矩陣。
當然這個實現本身是有一定問題的,因為這個原點被固定在左上角了。
?
仿射變換實現
var warpAffine = function (__src, __rotArray, __dst){ (__src && __rotArray) || error(arguments.callee, IS_UNDEFINED_OR_NULL /* {line} */ ); if (__src.type && __src.type === "CV_RGBA" ){ var height = __src.row, width = __src.col, dst = __dst || new Mat(height, width, CV_RGBA), sData = new Uint32Array(__src.buffer), dData = new Uint32Array(dst.buffer); var i, j, xs, ys, x, y, nowPix; for (j = 0, nowPix = 0; j < height; j++ ){ xs = __rotArray[1] * j + __rotArray[2 ]; ys = __rotArray[4] * j + __rotArray[5 ]; for (i = 0; i < width; i++, nowPix++, xs += __rotArray[0], ys += __rotArray[3 ]){ if (xs > 0 && ys > 0 && xs < width && ys < height){ y = ys | 0 ; x = xs | 0 ; dData[nowPix] = sData[y * width + x]; } else { dData[nowPix] = 4278190080; // Black } } } } else { error(arguments.callee, UNSPPORT_DATA_TYPE /* {line} */ ); } return dst; };
這個函數先把矩陣數據變成32位形式,操作每個元素就等同于操作每一個像素。
然后遍歷所有元素,對對應的點進行賦值。
?
效果
?
?
系列目錄
?
參考資料
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
