perspective transform透视矩阵快速求法+矩形矫正
算了半天一直在思考如何快速把矩阵算出来,网上基本都是在说边长为1的正方形的变换方式=。= 不怎么用得上…… 公式推导推半天,计算还麻烦。。。。
++++++++++++++++++++++++++++++
对于透视变换:

其中我们在使用的时候最重要的是算出系数…………………… 这里我们按照i=1计算
找了半天找到了这一篇论文:http://www.ixueshu.com/document/027c165d22e18077318947a18e7f9386.html
里面提到我们可以将公式
改写成
的模式。
那么根据矩形矫正前后的8个顶点可以得到公式:

那么只要计算中间8x8矩阵的逆,乘上变换后的uv矩阵,就可以求出所有待定系数。其中点的检测需要用到hough算法,点和点之间的对应我做了个交互,不然太麻烦了。。。。
矩阵求逆代码:其中N为8
#include <iostream>
using namespace std;
#define N 8 //测试矩阵维数定义 //按第一行展开计算|A|
double getA(double arcs[N][N], int n)
{
if (n == )
{
return arcs[][];
}
double ans = ;
double temp[N][N] = { 0.0 };
int i, j, k;
for (i = ; i<n; i++)
{
for (j = ; j<n - ; j++)
{
for (k = ; k<n - ; k++)
{
temp[j][k] = arcs[j + ][(k >= i) ? k + : k]; }
}
double t = getA(temp, n - );
if (i % == )
{
ans += arcs[][i] * t;
}
else
{
ans -= arcs[][i] * t;
}
}
return ans;
} //计算每一行每一列的每个元素所对应的余子式,组成A*
void getAStart(double arcs[N][N], int n, double ans[N][N])
{
if (n == )
{
ans[][] = ;
return;
}
int i, j, k, t;
double temp[N][N];
for (i = ; i<n; i++)
{
for (j = ; j<n; j++)
{
for (k = ; k<n - ; k++)
{
for (t = ; t<n - ; t++)
{
temp[k][t] = arcs[k >= i ? k + : k][t >= j ? t + : t];
}
} ans[j][i] = getA(temp, n - ); //此处顺便进行了转置
if ((i + j) % == )
{
ans[j][i] = -ans[j][i];
}
}
}
} //得到给定矩阵src的逆矩阵保存到des中。
bool GetMatrixInverse(double src[N][N], int n, double des[N][N])
{
double flag = getA(src, n);
double t[N][N];
if ( == flag)
{
cout << "原矩阵行列式为0,无法求逆。请重新运行" << endl;
return false;//如果算出矩阵的行列式为0,则不往下进行
}
else
{
getAStart(src, n, t);
for (int i = ; i<n; i++)
{
for (int j = ; j<n; j++)
{
des[i][j] = t[i][j] / flag;
} }
} return true;
}
主函数内代码:(仅部分)
vector<pair<int, int>> P ,newPoint; //P 变换后标准A4的点 newPoint 变换前的点 计算时候计算变换后变换到变换前 //省略中间数值插入和输出图片构成 P.push_back(make_pair(, ));
P.push_back(make_pair((int)len1, ));
P.push_back(make_pair((int)len1, (int)len2));
P.push_back(make_pair(, (int)len2)); int uv[] = { newPoint[].first, newPoint[].second,
newPoint[].first, newPoint[].second,
newPoint[].first, newPoint[].second,
newPoint[].first, newPoint[].second }; double src[][] =
{ { P[].first, P[].second, , , , , -newPoint[].first*P[].first, -newPoint[].first*P[].second },
{ , , , P[].first, P[].second, , -newPoint[].second*P[].first, -newPoint[].second*P[].second }, { P[].first, P[].second, , , , , -newPoint[].first*P[].first, -newPoint[].first*P[].second },
{ , , , P[].first, P[].second, , -newPoint[].second*P[].first, -newPoint[].second*P[].second }, { P[].first, P[].second, , , , , -newPoint[].first*P[].first, -newPoint[].first*P[].second },
{ , , , P[].first, P[].second, , -newPoint[].second*P[].first, -newPoint[].second*P[].second }, { P[].first, P[].second, , , , , -newPoint[].first*P[].first, -newPoint[].first*P[].second },
{ , , , P[].first, P[].second, , -newPoint[].second*P[].first, -newPoint[].second*P[].second } }; double matrix_after[N][N]{};
bool flag = GetMatrixInverse(src, N, matrix_after);
if (false == flag) {
cout << "求不出系数" << endl;
return;
} cout << "逆矩阵:" << endl; for (int i = ; i<; i++)
{
for (int j = ; j<; j++)
{
cout << matrix_after[i][j] << " ";
//cout << *(*(matrix_after+i)+j)<<" ";
}
cout << endl;
} double xs[];
for (int i = ; i < ; i++) {
double sum = ;
for (int t = ; t < ; t++) {
sum += matrix_after[i][t] * uv[t];
}
xs[i] = sum;
}
//矩形矫正 没有用双线性插值
cimg_forXY(outputimg, x, y) {
double px = xs[] * x + xs[] * y + xs[];
double py = xs[] * x + xs[] * y + xs[];
double p = xs[] * x + xs[] * y + ; int u = px / p;
int v = py / p; outputimg(x, y, ) = paint(u, v, );
outputimg(x, y, ) = paint(u, v, );
outputimg(x, y, ) = paint(u, v, );
}
以上~
基本实验了一下:

结果:

还可以吧。。。
perspective transform透视矩阵快速求法+矩形矫正的更多相关文章
- 【CImg】简单的畸变矩形矫正
三个角点确定一个平面,畸变的平面可以看成是不同基底下同一图像的表示 ============================我是分割线============================= 1. ...
- CSS3打造3D效果——perspective transform的深度剖析
声明:此篇博文虽是自己手写,但大量资源取自 张鑫旭 的博文.想看更详细 更专业的剖析请看张鑫旭的博文. 昨天对css3的transform做了初步的分析和认识,突然看到perspective属性,调了 ...
- hdu3306 Another kind of Fibonacci【矩阵快速幂】
转载请注明出处:http://www.cnblogs.com/KirisameMarisa/p/4187670.html 题目链接:http://acm.hdu.edu.cn/showproblem. ...
- [技术]浅谈OI中矩阵快速幂的用法
前言 矩阵是高等代数学中的常见工具,也常见于统计分析等应用数学学科中,矩阵的运算是数值分析领域的重要问题. 基本介绍 (该部分为入门向,非入门选手可以跳过) 由 m行n列元素排列成的矩形阵列.矩阵里的 ...
- HDU 6185 Covering 矩阵快速幂
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6185 题意:用 1 * 2 的小长方形完全覆盖 4 * n的矩形有多少方案. 解法:小范围是一个经典题 ...
- hdu4549 M斐波那契数列 矩阵快速幂+快速幂
M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = aF[1] = bF[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a, b, n,你能求出F[n]的 ...
- 五校联考R1 Day1T3 平面图planar(递推 矩阵快速幂)
题目链接 我们可以把棱柱拆成有\(n\)条高的矩形,尝试递推. 在计算的过程中,第\(i\)列(\(i\neq n\))只与\(i-1\)列有关,称\(i-1\)列的上面/下面为左上/左下,第\(i\ ...
- BZOJ2476: 战场的数目(矩阵快速幂)
题意 题目链接 Sol 神仙题Orzzz 考虑两边是否有\(1\) 设\(f[i]\)表示周长为\(2i\)的方案数 第一种情况:左侧或右侧有一个1,那么把这个1删去,对应的方案数为\(f[i - 1 ...
- HDU - 6185 Covering(暴搜+递推+矩阵快速幂)
Covering Bob's school has a big playground, boys and girls always play games here after school. To p ...
随机推荐
- 高并发 Nginx+Lua OpenResty系列(4)——Lua 模块开发
在实际开发中,不可能把所有代码写到一个大而全的lua文件中,需要进行分模块开发:而且模块化是高性能Lua应用的关键.使用require第一次导入模块后,所有Nginx 进程全局共享模块的数据和代码,每 ...
- C# 设计模式,简单工厂
C# 实现计算机功能 (封装,继承,多态) using System; using System.Collections.Generic; using System.Linq; using Syste ...
- spark 源码分析之四 -- TaskScheduler的创建和启动过程
在 spark 源码分析之二 -- SparkContext 的初始化过程 中,第 14 步 和 16 步分别描述了 TaskScheduler的 初始化 和 启动过程. 话分两头,先说 TaskSc ...
- 纯CSS制作加<div>制作动画版哆啦A梦
纯CSS代码加上<div>制作动画版哆啦A梦(机器猫) 哆啦A梦(机器猫)我们大家一定都很熟悉,今天给大家演示怎么用纯CSS代码,来做一个动画版的哆啦A梦. 效果图: ###下面代码同学可 ...
- Shell学习笔记2》转载自runnoob
学习且转载地址:http://www.runoob.com/linux/linux-shell-passing-arguments.html 这个网站整理的的确不错,看着很清晰,而且内容也很全面,个人 ...
- java请求转发,响应重定向的区别
请求转发:request.getRequestDispatcher().forward(); 例:request.getRequestDispatcher("/index.jsp" ...
- 就是要让你彻底学会 @Bean 注解
@Bean 注解全解析 随着SpringBoot的流行,基于注解式开发的热潮逐渐覆盖了基于XML纯配置的开发,而作为Spring中最核心的bean当然也能够使用注解的方式进行表示.所以本篇就来详细的讨 ...
- ZigBee按键中断
何为按键中断? 在了解按键中断之前,我们先来了解一下什么是中断?中断就是程序执行当前代码,当前任务的时候: 突然有自身函数或外部的影响,而使程序执行到别的任务再回来. 举个栗子: 当你在做饭的时候,电 ...
- 接口文档注解:@ApiOperation
@ApiOperation不是spring自带的注解是swagger里的 com.wordnik.swagger.annotations.ApiOperation; @ApiOperation和@Ap ...
- 深入学习Spring框架(四)- 事务管理
1.什么是事务? 事务(Transaction)是一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位,是数据库环境中的逻辑工作单位.事务是为了保证数据库的完整性.例如:A给B转账,需 ...