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);
    }

 

以上~

基本实验了一下:

结果:

 

还可以吧。。。

 

转载于:https://www.cnblogs.com/dycf1111/p/6642894.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值