Javascript圖像處理——仿射變換


前言

上一篇文章,我們講解了圖像金字塔,這篇文章我們來了解仿射變換。

 

仿射?!

任何仿射變換都可以轉換成,乘以一個矩陣(線性變化),再加上一個向量(平移變化)。

實際上仿射是兩幅圖片的變換關系。

例如我們可以通過仿射變換對圖片進行:縮放、旋轉、平移等操作。

 

一個數學問題

在解決仿射問題前,我們來做一個數學題。

如圖,對於點(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)就行了。

 

獲得變換矩陣函數實現

通常我們使用2 \times 3矩陣來表示仿射變換。

A = \begin{bmatrix}
     a_{00} & a_{01} \\
     a_{10} & a_{11}
     \end{bmatrix}_{2 \times 2}
 B = \begin{bmatrix}
     b_{00} \\
     b_{10}
     \end{bmatrix}_{2 \times 1}

 M = \begin{bmatrix}
     A & B
     \end{bmatrix}
 =
\begin{bmatrix}
     a_{00} & a_{01} & b_{00} \\
     a_{10} & a_{11} & b_{10}
\end{bmatrix}_{2 \times 3}

其中A是旋轉縮放變換,B是平移變換。則結果T滿足:

T = A \cdot \begin{bmatrix}x \\ y\end{bmatrix} + B 或者 T = M \cdot  [x, y, 1]^{T}

即:T =  \begin{bmatrix}
    a_{00}x + a_{01}y + b_{00} \\
    a_{10}x + a_{11}y + b_{10}
    \end{bmatrix}

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位形式,操作每個元素就等同於操作每一個像素。

然后遍歷所有元素,對對應的點進行賦值。

 

效果

 

 

 

系列目錄

Javascript圖像處理系列

 

參考資料

Affine Transformations


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM