相对定向-绝对定向(C++实现)--摄影测量学

一. 目的

  1. 理解并掌握空间相对定向-原理。
  2. 体会相对定向-绝对定向与前后方交会的异同,理解各参数含义。
  3. 熟悉计算流程,并通过编程运用到实践上。
  4. 提高编程计算能力,并将算式转换为程序,体会编程计算的特点。

二. 实验要求

  1. 提交实习报告:程序框图、程序源代码、计算结果、体会。
  2. 计算结果:相对定向五参数及精度评定、计算模型点坐标、绝对定向七参数及精度评定。

三. 实验思路

先求解相对定向,解得五参数,然后计算模型点,最后求解七参数,求解地面摄影测量坐标。

四.实验数据

  1. 点位信息。
    相对定向-绝对定向(C++实现)--摄影测量学_第1张图片
    点位信息

    f=150.000mm,x0=0,y0=0

五. 实验结果

  1. 待求点地面摄影测量坐标


    相对定向-绝对定向(C++实现)--摄影测量学_第2张图片
    结果
  2. 相对定向五参数

五 参 数 :f w k u v
0.0155932 0.0155955 0.0157996 -0.0159242 0.0312629
相 对 定 向 精 度 : 2.55745e-07
相 对 定 向 迭 代 次 数 : 4

  1. 模型点坐标

X Y Z
153.706 767.599 4.98951
826.447 757.146 45.0979
130.021 -772.319 -14.688
804.556 -782.906 -22.5479
489.955 762.558 24.9652
142.214 -2.24693 -14.3932
478.625 -7.48203 5.57837
815.018 -12.7547 25.6743
467.161 -777.641 -13.908

  1. 绝对定向七参数

    绝 对 定 向 七 参 数 :x y z l f w k
    5000.07 5043.55 499.508 1.03883 0.000437969 0.0287284 0.095136
    绝 对 定 向 精 度 : 0.0999457
    相 对 定 向 迭 代 次 数 : 5

  1. 地面摄影测量坐标

X Y Z
5083.26 5852.04 527.963
5779.98 5906.4 571.513
5210.76 4258.46 461.775
5909.37 4314.29 455.517
5431.48 5879.4 549.662
5147.37 5055.69 484.963
5495.77 5082.86 506.652
5844.15 5110 528.47
5559.93 4286.2 463.536

六. 程序框图

  1. 相对定向


    相对定向-绝对定向(C++实现)--摄影测量学_第3张图片
    相对定向结果
  2. 模型点计算


    相对定向-绝对定向(C++实现)--摄影测量学_第4张图片
    模型点计算
  3. 绝对定向


    相对定向-绝对定向(C++实现)--摄影测量学_第5张图片
    绝对定向

七. 实验原理公式

  1. 共线方程


    共线方程
  2. 旋转矩阵


    旋转矩阵
  3. 最小二乘准则


    最小二乘准则
  4. 解析法相对定向原理:

根据同名光线对对相交这一立体像对内在的几何关系,通过量测的像点坐标,用解析计算的方法解求相对定向元素,建立与地面相似的立体模型,确定模型点的三维坐标。
相对定向的共面条件:B·(S1a1·S2a2)=0,即F=
连续像对的相对定向:连续像对法相对定向是以左像片为基准,求出右像片相对于左像片的五个定向元素 .为了统一单位,把bY,bZ两个基线元素改为角度形式表示,如下,μ和ν为极限的偏角和倾角。

  1. 前方交会


    相对定向-绝对定向(C++实现)--摄影测量学_第6张图片
    前方交会
  2. 模型点计算


  3. 绝对定向。

相对定向后建立的立体模型是相对于摄影测量坐标系统的,它在地面坐标系统中的方位是未知的,其比例尺也是任意的。如果想要知道模型中某点相应的地面点的地面坐标,就必须对所建立的模型进行绝对定向,即要确定模型在地面坐标系中的正确方位,及比例尺因子。很容易将模型坐标转化为地面坐标,这样就能确定出加密点的地面坐标。这叫立体模型的绝对定向。
绝对定向的定义:解算立体模型绝对方位元素的工作。立体模型绝对方位元素有7个,它们是: 。
绝对定向的目的:恢复立体模型在地面坐标系中的大小和方位的工作。

八.实验代码(附录)

九.实验结果(截图)

相对定向-绝对定向(C++实现)--摄影测量学_第7张图片

十. 实验心得体会

一句话总结这次实验:收获甚丰,内心很苦。为何这样说?

首先说一下收获甚丰。这次实验真正的让我体会到相对定向-绝对定向与前后方交会之间的区别、联系。他们是空间双象解析的两种重要方法,但是求解思路却不相同。前后交会是先求解单张相片的地面摄影测量坐标,然后再前方交会实现还原相片位置,求解坐标;然而相对-绝对是先求解左右相片的相对位置,然后再逐步求解其在空间中的位置。两者相通的可能就是最基本的原理—共线方程,两者都采用前方交会计算坐标。因此,从根本上讲,前后方交会是同一问题的不同求解顺序。

其次想谈一谈内心的痛苦。说白了就是编程中所遇到的问题。

  1. 绝对定向中bx。
    在求解过程中,bx = x1 – x2; 我开始写的是bx = x2 – x1;就是这样简单的问题,因为没有想清楚,所以就出错了。
    相对定向中,bx其实是一个无关紧要的量,因此,我算出来相对定向的值是正确的;然而到了绝对定向,出现问题了,七参数中z异常打!然而找不到问题所在,最后在调试时,发现不对,才改正过来,于是乎,绝对定向才收敛,这个过程持续了至少5个小时。
  2. 数据录入错误。
    这可能是最低级的错误,但是这次我又犯了,把一个数据的正负号搞错了,于是乎,根本不会闭合,看着迭代次数1,100,100…绝望!
  3. 矩阵与数组之间的频繁转换。
    由于原始数据是数组,操作起来也很便捷,但有时候为了求逆,不得不将数据转为矩阵;有时候矩阵与数组结构不相同,出现了某一个位置未赋值的情况,从而出现各种奇怪的值!
  4. 参数过多,传值频繁。
    此程序内的定向类可以认为根本不符合面向对象的编程思想,因为这个类的存在几乎就是为了在函数之间传递变量。因此,在数值传递过程中就会出现变量混乱,变量名污染的情况。
    总之,这三天的编程还是蛮刺激的,不仅要一遍遍看书,还有详细了解编程知识,同时要不断地Debug,Debug,Debug……

附录

  1. 入口文件ResAblOrientation
#include "stdafx.h"
#include 
#include "Orientation.h"
using namespace std;
int main()
{
    //左片数据
    double l[9][2] = {
        { 0.016012 ,0.079963 },
        { 0.08856 ,0.081134 },
        { 0.013362 ,-0.07937 },
        { 0.08224 ,-0.080027 },
        { 0.051758,0.080555 },
        { 0.014618,-0.000231 },
        { 0.04988,-0.000782 },
        { 0.08614,-0.001346 },
        { 0.048035,-0.079962 }
    };
    //右片数据
    double r[9][2] = {
        { -0.07393,0.078706 },
        { -0.005252,0.078184 },
        { -0.079122,-0.078879 },
        { -0.009887,-0.080089 },
        { -0.039953,0.078463 },
        { -0.076006,0.000036 },
        { -0.042201,-0.001022 },
        { -0.007706,-0.002112 },
        { -0.044438,-0.079736 }
    };
    //控制点地面摄影测量坐标
    double g[4][3] = {
        { 5083.205,5852.099,527.925 },
        { 5780.02,5906.365,571.549 },
        { 5210.879,4258.446,461.81 },
        { 5909.264,4314.283,455.484 }
    };
    double f = 0.15; //焦距

    //实例化定向对象
    COrientation o(l,r,g,f);

    cout << endl << endl;
    cout << "--------定向计算结果--------" << endl;
    cout << endl << endl;
    //相对定向
    o.RelaOrientation();

    cout << "--------------------------------" << endl;

    //计算模型点
    o.ModelPoints();

    cout << "--------------------------------" << endl;

    //绝对定向
    o.AbsOrientation();

    cout << "--------------------------------" << endl;

    //计算坐标值
    o.GetPoints();

    cin.get();
    return 0;
}
  1. 定向类COrientation
#pragma once
#include "Matrix.h"
#include 
/*
定向类
*/
class COrientation
{
private:
    //相对定向五参数
    double f;
    double w;
    double k;
    double u;
    double v;
    double countx; //相对定向循环次数

    double df; //焦距
    double bx;
    double by;
    double bz;

    //七参数
    double x;
    double y;
    double z;
    double jf;
    double jw;
    double jk;
    double jl;
    double countj; //绝对定向循环次数

    double N1;
    double N2;

    double l[9][2]; //左片数据
    double r[9][2]; //右片数据
    double g[4][3]; //控制点地面摄影测量数据
    double p[9][3]; //模型点数据

public:
    //初始化
    COrientation(double l[9][2], double r[9][2], double g[4][3],double f);
    void RelaOrientation(); //相对定向
    void ModelPoints(); //计算模型点
    void AbsOrientation(); //绝对定向
    void GetPoints(); //得出地面摄影测量坐标
    CMatrix GetR(double f, double w, double k); //计算旋转矩阵
    ~COrientation();
};
#include "stdafx.h"
#include "Orientation.h"
#include "math.h"
#include 
using namespace std;
COrientation::COrientation(double lpoints[9][2], double rpoints[9][2], double g[4][3], double df)
{
    //焦距
    this->df = df;
    //初始值
    bx = lpoints[0][0] - rpoints[0][0]; //bx初始值
    //初始值
    f = w = k = u = v = 0;
    countx = countj = 0;
    //赋值
    for (int i = 0; i < 9; i++)
    {
        for (int j = 0; j < 2; j++)
        {
            l[i][j] = lpoints[i][j];
            r[i][j] = rpoints[i][j];
        }
    }
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            this->g[i][j] = g[i][j];
        }
    }
}

void COrientation::RelaOrientation()
{
    //误差方程参数
    CMatrix A(6, 5), L(6, 1), X(5, 1), V(6, 1);

    //右片相对相空间坐标,相对摄影测量坐标
    CMatrix mr(3, 1), mrimg(3, 1);

    //迭代运算
    while (1)
    {
        //计算旋转矩阵
        CMatrix R2 = GetR(f, w, k);

        //by,bz计算
        by = bx*u;
        bz = bx*v;

        //计算每个点参数,组成法方程矩阵
        for (int i = 0; i < 6; i++)
        {
            //左片相对摄影测量坐标
            double x1 = l[i][0];
            double y1 = l[i][1];
            double z1 = -df;

            //右片相对摄影测量坐标
            mr(0, 0) = r[i][0];
            mr(1, 0) = r[i][1];
            mr(2, 0) = -df;
            //计算相对摄影测量坐标
            mrimg = R2*mr;

            //计算N1,N2
            N1 = (bx*mrimg(2, 0)- bz*mrimg(0, 0)) / (x1*mrimg(2, 0) - mrimg(0, 0)*z1);
            N2 = (bx*z1 - bz*x1) / (x1*mrimg(2, 0) - mrimg(0, 0)*z1);
            //计算每个点的Q值
            double Q = N1*y1 - N2*mrimg(1, 0) - by;
            //计算每个点误差系数
            double v[5] = {0};
            v[0] = -mrimg(0, 0)*mrimg(1, 0)*N2 / mrimg(2, 0);
            v[1] = -(mrimg(2, 0) + mrimg(1, 0)*mrimg(1, 0) / mrimg(2, 0))*N2;
            v[2] = mrimg(0, 0)*N2;
            v[3] = bx;
            v[4] = -mrimg(1, 0)*bx / mrimg(2, 0);

            //加入总误差系数阵
            for (int ii = 0; ii < 5; ii++)
                A(i, ii) = v[ii];
            L(i, 0) = Q;
        }
        //求解X
        X = (~A*A).Inv()*(~A)*L;

        //累加五参数
        f += X(0, 0);
        w += X(1, 0);
        k += X(2, 0);
        u += X(3, 0);
        v += X(4, 0);

        //循环次数+
        countx++;

        //判断是否收敛
        if (abs(X(0, 0)) < 0.00003 && abs(X(1, 0)) < 0.00003 && abs(X(2, 0)) < 0.00003 && abs(X(3, 0)) < 0.00003 && abs(X(4, 0)) < 0.00003)
        {
            //输出五参数
            cout << "五参数:f w k u v" << endl;
            cout << f << " " << w << " " << k << " " << u << "  " << v << endl;
            //评定精度
            V = A*X - L;
            double c1 = sqrt((~V*V)(0, 0) / 6);
            cout << "相对定向精度:" << c1 << endl;
            cout << "相对定向迭代次数:" << countx << endl;
            break;
        }
    }


}

void COrientation::ModelPoints()
{
    //比例尺
    double m1 = sqrt((l[0][0] - l[1][0])*(l[0][0] - l[1][0]) + (l[0][1] - l[1][1])*(l[0][1] - l[1][1]));
    double m2 = sqrt((g[0][0] - g[1][0])*(g[0][0] - g[1][0]) + (g[0][1] - g[1][1])*(g[0][1] - g[1][1]));
    double m = m2 / m1;
    //m = 10000;

    //计算每个点模型坐标
    //右片相对相空间坐标,相对摄影测量坐标
    CMatrix mr(3, 1), mrimg(3, 1);
    //计算旋转矩阵
    CMatrix R2 = GetR(f, w, k);
    for (int i = 0; i < 9; i++)
    {

        //左片相对摄影测量坐标
        double x1 = l[i][0];
        double y1 = l[i][1];
        double z1 = -df;

        //右片相对摄影测量坐标
        mr(0, 0) = r[i][0];
        mr(1, 0) = r[i][1];
        mr(2, 0) = -df;
        //计算相对摄影测量坐标
        mrimg = R2*mr;

        //计算N1,N2
        N1 = (bx*mrimg(2, 0) - bz*mrimg(0, 0)) / (x1*mrimg(2, 0) - mrimg(0, 0)*z1);
        N2 = (bx*z1 - bz*x1) / (x1*mrimg(2, 0) - mrimg(0, 0)*z1);

        double xp = m*N1*x1;
        double yp = 0.5*m*(N1*y1 + N2*mrimg(1, 0) + by);
        double zp = m*df + m* N1*(-df);
        p[i][0] = xp;
        p[i][1] = yp;
        p[i][2] = zp;
    }
    cout << "模型点坐标:" << endl;
    for (int i = 0; i < 9; i++)
    {
        for (int j = 0; j < 3; j++)
            cout << p[i][j] << " ";
        cout << endl;
    }
}

void COrientation::AbsOrientation()
{
    //初始化七参数
    x = y = z = jf = jw = jk = 0;
    jl = 1;
    //法方程系数
    CMatrix A(12, 7), L(12, 1), V(12, 1), X(7,1);
    //迭代计算
    while (true)
    {
        //计算每一个点的系数
        for (int i = 0; i < 4; i++)
        {
            //旋转矩阵
            CMatrix R = GetR(jf, jw, jk);
            //每个点误差方程系数
            CMatrix mtp(3, 1), mp(3, 1), p0(3, 1);
            //赋值给矩阵,便于计算
            for (int j = 0; j < 3; j++)
            {
                mtp(j, 0) = g[i][j];
                mp(j, 0) = p[i][j];
            }
            p0(0, 0) = x;
            p0(1, 0) = y;
            p0(2, 0) = z;
            //计算每个点的L
            CMatrix jL = mtp - jl*R*mp - p0;
            //每个点3X3的系数阵A
            CMatrix jA(3, 7);
            jA(0, 0) = 1;
            jA(1, 1) = 1;
            jA(2, 2) = 1;
            jA(0, 3) = p[i][0];
            jA(0, 4) = -p[i][2];
            jA(0, 6) = -p[i][1];
            jA(1, 3) = p[i][1];
            jA(1, 5) = -p[i][2];
            jA(1, 6) = p[i][0];
            jA(2, 3) = p[i][2];
            jA(2, 4) = p[i][0];
            jA(2, 5) = p[i][1];

            //添加到大系数阵A,L
            for (int j = 0; j < 7; j++)
            {
                A(3 * i, j) = jA(0, j);
                A(3 * i + 1, j) = jA(1, j);
                A(3 * i + 2, j) = jA(2, j);
            }
            L(3 * i, 0) = jL(0, 0);
            L(3 * i + 1, 0) = jL(1, 0);
            L(3 * i + 2, 0) = jL(2, 0);
        }

        //求解法方程
        X = (~A*A).Inv()*~A*L;

        //累加七参数
        x += X(0, 0);
        y += X(1, 0);
        z += X(2, 0);
        jl += X(3, 0);
        jf += X(4, 0);
        jw += X(5, 0);
        jk += X(6, 0);

        //循环次数累加
        countj++;
        //判断是否收敛
        if (abs(X(0, 0)) < 0.001 && abs(X(1, 0)) < 0.001 && abs(X(2, 0)) < 0.001 && abs(X(3, 0)) < 0.001 && abs(X(4, 0)) < 0.001&& abs(X(5, 0)) < 0.001 && abs(X(6, 0)) < 0.001)
        {
            cout << "绝对定向七参数:x y z l f w k" << endl;;
            cout << x << " " << y << " " << z << " " << jl << " " << jf << " " << jw << " " << jk << endl;;
            //精度评定
            V = A*X - L;
            double c2 = sqrt((~V*V)(0, 0) / 4);
            cout << "绝对定向精度:" << c2 << endl;
            cout << "相对定向迭代次数:" << countj << endl;
            break;
        }
    }

}

void COrientation::GetPoints()
{
    CMatrix XTP(9,3); //地面摄影测量坐标
    //计算坐标
    for (int i = 0; i < 9; i++)
    {
        //依次为相对摄影测量坐标、七参数、地面摄影测量坐标
        CMatrix XP(3, 1), DX(3, 1), mXTP(3, 1);
        //为矩阵赋值
        XP(0, 0) = p[i][0]; 
        XP(1, 0) = p[i][1]; 
        XP(2, 0) = p[i][2];

        DX(0, 0) = x; 
        DX(1, 0) = y, 
        DX(2, 0) = z;
        //计算摄影测量坐标
        mXTP = jl*GetR(jf, jw, jk)*XP + DX;
        for (int j = 0; j < 3; j++)
        {
            XTP(i, j) = mXTP(j, 0);
        }
    }
    cout << "地面摄影测量坐标为:" << endl;
    cout << XTP;
}

CMatrix COrientation::GetR(double f, double w, double k)
{
    CMatrix R2(3, 3);
    R2(0, 0) = cos(f)*cos(k) - sin(f)*sin(w)*sin(k);
    R2(0, 1) = -cos(f)*sin(k) - sin(f)*sin(w)*cos(k);
    R2(0, 2) = -sin(f)*cos(w);
    R2(1, 0) = cos(w)*sin(k);
    R2(1, 1) = cos(w)*cos(k);
    R2(1, 2) = -sin(w);
    R2(2, 0) = sin(f)*cos(k) + cos(f)*sin(w)*sin(k);
    R2(2, 1) = -sin(f)*sin(k) + cos(f)*sin(w)*cos(k);
    R2(2, 2) = cos(f)*cos(w);

    return R2;
}

COrientation::~COrientation()
{
}
  1. 矩阵类CMatrix
#pragma once
#include 
using namespace std;
class CMatrix
{
public:
    CMatrix(int row = 3, int col = 3);
    // copy constructor

    CMatrix(const CMatrix& m);


    ~CMatrix(void);
private:
    double **dMatData;//保存矩阵元素数据的二维数组
    int iRow;//矩阵的行
    int iCol;//矩阵的列

public:
    int Row() const { return iRow; }//返回行
    int Col() const { return iCol; }//返回列
    void SetSize(int row, int col);//调整数组的大小,原有数据不变(未测试)
    void SetRow(int row, double arrrow[]); //设置一行元素

    double& operator () (int row, int col);//获取矩阵元素
    double  operator () (int row, int col) const;//重载获取矩阵元素函数,只有const对象能访问

    CMatrix& operator = (const CMatrix& m);

    //注意:友元函数并不是类自己的成员函数
    friend CMatrix operator + (const CMatrix& m1, const CMatrix& m2);
    friend CMatrix operator - (const CMatrix& m1, const CMatrix& m2);
    friend CMatrix operator * (const CMatrix& m1, const CMatrix& m2);
    friend CMatrix operator * (const double& num, const CMatrix& m1);
    friend CMatrix operator * (const CMatrix& m1, const double& num);
    friend ostream & operator<<(ostream &out, CMatrix &m); //重载<<

    friend CMatrix operator ~ (const CMatrix& m);//矩阵转置
    CMatrix Inv();//矩阵求逆
    void Unit();//生成单位矩阵
};


#include "stdafx.h"
#include "Matrix.h"
#include "math.h"

CMatrix::CMatrix(int row, int col)
{
    iRow = row;
    iCol = col;
    dMatData = new double*[row];

    for (int i = 0; i < row; i++)
    {
        dMatData[i] = new double[col];
        for (int j = 0; j= iRow || col >= iCol)
    {
        throw("CMatrix::operator(): Index out of range!");
    }

    return dMatData[row][col];
}

////返回数组元素(重载)
double CMatrix::operator () (int row, int col) const
{
    if (row >= iRow || col >= iCol)
    {
        throw("CMatrix::operator(): Index out of range!");
    }

    return dMatData[row][col];
}


//重载预算符+
CMatrix operator + (const CMatrix& m1, const CMatrix& m2)
{

    if ((m1.Col() != m2.Col()) || (m1.Row() != m2.Row()))
    {
        throw("CMatrix::operator+: The two matrix have different size!");
    }

    CMatrix matTmp(m1.Row(), m1.Col());
    for (int i = 0; irow) ? row : iRow;
    int minCol = (iCol>col) ? col : iCol;
    int  colSize = minCol * sizeof(double);


    for (int i = 0; i < minRow; i++)
    {
        memcpy(rsData[i], dMatData[i], colSize);
    }

    for (int i = 0; i < minRow; i++)
    {
        delete[] dMatData[i];
    }
    delete[] dMatData;
    dMatData = rsData;
    iRow = row;
    iCol = col;
    return;
}
void CMatrix::SetRow(int row, double arrrow[])
{
    if (row > iRow)
        throw("CMatrix::SetRow: the row is out of index");
    if (sizeof(arrrow) / sizeof(double) > iCol)
        throw("CMatrix::SetRow: the col is out of index");
    for (int i = 0; i < iCol; i++)
    {
        dMatData[row][i] = arrrow[i];
    }
}



//重载预算符-
CMatrix operator - (const CMatrix& m1, const CMatrix& m2)
{

    if ((m1.Col() != m2.Col()) || (m1.Row() != m2.Row()))
    {
        throw("CMatrix::operator-: The two matrix have different size!");
    }

    CMatrix matTmp(m1.Row(), m1.Col());
    for (int i = 0; i dMainCell)
                {
                    dMainCell = dTemp;
                    MainRow[k] = i;
                    MainCol[k] = j;
                }
            }
        }

        if (fabs(dMainCell) < 0.0000000000001)//矩阵秩亏,不能求逆
        {
            throw("矩阵秩亏");
        }

        if (MainRow[k] != k)//交换行
        {
            for (j = 0; j= 0; k--)
    {
        if (MainCol[k] != k)// 交换行
        {
            for (j = 0; j

你可能感兴趣的:(相对定向-绝对定向(C++实现)--摄影测量学)