2020-01-15 C++ 绝对定向

#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>

using namespace cv;
using namespace std;

//求解绝对定向的步骤
/*
① 给定七个参数的初始值 phi = omega = kappa = 0 scale = 1 X = Y =Z= 0;
② 计算控制点地面坐标系的重心坐标和各控制点重心化的坐标
③ 计算模型点空间坐标系的重心坐标和各模型点重心化的坐标
④ 计算常数项 误差方程的常数项(矩阵表示)【lx ly lz】^T 书本71
⑤ 计算误差方程的系数矩阵 一般为3*7 矩阵(多个控制点则表示为3n * 7) 
⑥ 逐点法化求解法方程
⑦ 计算待定系数(scale phi omega kappa)的新值
⑧ 判断待定系数改正数是否均小于限定阈值xita
⑨ 根据求解的系数(scale phi omega kappa)代入重心变换方程求解X Y Z
*/

#define NUM 4 //地面控制点数量
#define JINDU 0.001//阈值
#define PI 3.14159265358975

//矩阵的数乘
Mat muul(Mat& p, double s) {
    int row = p.rows;
    int col = p.cols;
    Mat res = Mat_<double>(row, col);

    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {

            res.at <double>(i, j) = s;
        }

    }

    res = p.mul(res);
    double a = res.at<double>(0, 0);
    return res;

}


//求重心
Mat getTheCore(vector<Mat> &vec1) {

    int num = vec1.size();
    Mat p1 = (Mat_<double>(3, 1) << 0.0, 0.0, 0.0);
    for (int i = 0; i < num; i++)
    {
        p1 = p1 + vec1[i];


    }
    double cc = 1 / (double)num;
    Mat res = muul(p1,cc);
    double a = res.at<double>(0, 0);

    return res;

}

//摄影测量R矩阵
Mat getTheR(double omiga, double phi, double kamma) {
    double a1 = cos(phi) * cos(kamma) - sin(phi) * sin(omiga) * sin(kamma);
    double a2 = -cos(phi) * sin(kamma) - sin(phi) * sin(omiga) * cos(kamma);
    double a3 = -sin(phi) * cos(omiga);
    double b1 = cos(omiga) * sin(kamma);
    double b2 = cos(omiga) * cos(kamma);
    double b3 = -sin(omiga);
    double c1 = sin(phi) * cos(kamma) + cos(phi) * sin(omiga) * sin(kamma);
    double c2 = -sin(phi) * sin(kamma) + cos(phi) * sin(omiga) * cos(kamma);
    double c3 = cos(phi) * cos(omiga);

    Mat result = (Mat_<double>(3, 3) << a1, a2, a3, b1, b2, b3, c1, c2, c3);
    return result;

}

//多个控制点的矩阵形式转换
Mat transMat(vector<Mat>& vec, int num) {

    Mat ret = vec[0];

    for (int i = 1; i < vec.size(); i++)
    {
        vconcat(ret, vec[i], ret);
    }
    return ret;
}

//L

Mat getL(vector<Mat>& vec_tp, vector<Mat>& vec, double scale, Mat& r) {

    vector<Mat> vec_L;

    for (int i = 0; i < vec.size(); i++)
    {
        Mat m_tp = vec_tp[i];
        Mat m = vec[i];
        Mat r_m = r * m;
        Mat L = m_tp - muul(r_m,scale);
        vec_L.push_back(L);

    }

    Mat LL = transMat(vec_L, NUM);

    return LL;
}

//A

Mat getA(vector<Mat> &vec) {

    vector<Mat> vec_A;
    for (int i = 0; i < vec.size(); i++)
    {
        Mat m = vec[i];
        double X = m.at<double>(0, 0);
        double Y = m.at<double>(1, 0);
        double Z = m.at<double>(2, 0);

        Mat A = (Mat_<double>(3, 7) << 1, 0, 0, X, -Z, 0, -Y,
            0, 1, 0, Y, 0, -Z, X,
            0, 0, 1, Z, X, Y, 0);

        vec_A.push_back(A);
    }

    
    Mat AA = transMat(vec_A, NUM);


    return AA;

}

//求重心化
vector<Mat> CoreMat(vector<Mat> &p1, Mat &core) {

    vector<Mat> result;

    for (int i = 0; i < p1.size(); i++)
    {
        Mat m = p1[i];
        Mat res_m = m - core;
        result.push_back(res_m);
    }

    return result;
}

//计算改正数
Mat getX(Mat& A, Mat& L) {

    Mat AtA = (A.t()) * A;
    Mat nAtA;
    invert(AtA, nAtA, DECOMP_LU);
    Mat X = nAtA * (A.t()) * L;
    return X;
}

int main(int argc, char* argv[]) {



    // 初始化参数
    double scale = 1.0;
    double omega = 0.0;
    double phi = 0.0;
    double kappa = 0.0;
    double X = 0.0;
    double Y = 0.0;
    double Z = 0.0;

    //改正数
    double d_scale = 1.0;
    double d_phi = 1.0;
    double d_omega = 1.0;
    double d_kappa = 1.0;

    double jindu = JINDU;

    /*测试一下*/



    vector<Mat> vec1 = {(Mat_<double>(3,1)<< 153.706,767.599, 4.98951),(Mat_<double>(3,1) << 826.447,757.146,45.0979) ,(Mat_<double>(3,1) << 130.021,-772.319,-14.688) ,(Mat_<double>(3,1) << 804.556, -782.906 ,-22.5479) };//像辅助原始点坐标
    vector<Mat> vec2 = {(Mat_<double>(3,1) << 5083.26,5852.04,527.963),(Mat_<double>(3,1) << 5779.98,5906.4,571.513) ,(Mat_<double>(3,1) << 5210.76,4258.46,461.775) ,(Mat_<double>(3,1) << 5909.37,4314.29,455.517) };//控制点地面原始点坐标

    vector<Mat> core_vec1;//像辅助重心化点坐标
    vector<Mat> core_vec2;//控制点地面重心化点坐标

    //求解重心和重心化坐标
    Mat core1 = getTheCore(vec1);
    Mat core2 = getTheCore(vec2);


    core_vec1 = CoreMat(vec1, core1);
    core_vec2 = CoreMat(vec2, core2);


    while (!(!(fabs(d_kappa) > jindu) && !(fabs(d_omega) > jindu) && !(fabs(d_phi) > jindu)))
    {
        //获得矩阵形式的R,A L
        Mat R = getTheR(omega, phi, kappa);
        Mat A = getA(core_vec1);
        Mat L = getL(core_vec2, core_vec1, scale, R);

        //计算改正数
        Mat XX = getX(A, L);
    

        //计算新值
        d_scale = XX.at<double>(3, 0);
        d_phi = XX.at<double>(4, 0);
        d_omega = XX.at <double>(5, 0);
        d_kappa = XX.at<double>(6, 0);

        scale = scale *(1 + d_scale);
        phi += d_phi;
        omega += d_omega;
        kappa += d_kappa;
    }
    

    //计算最终的XYZ
    Mat R = getTheR(omega, phi, kappa);
    Mat XYZ;
    Mat r_core1 = R * core1;
    XYZ = core2 - muul(r_core1, scale);
 
    double pi = PI;
    double dS_omega = (180/pi)*(omega - int(omega / (2*pi)) * (2*pi));
    double dS_phi = (180 / pi) * (phi - int(phi / (2 * pi)) * (2 * pi));
    double dS_kappa = (180 / pi) * (kappa - int(kappa / (2 * pi)) * (2 * pi));
    X = XYZ.at<double>(0, 0);
    Y = XYZ.at<double>(1, 0);
    Z = XYZ.at<double>(2, 0);

    return 1;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容