航摄相片的外方位元素表示的是摄影摄影瞬间相片上的点对于地面上的点之间的关系的一些参数,在测绘工作中,如果求出了一张航拍相片的外方位元素,那么就可以根据像素点的坐标计算出对应的地面点的坐标,而这些解算过程计算量是非常大的。所以,编写一个能够计算航空摄影测量外方位元素的程序就很有必要了。今天,小博根据所学专业知识完成了该程序的编写,下面是该程序的详细算法,希望对大家有所帮助。
为了方便大家在测绘技术上的交流,小博创建了一个QQ群,欢迎大家加入测绘技术交流QQ群234035436
程序图片

程序计算原理
单张影像的空间后方交会:利用已知地面控制点数据及相应像点坐标根据共线方程反求影像的外方位元素。
数学模型为共线条件方程式:
求解过程:
(1)获取已知数据。从航摄资料中查取平均航高与摄影机主距;获取控制点的地面测量坐标并转换为地面摄影测量坐标。
(2)量测控制点的像点坐标并做系统改正。
(3)确定未知数的初始值。在竖直摄影且地面控制点大致分布均匀的情况下,按如下方法确定初始值,即:

q=w=k=0
式中:m为摄影比例尺分母;n为控制点个数。
(4)用三个角元素的初始值,计算个方向余弦,组成旋转矩阵R。
(5)逐点计算像点坐标的近似值。利用未知数的近似值和控制点的地面
坐标代入共线方程式,逐点计算像点坐标的近似值(x)、(y)。
(6)逐点计算误差方程式的系数和常数项,组成误差方程式。
(7)计算法方程的系数矩阵A和常数项L,组成法方程式。
(8)解法方程,求得外方位元素的改正数dXs,dYs,dZs,dq,dw,dk。
(9)用前次迭代取得的近似值,加本次迭代的改正数,计算外方位元素
的新值。
(10)将求得的外方位元素改正数与规定的限差比较,若小于限差则迭代结束。否则用新的近似值重复(4)~(9),直到满足要求为止。
程序设计及代码
(1)导入数据时读取文件的代码
其中要导入的txt文件数据结构如图所示:

代码:
-
#include "stdafx.h"
-
#include "KongJianHouFangJiaoHui.h"
-
#include "KongJianHouFangJiaoHuiDlg.h"
-
#include "afxdialogex.h"
-
#include "CeHuiLei.h"
-
#include "Matrix.h"
-
#ifdef _DEBUG
-
#define new DEBUG_NEW
-
#endif
-
CMatrix xyXYZ;
-
int ButtonClickeOk =
1;
-
void CKongJianHouFangJiaoHuiDlg::OnBnClickedOk()//导入测量数据按钮代码
-
{
-
-
CFileDialog dlgOpenFile(TRUE, _T("txt"), NULL,
-
OFN_FILEMUSTEXIST, _T("(文本文件)|*.txt|(所有文件)|*.*)||"));
-
-
if (dlgOpenFile.DoModal() == IDCANCEL)
-
return;
//如果选择取消按钮,则退出
-
-
CString strPathName = dlgOpenFile.GetPathName();
//获取选择的文件的完整路径
-
-
CString strFileTitle = dlgOpenFile.GetFileTitle();
//获取文件名
-
CString strExtName = dlgOpenFile.GetFileExt();
//获取文件扩展名
-
CStdioFile sf;
//创建文件对象
-
-
//以读的形式打开文件,如果打开失败
-
if (!sf.Open(strPathName, CFile::modeRead))
-
{
-
MessageBox(_T(
"读取文件出错!"));
-
return;
-
}
-
CString strLine;
//存放每一行文本
-
CStringArray strSplit;
-
CeHuiLei SplitString;
-
int hang =
0;
-
while (sf.ReadString(strLine))
-
{
-
if (hang <=
1)
-
{
-
hang++;
-
}
-
else {
-
int n = SplitString.SplitStringArray(strLine,
',', strSplit);
-
int index1 = m_list1.GetItemCount();
-
CString sno1 = _T(
"");
-
sno1.Format(_T(
"%d"), index1 +
1);
-
int nR = m_list1.InsertItem(index1, sno1);
-
for (
int i =
0; i <
5; i++)
-
{
-
m_list1.SetItemText(index1, i +
1, strSplit[i]);
-
-
}
-
}
-
-
}
-
sf.Close();
-
int Line = m_list1.GetItemCount();
-
CMatrix listXYZ(Line, 5);
-
for (
int i =
0; i < Line; i++)
-
for (
int j =
0; j <
5;j++)
-
listXYZ(i,j)=_wtof(m_list1.GetItemText(i, j +
1));
-
xyXYZ = listXYZ;
-
ButtonClickeOk =
0;
//表示导入数据按钮已被点击并且已导入数据
-
}
(1)主要的计算代码
-
CMatrix CKongJianHouFangJiaoHuiDlg::GetX(CMatrix A, CMatrix L)//计算外方位元素改正数矩阵
-
{
-
CMatrix X,_A,_AA,N_AA;
-
_A = ~A;
//A的转置
-
_AA = _A*A;
-
N_AA = _AA.Inv();
//_AA的逆矩阵
-
X = N_AA*_A*L;
-
return X;
-
}
-
-
CMatrix CKongJianHouFangJiaoHuiDlg::GetA(CMatrix xyXYZ, double f, CMatrix XX)//计算系数矩阵A
-
{
-
int iRow = xyXYZ.Row();
-
CMatrix A(2 * iRow, 6);
-
double XS = XX(
0,
0);
-
double YS = XX(
0,
1);
-
double ZS = XX(
0,
2);
-
-
double w = XX(
0,
4);
-
double k = XX(
0,
5);
-
double q = XX(
0,
3);;
-
double a1 =
cos(q)*
cos(k) -
sin(q)*
sin(w)*
sin(k);
-
double a2 = -
cos(q)*
sin(k) -
sin(q)*
sin(w)*
cos(k);
-
double a3 = -
sin(q)*
cos(w);
-
double b1 =
cos(w)*
sin(k);
-
double b2 =
cos(w)*
cos(k);
-
double b3 = -
sin(w);
-
double c1 =
sin(q)*
cos(k) +
cos(q)*
sin(w)*
sin(k);
-
double c2 = -
sin(q)*
sin(k) +
cos(q)*
sin(w)*
cos(k);
-
double c3 =
cos(q)*
cos(w);
-
f = f /
1000.0;
-
-
for (
int i =
0; i < iRow; i++)
-
{
-
double ZA = xyXYZ(i,
4);
-
double XA = xyXYZ(i,
2);
-
double YA = xyXYZ(i,
3);
-
double x = (xyXYZ(i,
0)-_wtof(strx0))/
1000.0;
-
double y = (xyXYZ(i,
1)-_wtof(stry0))/
1000.0;
-
-
double _Z = a3*(XA - XS) + b3*(YA - YS) + c3*(ZA - ZS);
-
-
A(
2*i,
0) = (a1*f + a3*x) / _Z;
-
A(
2*i,
1) = (b1*f + b3*x) / _Z;
-
A(
2*i,
2) = (c1*f + c3*x) / _Z;
-
-
A(
2*i,
3) = y*
sin(w) - (x*(x*
cos(k) - y*
sin(k)) / f + f*
cos(k))*
cos(w);
-
A(
2*i,
4) = -f*
sin(k) - x*(x*
sin(k) + y*
cos(k)) / f;
-
A(
2*i,
5) = y;
-
A(
2*i+
1,
0) = (a2*f + a3*y) / _Z;
-
A(
2 * i +
1,
1) = (b2*f + b3*y) / _Z;
-
A(
2 * i +
1,
2) = (c2*f + c3*y) / _Z;
-
A(
2 * i +
1,
3) = -x*
sin(w) - (y*(x*
cos(k) - y*
sin(k)) / f - f*
sin(k))*
cos(w);
-
A(
2 * i +
1,
4) = -f*
cos(k) - y/ f*(x*
sin(k) + y*
cos(k));
-
A(
2 * i +
1,
5) = -x;
-
}
-
return A;
-
}
-
-
CMatrix CKongJianHouFangJiaoHuiDlg::GetL(CMatrix xyXYZ, double f, CMatrix XX)//计算L矩阵
-
{
-
int iRow = xyXYZ.Row();
-
CMatrix L(2 * iRow, 1);
-
double XS = XX(
0,
0);
-
double YS = XX(
0,
1);
-
double ZS = XX(
0,
2);
-
-
double w = XX(
0,
4);
-
double k = XX(
0,
5);
-
double q = XX(
0,
3);;
-
double a1 =
cos(q)*
cos(k) -
sin(q)*
sin(w)*
sin(k);
-
double a2 = -
cos(q)*
sin(k) -
sin(q)*
sin(w)*
cos(k);
-
double a3 = -
sin(q)*
cos(w);
-
double b1 =
cos(w)*
sin(k);
-
double b2 =
cos(w)*
cos(k);
-
double b3 = -
sin(w);
-
double c1 =
sin(q)*
cos(k) +
cos(q)*
sin(w)*
sin(k);
-
double c2 = -
sin(q)*
sin(k) +
cos(q)*
sin(w)*
cos(k);
-
double c3 =
cos(q)*
cos(w);
-
f = f /
1000.0;
-
for (
int i =
0; i < iRow; i++)
-
{
-
double ZA = xyXYZ(i,
4);
-
double XA = xyXYZ(i,
2);
-
double YA = xyXYZ(i,
3);
-
double x = (xyXYZ(i,
0) - _wtof(strx0)) /
1000.0;
-
double y = (xyXYZ(i,
1) - _wtof(stry0)) /
1000.0;
-
double x0 = -f*(a1*(XA - XS) + b1*(YA - YS) + c1*(ZA - ZS)) / (a3*(XA - XS) + b3*(YA - YS) + c3*(ZA - ZS));
-
double y0 = -f*(a2*(XA - XS) + b2*(YA - YS) + c2*(ZA - ZS)) / (a3*(XA - XS) + b3*(YA - YS) + c3*(ZA - ZS));
-
-
L(
2*i,
0) =x - x0;
-
L(
2*i+
1,
0) =y - y0;
-
}
-
return L;
-
-
}
-
-
void CKongJianHouFangJiaoHuiDlg::OnBnClickedButton1()//计算按钮
-
{
-
UpdateData(
true);
-
if (ButtonClickeOk ==
1)
-
{
-
MessageBox(_T(
"请先点击“导入已知坐标”按钮导入数据!"), _T(
"提示"));
-
return;
-
}
-
else
if (strf == _T(
"") || strm == _T(
"") || strx0 == _T(
"") || stry0 == _T(
""))
-
{
-
MessageBox(_T(
"请输入数据!"), _T(
"提示"));
-
return;
-
}
-
else
-
{
-
int c = strm.GetLength();
-
double m = _wtof(strm.Right(c -
2));
-
int iRow = xyXYZ.Row();
-
double sumX =
0;
-
double sumY =
0;
-
double sumZ =
0;
-
for (
int i =
0; i < iRow; i++)
-
{
-
sumX += xyXYZ(i,
2);
-
sumY += xyXYZ(i,
3);
-
sumZ += xyXYZ(i,
4);
-
}
-
double XS = sumX / iRow;
-
double YS = sumY / iRow;
-
double ZS = sumZ / iRow + m*_wtof(strf) /
1000;
-
double w =
0;
-
double k =
0;
-
double q =
0;
-
CMatrix XX(1, 6);
-
XX(
0,
0) = XS;
-
XX(
0,
1) = YS;
-
XX(
0,
2) = ZS;
-
XX(
0,
3) = q;
-
XX(
0,
4) = w;
-
XX(
0,
5) = k;
-
CMatrix dX(6, 1);
-
//迭代计算:
-
do {
-
CMatrix A = GetA(xyXYZ, _wtof(strf), XX);
-
CMatrix L = GetL(xyXYZ, _wtof(strf), XX);
-
dX = GetX(A, L);
-
for (
int n =
0; n <
6; n++)
-
XX(
0, n) = XX(
0, n) + dX(n,
0);
-
}
while (dX(
3,
0) >=
2.908882087e-5 || dX(
4,
0) >=
2.908882087e-5 || dX(
5,
0) >=
2.908882087e-5);
//各角元素迭代计算至其改正值小于6秒,6s=2.908882087e-5 弧度。
-
-
CString strarray[
6];
//输出外方位元素计算结果
-
strarray[
0] = _T(
"XS");
-
strarray[
1] = _T(
"YS");
-
strarray[
2] = _T(
"ZS");
-
strarray[
3] = _T(
"q");
-
strarray[
4] = _T(
"w");
-
strarray[
5] = _T(
"k");
-
-
CString strOutPut = _T(
"外方位元素为:\r\n");
-
CString str = _T(
"");
-
for (
int i =
0; i <
6; i++)
-
{
-
str.Format(_T(
"%s=%.4f "), strarray[i], XX(
0, i));
-
strOutPut += str;
-
if (i ==
2)
-
strOutPut += _T(
"\r\n");
-
}
-
MessageBox(strOutPut, _T(
"提示"),
1);
-
}
-
-
}