知源图四点坐标和目标图四点坐标,求透视变换矩阵

  最近在搞图像处理,碰到了透视变换的问题。

  同事给我一些代码,里边有误差,挺严重,让我帮他想想哪里出错了。捣鼓了很久,我猜测肯定是透视变换矩阵求错了,然后我的透视变换之旅就开始了。

  后来问题解决了,发现他的矩阵和我求得矩阵一摸一样,他的代码并没有错误,是他采用的图片在做广角变换的时候有误差,导致程序结果误差。

  首先感谢xiaowei_cqu,是她的一篇博客(http://blog.csdn.net/xiaowei_cqu/article/details/26471527)教会了我变换原理。

  后来去用opencv来验证,发现函数调来调去太麻烦了,代码量也不小。

  可是我只想要变换矩阵,自己写个不就好了!然后根据opencv源码里的原理,配上高斯消元自己写了个qwq。

  talk is cheap,show me the code!!!

//Calculates coefficients of perspective transformation
/* Calculates coefficients of perspective transformation
* which maps (xi,yi) to (ui,vi), (i=1,2,3,4):
*
*      c00*xi + c01*yi + c02
* ui = ---------------------
*      c20*xi + c21*yi + c22
*
*      c10*xi + c11*yi + c12
* vi = ---------------------
*      c20*xi + c21*yi + c22
*
* Coefficients are calculated by solving linear system:
* / x0 y0  1  0  0  0 -x0*u0 -y0*u0 \ /c00\ /u0* | x1 y1  1  0  0  0 -x1*u1 -y1*u1 | |c01| |u1|
* | x2 y2  1  0  0  0 -x2*u2 -y2*u2 | |c02| |u2|
* | x3 y3  1  0  0  0 -x3*u3 -y3*u3 |.|c10|=|u3|,
* |  0  0  0 x0 y0  1 -x0*v0 -y0*v0 | |c11| |v0|
* |  0  0  0 x1 y1  1 -x1*v1 -y1*v1 | |c12| |v1|
* |  0  0  0 x2 y2  1 -x2*v2 -y2*v2 | |c20| |v2|
* \  0  0  0 x3 y3  1 -x3*v3 -y3*v3 / \c21/ \v3/
*
* where:
*   cij - matrix coefficients, c22 = 1
*/

void Gauss(double A[][9], int equ, int var, double* ans) { //epu:A‘s row  var:A‘s col-1
	int row, col;
	for (row = 0, col = 0; col<var&&row<equ; col++, row++) {
		int max_r = row;
		for (int i = row + 1; i<equ; i++) {
			if ((1e-12)<fabs(A[i][col]) - fabs(A[max_r][col])) {
				max_r = i;
			}
		}
		if (max_r != row)
			for (int j = 0; j<var + 1; j++)
				swap(A[row][j], A[max_r][j]);
		for (int i = row + 1; i<equ; i++) {
			if (fabs(A[i][col])<(1e-12))
				continue;
			double tmp = -A[i][col] / A[row][col];
			for (int j = col; j<var + 1; j++) {
				A[i][j] += tmp*A[row][j];
			}
		}

	}
	for (int i = var - 1; i >= 0; i--) { //计算唯一解。
		double tmp = 0;
		for (int j = i + 1; j<var; j++) {
			tmp += A[i][j] * (*(ans + j));
		}
		ans[i] = (A[i][var] - tmp) / A[i][i];
	}
}

void byx_getPerspectiveTransform(PointD * src, PointD * dst, double* ret){
	double x0 = src[0].x, x1 = src[1].x, x2 = src[3].x, x3 = src[2].x;
	double y0 = src[0].y, y1 = src[1].y, y2 = src[3].y, y3 = src[2].y;
	double u0 = dst[0].x, u1 = dst[1].x, u2 = dst[3].x, u3 = dst[2].x;
	double v0 = dst[0].y, v1 = dst[1].y, v2 = dst[3].y, v3 = dst[2].y;
	double A[8][9] = {
			{ x0, y0, 1, 0, 0, 0, -x0*u0, -y0*u0, u0 },
			{ x1, y1, 1, 0, 0, 0, -x1*u1, -y1*u1, u1 },
			{ x2, y2, 1, 0, 0, 0, -x2*u2, -y2*u2, u2 },
			{ x3, y3, 1, 0, 0, 0, -x3*u3, -y3*u3, u3 },
			{ 0, 0, 0, x0, y0, 1, -x0*v0, -y0*v0, v0 },
			{ 0, 0, 0, x1, y1, 1, -x1*v1, -y1*v1, v1 },
			{ 0, 0, 0, x2, y2, 1, -x2*v2, -y2*v2, v2 },
			{ 0, 0, 0, x3, y3, 1, -x3*v3, -y3*v3, v3 },
	};
	double ans[8] = { 0 };
	Gauss(A, 8, 8, ans);
	*(ret + 0) = ans[0];    *(ret + 1) = ans[1];    *(ret + 2) = 0;    *(ret + 3) = ans[2];
	*(ret + 4) = ans[3];    *(ret + 5) = ans[4];    *(ret + 6) = 0;    *(ret + 7) = ans[5];
	*(ret + 8) = 0;         *(ret + 9) = 0;         *(ret + 10) = 1;   *(ret + 11) = 0;
	*(ret + 12) = ans[6];   *(ret + 13) = ans[7];   *(ret + 14) = 0;   *(ret + 15) = 1;
}

PointD byx_Transform(PointD p,double * mat){
    PointD ret;
    double D = p.x*mat[12]+p.y*mat[13]+mat[15];
    ret.x=(p.x*mat[0]+p.y*mat[1]+mat[3])/D;
    ret.y=(p.x*mat[4]+p.y*mat[5]+mat[7])/D;
    return ret;
}

  ps:变换矩阵是3*3的,我同事需要4*4的(第三行和第三列自行忽略)

时间: 2024-10-13 14:52:17

知源图四点坐标和目标图四点坐标,求透视变换矩阵的相关文章

大数据图数据库之MapReduce用于图计算

/* 版权声明:可以任意转载,转载时请务必标明文章原始出处和作者信息 .*/                 CopyMiddle: 张俊林 节选自<大数据日知录:架构与算法>十四章,书籍目录在此 1.使用Mapreduce进行图计算 使用MapReduce框架来针对大规模图数据进行计算的研究工作相对较少,这主要归结于两方面原因:一方面,将传统的图计算映射为MapReduce任务相对其他类型的很多任务而言不太直观:另一方面,从某种角度讲,使用该分布计算框架解决图计算任务也并非最适宜的解决方案.

量化投资_关于Multicharts砖型图(传统砖型图和非传统砖型图)最详细的解释

1. Multicharts的图表中有砖型图的解释,参考官方论坛解释:https://forum.multicharts.cn/forum/cat/1/thread/2821?k=%E7%A0%96 2. 砖型图在交易中会非常棒的提升交易绩效,因为砖型图起到了降噪和二分的作用,降噪不用多解释,因为事先设定砖型图的波动单位,不符合这个单位的小波动就被过滤掉了:所谓二分就是在砖型图的世界中只有两种状态:涨和跌,因此对于绩效的提升非常棒. 3. 但是在Multicharts砖型图不能直接用于交易,这就

7-9-有向图无环拓扑排序-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第7章  图 - 有向无环图拓扑排序 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.SequenceStack.c.ALGraph.c    

Mindjet MindManager 思维导图软件-使用思维导图跟踪调用流程,绘制软件框架

思维导图.据说是每一个产品经理必备的软件.假设你阅读大型源码.使用思维导图跟踪调用流程,绘制软件框架将会很方便. 特点:没什么好说的.用过的都说好. 软件截图: 下载:http://www.mindmanager.cc/ MindManager新手新手教程 MindManager是一款创造.管理和交流思想的思维导图软件,其直观清晰的可视化界面和强大的功能能够高速捕捉.组织和共享思维.想法.资源和项目进程等等.MindManager新手新手教程专为新手用户设计,包括创建思维导图基本入门操作,让用户

HighCharts之2D柱状图 折线图的组合多轴图

HighCharts之2D柱状图.折线图的组合多轴图 1.实例源码 SomeAxis.html: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>HighCharts 2D柱状图.折线图的组合多轴图</title> <script type="text/javascript" src="../scripts/

用C#写小工具:将圆柱面贴图映射到半球贴图

最近在写GBA的程序.GBA运行的是C的裸机代码,而中途使用的很多小工具则用C#写的,例如:图片转换到.h头文件,制作三角函数表,还有像这次介绍的将圆柱面贴图映射到半球贴图的小工具.这样的小功能,用C#写就是一小会的事,效率非常高. 这时候就能体现出来——各语言有各自的用途,C用来做硬件开发,C++做软件开发,C#做快速功能. 这次要解决的问题是: 制作3D时,一个球体的贴图,我们通常映射成一个柱面,就像我们常见的世界地图一样.如图(这张图片是从NASA上下载的卫星图) 但是如果我们想用半球映射

EA逆向生成数据库E-R图(mysql,mariadb数据库-->ER图) v13 及以后的版本处理方式(xjl456852原创)

处理er图需要先将数据库逆向到EA中. 需要电脑上安装mysql 的 odbc可以在官网下载mysql的odbc版本,如果是mariadb的需要下载mariadb的odbc 需要注意,这个EA是32位的软件,一定要下载32位的odbc,否则EA识别不了mysql的驱动. 我安装了mysql odbc驱动32位 下载地址: https://dev.mysql.com/downloads/connector/odbc/ 也可在页面中点击 Looking for the latest GA versi

Echarts生成饼状图、条形图以及线形图 JS封装

1.在我们开发程序中,经常会用到生成一些报表,比方说饼状图,条形图,折线图等.不多说了,直接上封装好的代码,如下Echarts.js所示 以下代码是封装在Echarts.js文件中 /** * Created by Administrator on 2015/8/7. */ var charec; // 路径配置 require.config({ paths: { echarts: 'http://echarts.baidu.com/build/dist' } }); // 按需加载所需图表 r

图结构练习——判断给定图是否存在合法拓扑序列

图结构练习——判断给定图是否存在合法拓扑序列 Time Limit: 1000MS Memory limit: 65536K 题目描述 给定一个有向图,判断该有向图是否存在一个合法的拓扑序列. 输入 输入包含多组,每组格式如下. 第一行包含两个整数n,m,分别代表该有向图的顶点数和边数.(n<=10) 后面m行每行两个整数a b,表示从a到b有一条有向边. 输出 若给定有向图存在合法拓扑序列,则输出YES:否则输出NO. 示例输入 1 0 2 2 1 2 2 1 示例输出 YES NO #inc