C++实现七参数转换法(布尔莎模型)
七参数转换法(布尔莎模型)
七参数法(包括布尔莎模型,一步法模型,海尔曼特等)是解决此问题的比较严密和通用的方法。一般含有7个转换参数:X平移,Y平移,Z平移,X旋转,Y旋转,Z旋转,尺度变化m。通过3个以上的公共点由最小二乘法拟合出相应的转换参数, 然后由求得的转换参数进行坐标转换。
七参数公式如下:
[XYZ]=[ΔXΔYΔZ]+(1+m)[1θz−θy−θz1θxθy−θx1][X0Y0Z0]\left[\begin{array}{l} X \\ Y \\ Z \end{array}\right]=\left[\begin{array}{c} \Delta X \\ \Delta Y \\ \Delta Z \end{array}\right]+(1+m)\left[\begin{array}{ccc} 1 & \theta_{z} & -\theta_{y} \\ -\theta_{z} & 1 & \theta_{x} \\ \theta_{y} & -\theta_{x} & 1 \end{array}\right]\left[\begin{array}{l} X_{0} \\ Y_{0} \\ Z_{0} \end{array}\right] ⎣⎡XYZ⎦⎤=⎣⎡ΔXΔYΔZ⎦⎤+(1+m)⎣⎡1−θzθyθz1−θx−θyθx1⎦⎤⎣⎡X0Y0Z0⎦⎤
式中, ΔX,ΔY,ΔZ\Delta X, \Delta Y, \Delta ZΔX,ΔY,ΔZ为三个平移参数; θx,θy,θz\theta_{x}, \theta_{y}, \theta_{z}θx,θy,θz为3个旋转参数,m为尺度参数。将七参数作为未知数,并且按参数线性化,则可以转换为:
[X−X(X0)Y−Y(Y0)Z−Z(Z0)]=[1000−(1+m)Z0(1+m)Y0X0+θzY0−θyZ0010(1+m)Z00−(1+m)X0−θzX0+Y0+θxZ0001−(1+m)Y0(1+m)X00θyX0−θxY0+Z0][ΔXΔYΔZθxθyθzm]\left[\begin{array}{c} X-X\left(X_{0}\right) \\ Y-Y\left(Y_{0}\right) \\ Z-Z\left(Z_{0}\right) \end{array}\right]=\left[\begin{array}{ccccccc} 1 & 0 & 0 & 0 & -(1+m) Z_{0} & (1+m) Y_{0} & X_{0}+\theta_{z} Y_{0}-\theta_{y} Z_{0} \\ 0 & 1 & 0 & (1+m) Z_{0} & 0 & -(1+m) X_{0} & -\theta_{z} X_{0}+Y_{0}+\theta_{x} Z_{0} \\ 0 & 0 & 1 & -(1+m) Y_{0} & (1+m) X_{0} & 0 & \theta_{y} X_{0}-\theta_{x} Y_{0}+Z_{0} \end{array}\right]\left[\begin{array}{c} \Delta X \\ \Delta Y \\ \Delta Z \\ \theta_{x} \\ \theta_{y} \\ \theta_{z} \\ m \end{array}\right] ⎣⎡X−X(X0)Y−Y(Y0)Z−Z(Z0)⎦⎤=⎣⎡1000100010(1+m)Z0−(1+m)Y0−(1+m)Z00(1+m)X0(1+m)Y0−(1+m)X00X0+θzY0−θyZ0−θzX0+Y0+θxZ0θyX0−θxY0+Z0⎦⎤⎣⎢⎢⎢⎢⎢⎢⎢⎢⎡ΔXΔYΔZθxθyθzm⎦⎥⎥⎥⎥⎥⎥⎥⎥⎤
其中,X(X0),Y(Y0),Z(Z0)X(X_0),Y(Y_0),Z(Z_0)X(X0),Y(Y0),Z(Z0)由七参数公式给出,利用最小二乘法法即可对该线性化的方程进行迭代求解。
七参数转换法实例
下面以C++代码为例,利用已有四个控制点坐标,根据最小二乘来求解七参数模型的参数,并利用一个检查点来验证其转换精度。
1.导入数据
使用4个同名点的原坐标(x, y, z)和目标坐标(x’, y’, z’)来求解七参数
2.正向计算
根据坐标转换公式来列立系数方程定义函数返回系数矩阵。使用4个同名点的坐标转换公式作为误差方程进行最小二乘平差,根据坐标转换公式来列立系数方程 Wx=bW x=bWx=b
3.系数求解
组成法方程 $(W’W) x = (W’b) 并利用最小二乘求解并利用最小二乘求解并利用最小二乘求解x$
4.模型精度评定和结果验证
评定最小二乘模型的精度结果,并使用预留的已知坐标同名点来验证七参数模型的效果
C++代码:
#include <arrayfire.h>
#include <iostream>using namespace af;array point2matrix(double& x, double& y, double& z, array& args)
{/*定义函数返回系数矩阵 B, l定义函数: point2matrix,通过给定的同名点坐标列立误差方程B系数阵的部分x, y, z: 原坐标值args: 七参数误差值[Delta_X, Delta_Y, Delta_Z, theta_x, theta_y, theta_z, m]返回值: W系数阵的部分*/array W = constant(0,3,7,f64);W(seq(3), seq(3))= identity(3, 3);W(0, 4) = -(1 + args(6)) * z;W(0, 5) = (1 + args(6)) * y;W(0, 6) = x + args(5) * y - args(4) * z;W(1, 3) = (1 + args(6)) * z;W(1, 5) = -(1 + args(6)) * x;W(1, 6) = -(args(5) * x) + y + args(3) * z;W(2, 3) = -(1 + args(6)) * y;W(2, 4) = (1 + args(6)) * x;W(2, 6) = args(4) * x - args(3) * y + z;return W;
}array points2W(array &points, array &args)
{/*定义函数: points2W通过同名点序列列立误差方程B系数阵的整体x, y, z: 同名点序列args: 七参数误差值[Delta_X, Delta_Y, Delta_Z, theta_x, theta_y, theta_z, m]返回值: W系数阵*/array big_mat;double x, y, z;for(int i =0;i<points.dims(0);++i){array p = points(i, span);x = p(0).scalar<double>();y = p(1).scalar<double>();z = p(2).scalar<double>();array mat = point2matrix(x, y, z, args);if (big_mat.elements() == 0){big_mat = mat;}else{big_mat = join(0,big_mat, mat);}}return big_mat;
}array ordinationConvert(double& x1, double& y1, double& z1, array& args)
{array p = constant(0,1,3,f64);p(0) = args(0) + (1 + args(6)) * (x1 + args(5) * y1 - args(4) * z1);p(1) = args(1) + (1 + args(6)) * (-(args(5) * x1) + y1 + args(3) * z1);p(2) = args(2) + (1 + args(6)) * (args(4) * x1 - (args(3) * y1) + z1);return p;
}array points2b(array &source_points, array &target_points, array &args)
{/*定义函数: points2b通过同名点坐标转换关系列立误差方程B系数阵的整体x, y, z: 同名点的原坐标和目标坐标对组成的序列args: 七参数误差值[Delta_X, Delta_Y, Delta_Z, theta_x, theta_y, theta_z, m]返回值: b系数阵*/int len = source_points.dims(0);array big_mat = constant(0,len,3,f64);//array p0, p1, p2;double x1, y1, z1;for(int i=0;i<len;++i){array p1 = source_points(i, span);x1 = p1(0).scalar<double>(); y1 = p1(1).scalar<double>(); z1 = p1(2).scalar<double>();array p2 = target_points(i, span);array p0 = ordinationConvert(x1, y1, z1, args);big_mat(i, span) = p2 - p0;}return flat(big_mat.T());
}int main()
{try {/*int device = 2;setDevice(device);*/array Args = constant(0, 7,f64);array parameters = constant(1,7,f64);// 原坐标(x, y, z)double h_source_points[12] = {3381400.980, 395422.030, 32.956,3381404.344, 395844.239, 32.207,3382149.810, 396003.592, 33.290,3382537.793, 395985.359, 33.412 };// 目标坐标(x’, y’, z’) double h_target_points[12] = {3380968.194, 539468.888, 13.875,3380977.154, 539890.934, 13.179,3381724.612, 540040.47, 14.273,3381724.636, 540040.485, 14.282 };array source_points = array(3, 4, h_source_points).T();array target_points = array(3, 4, h_target_points).T();//归一化处理便于模型的快速迭代array ave_src = mean(source_points,0);array ave_tar = mean(target_points,0);source_points -= tile(ave_src,4,1,1,1);target_points -= tile(ave_tar,4,1,1,1);timer::start();// 当七参数的误差值之和大于1e - 10时,迭代运算得到更精确的结果array W, b, qxx;while ((sum)(abs(parameters)).scalar<double>() > 1e-10){W = points2W(source_points, Args);b = points2b(source_points, target_points, Args);qxx = inverse(matmul(W.T(), W));parameters = matmul(matmul(qxx, W.T()), b);Args += parameters;}//af_print(parameters); std::cout << "七参数输出: " << std::endl;af_print(Args);// 检查点坐标double hsource_test_points[3] = { 3381402.058, 395657.940, 32.728 };double htarget_test_points[3] = { 3380972.424, 539704.811, 13.665 };array source_test_points(1, 3, hsource_test_points);array target_test_points(1, 3, htarget_test_points);// 归一化处理source_test_points = source_test_points - ave_src;// 单位权标准差,即所得模型的坐标精度double sigma0 = (sqrt)(sum(b * b) / 2).scalar<double>();// 参数标准差,即所得模型的七参数精度array sigmax = sigma0 * (sqrt)(diag(qxx));double x, y, z;x = source_test_points(0).scalar<double>(); y = source_test_points(1).scalar<double>(); z = source_test_points(2).scalar<double>();array p_test = ordinationConvert(x, y, z, Args) + ave_tar;std::cout << "单位权中误差: " << sigma0 << std::endl;std::cout << "参数中误差:" << std::endl;af_print(sigmax);std::cout << "模型预测结果: " << std::endl;af_print(p_test);std::cout << "真实结果: " << std::endl;af_print(target_test_points);std::cout << "消耗时间: " << timer::stop() <<" s" << std::endl;}catch (af::exception& e){std::cerr << e.what() << std::endl;}
}
结果:
七参数输出:
Args
[7 1 1 1]0.00000.00000.0000-0.00000.0002-0.0717-0.2149单位权中误差: 162.711
参数中误差:
sigmax
[7 1 1 1]81.355781.355781.35570.65050.31110.19120.1497模型预测结果:
p_test
[1 3 1 1]
3380987.5078 539711.3111 13.6542
真实结果:
target_test_points
[1 3 1 1]
3380972.4240 539704.8110 13.6650
消耗时间: 1.39431 s
参考资料:
空间坐标与投影系统系列(四):七参数转换实例 | 武汉大学CVEO小组(张晓东教授团队) (whu-cveo.com)
https://mp.weixin.qq.com/s/1VcDLRTKuAX5W-dme6nX3Q
陈宇,白征东,罗腾.基于改进的布尔沙模型的坐标转换方法[J].大地测量与地球动力学,2010,30(03):71-73+78.
C++实现七参数转换法(布尔莎模型)相关推荐
- 基于布尔莎模型的7参数计算及坐标转换
前言 坐标转换的意义在前一篇<基于二维四参数模型的坐标转换>一文中已经提到,这里就不赘言.这篇文章我将主要介绍基于布尔莎模型的7参数计算流程及转换方法.为了验证数据转换的正确性,先将该工具 ...
- python应用实例:坐标转换——基于布尔莎模型,可实现BJ54坐标系/GSC2000坐标系/WGS84等各种地心直角坐标系的转换
博主准研究僧一枚,假期在老师指导下接触项目. 本博文可作为坐标转换,特别是布尔莎七参数法的学习资料.其python源码注释充分,也可作为python的学习项目. 程序UI界面如下,由于是自用程序,博主 ...
- 简析项目中常用的七参数转换法和四参数转换法以及涉及到的基本测量学知识...
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 在了解这两种转换方法时,我们有必要先了解一些与此相关的基本知 ...
- arcgis根据7参转坐标_在ArcGIS Desktop中进行三参数或七参数精确投影转换
假设原投影坐标系统为Xian80坐标系统,本例选择为系统预设的Projected Coordinate Systems\Gauss Kruger\Xian 1980\Xian 1980 GK Zone ...
- 七参数对不同坐标系统的转换
三参数法和七参数法均应用于空间直角坐标系的转换. 三参数坐标转换公式在假设两坐标系间各坐标轴相互平行,轴系间不存在欧勒角的条件下得出的. [七参数]法: 如上图:两个空间直角坐标系分别为O1-X1Y1 ...
- 【转载】根据已知点通过COORD七参数计算
感谢欧特_Glodon 原文链接:https://blog.csdn.net/m0_37251750/article/details/99941276 参考致谢:微信公众号 GIS前言 问题:同一个点 ...
- 利用坐标数据求解七参数
根据四组数据求解它们的七参数,并且求解出每个参数的中误差,最后用其中的任意一个数据求得它对应的坐标数据,来验证我们的求解结果.数据以文件的形式将数据输入.代码中有详细的注释. 具体代码如下: 数据如下 ...
- 二参数威布尔分布matlab,基于MATLAB的威布尔分布参数估计的图形界面设计
基于 MATLAB 的威布尔分布参数估计的图形界面设计 唐军军, 姜年朝, 宋军, 徐艳楠, 刘达 (总参第六十研究所, 江苏 南京 210016) 摘 要: 基于 MATLAB 平台, 设计了一款集 ...
- 坐标转换--基准面转换(布尔莎七参数)
坐标转换–基准面转换(布尔莎七参数) 在坐标转换中,除了正投影和反投影的转换,还有不同基准面之间的转换.基准面的转换有很多种转换模型,常见的有三参数和七参数转换.三参数的转换主要是通过对x,y,z三个 ...
最新文章
- 线性回归、逻辑回归及SVM
- spring-boot 参考链接
- WINCE6.0隐藏文件夹和应用程序访问物理寄存器
- JavaScript this指向相关内容
- java range(10)_Java Year range()用法及代码示例
- 一个edit的学习笔记
- (2)FPGA开发流程介绍(第1天)
- String reverse方法
- CentOS minimal 版安装图形界面的步骤分享,中文语言包
- 计算机网络—数据链路层的差错控制
- linux 升级g++ [错误:unrecognized command line option “-std=c++11”]
- ssl证书 所属项目怎么上传_Typora + 七牛云图床快速配置,告别手动上传图片!...
- STL容器-queue队列
- 能力提升综合题单Part 8.1 图的存储与遍历
- 使用ESP8266模块在WIFI下通过网页远程控制LED开关
- java 某字段重复的数据库,excel表格两个字段去重复的数据库【用JAVA程序向SQL数据库导入Excel表,判断出SQL表中已存在的重复数据,并跳过重复的继续导入其他记录.】...
- 计算机前端开发论文参考文献,web前端论文参考文献.doc
- 腾讯视频没有了html分享代码,腾讯视频代码在哪里 腾讯视频嵌入网页的方法-电脑教程...
- 关于蚂蚁花呗无法使用的问题
- 方法论--面对问题,提出问题,解决问题
热门文章
- 实际记录vue3中使用rrweb以及rrweb-player组件实现网页录屏和回放功能,还有遇到的问题和解决思考
- Linux下优雅的让程序后台运行
- oracle中栓锁,oracle 闩锁介绍
- 医院影像服务器系统,锐潮医学影像管理系统(PACS)
- vue 调色器和js-web-screen-shot截图插件
- Qt小项目(二):调色器
- 学日语就是一种煎熬!
- 困在“墙”里的中年程序员
- 新年最美表白烟花-祝大家新年快乐,表白成功
- 【附代码实现】光流法大全(DeepFlow、DenseFlow、DisFlow、FbFlow、PCAFlow、SimpleFlow、TV_L1)