perspective transform透視矩陣快速求法+矩形矯正


算了半天一直在思考如何快速把矩陣算出來,網上基本都是在說邊長為1的正方形的變換方式=。=   不怎么用得上…… 公式推導推半天,計算還麻煩。。。。

 ++++++++++++++++++++++++++++++

對於透視變換:

其中我們在使用的時候最重要的是算出系數……………………  這里我們按照i=1計算

找了半天找到了這一篇論文:http://www.ixueshu.com/document/027c165d22e18077318947a18e7f9386.html  

 

 

里面提到我們可以將公式

 

改寫成的模式。

那么根據矩形矯正前后的8個頂點可以得到公式:

那么只要計算中間8x8矩陣的逆,乘上變換后的uv矩陣,就可以求出所有待定系數。其中點的檢測需要用到hough算法,點和點之間的對應我做了個交互,不然太麻煩了。。。。

 

矩陣求逆代碼:其中N為8

 1 #include <iostream>
 2 using namespace std;
 3 #define N 8    //測試矩陣維數定義
 4 
 5 //按第一行展開計算|A|
 6 double getA(double arcs[N][N], int n)
 7 {
 8     if (n == 1)
 9     {
10         return arcs[0][0];
11     }
12     double ans = 0;
13     double temp[N][N] = { 0.0 };
14     int i, j, k;
15     for (i = 0; i<n; i++)
16     {
17         for (j = 0; j<n - 1; j++)
18         {
19             for (k = 0; k<n - 1; k++)
20             {
21                 temp[j][k] = arcs[j + 1][(k >= i) ? k + 1 : k];
22 
23             }
24         }
25         double t = getA(temp, n - 1);
26         if (i % 2 == 0)
27         {
28             ans += arcs[0][i] * t;
29         }
30         else
31         {
32             ans -= arcs[0][i] * t;
33         }
34     }
35     return ans;
36 }
37 
38 //計算每一行每一列的每個元素所對應的余子式,組成A*
39 void  getAStart(double arcs[N][N], int n, double ans[N][N])
40 {
41     if (n == 1)
42     {
43         ans[0][0] = 1;
44         return;
45     }
46     int i, j, k, t;
47     double temp[N][N];
48     for (i = 0; i<n; i++)
49     {
50         for (j = 0; j<n; j++)
51         {
52             for (k = 0; k<n - 1; k++)
53             {
54                 for (t = 0; t<n - 1; t++)
55                 {
56                     temp[k][t] = arcs[k >= i ? k + 1 : k][t >= j ? t + 1 : t];
57                 }
58             }
59 
60 
61             ans[j][i] = getA(temp, n - 1);  //此處順便進行了轉置
62             if ((i + j) % 2 == 1)
63             {
64                 ans[j][i] = -ans[j][i];
65             }
66         }
67     }
68 }
69 
70 //得到給定矩陣src的逆矩陣保存到des中。
71 bool GetMatrixInverse(double src[N][N], int n, double des[N][N])
72 {
73     double flag = getA(src, n);
74     double t[N][N];
75     if (0 == flag)
76     {
77         cout << "原矩陣行列式為0,無法求逆。請重新運行" << endl;
78         return false;//如果算出矩陣的行列式為0,則不往下進行
79     }
80     else
81     {
82         getAStart(src, n, t);
83         for (int i = 0; i<n; i++)
84         {
85             for (int j = 0; j<n; j++)
86             {
87                 des[i][j] = t[i][j] / flag;
88             }
89 
90         }
91     }
92 
93     return true;
94 }

 

 主函數內代碼:(僅部分)

vector<pair<int, int>> P ,newPoint; //P 變換后標准A4的點  newPoint 變換前的點   計算時候計算變換后變換到變換前

//省略中間數值插入和輸出圖片構成

P.push_back(make_pair(0, 0));
    P.push_back(make_pair((int)len1, 0));
    P.push_back(make_pair((int)len1, (int)len2));
    P.push_back(make_pair(0, (int)len2));

    int uv[8] = { newPoint[0].first, newPoint[0].second,
        newPoint[1].first, newPoint[1].second,
        newPoint[2].first, newPoint[2].second,
        newPoint[3].first, newPoint[3].second };
    
    double src[8][8] =
    { { P[0].first, P[0].second, 1, 0, 0, 0, -newPoint[0].first*P[0].first, -newPoint[0].first*P[0].second },
    { 0, 0, 0, P[0].first, P[0].second, 1, -newPoint[0].second*P[0].first, -newPoint[0].second*P[0].second },

    { P[1].first, P[1].second, 1, 0, 0, 0, -newPoint[1].first*P[1].first, -newPoint[1].first*P[1].second },
    { 0, 0, 0, P[1].first, P[1].second, 1, -newPoint[1].second*P[1].first, -newPoint[1].second*P[1].second },

    { P[2].first, P[2].second, 1, 0, 0, 0, -newPoint[2].first*P[2].first, -newPoint[2].first*P[2].second },
    { 0, 0, 0, P[2].first, P[2].second, 1, -newPoint[2].second*P[2].first, -newPoint[2].second*P[2].second },

    { P[3].first, P[3].second, 1, 0, 0, 0, -newPoint[3].first*P[3].first, -newPoint[3].first*P[3].second },
    { 0, 0, 0, P[3].first, P[3].second, 1, -newPoint[3].second*P[3].first, -newPoint[3].second*P[3].second } };



    double matrix_after[N][N]{};
    bool flag = GetMatrixInverse(src, N, matrix_after);
    if (false == flag) {
        cout << "求不出系數" << endl;
        return;
    }


    cout << "逆矩陣:" << endl;

    for (int i = 0; i<8; i++)
    {
        for (int j = 0; j<8; j++)
        {
            cout << matrix_after[i][j] << " ";
            //cout << *(*(matrix_after+i)+j)<<" ";
        }
        cout << endl;
    }

    double xs[8];
    for (int i = 0; i < 8; i++) {
        double sum = 0;
        for (int t = 0; t < 8; t++) {
            sum += matrix_after[i][t] * uv[t];
        }
        xs[i] = sum;
    }
        //矩形矯正  沒有用雙線性插值
    cimg_forXY(outputimg, x, y) {
        double px = xs[0] * x + xs[1] * y + xs[2];
        double py = xs[3] * x + xs[4] * y + xs[5];
        double p = xs[6] * x + xs[7] * y + 1;

        int u = px / p;
        int v = py / p;

        outputimg(x, y, 0) = paint(u, v, 0);
        outputimg(x, y, 1) = paint(u, v, 1);
        outputimg(x, y, 2) = paint(u, v, 2);
    }

 

以上~

基本實驗了一下:

結果:

 

還可以吧。。。

 


免責聲明!

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



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