基于罗格里德矩阵的坐标转换7参数求取

Rodrigues' Rotation Matrix(罗德里格旋转矩阵) 使用蒙特卡洛方法做半球面采样时遇到有这样的一个问题:默认产生的采样向量组所在的半球面是Y轴(或其它轴)所对应的方向,但是在使用时可能就需要根据法向量对其进行变换,于是就有了这样一个问题,给定两个向量V0和V1 计算出一旋转矩阵R得到: R V0 =V1 这个问题其实蛮简单,可以直接用两个向量的点积与叉乘计算出对应的夹角与旋转轴,然后组合出旋转矩阵即可(http://en.wikipedia.o 阅读详情
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;



namespace Spearman_count
{
    class Spearman 
    {
       public static double[,] Input(int n)//对输入的坐标,按行分,即每行存储一个点的坐标(x,y,z)信息;
        {            
            double[,] coordinate = new double[n, 3];
            string[] st = Console.ReadLine().Split(' ');
            for (int i = 0; i < n; ++i)
            {
                coordinate[i, 0] = Convert.ToDouble(st[0 + i * 3]);
                coordinate[i, 1] = Convert.ToDouble(st[1 + i * 3]);
                coordinate[i, 2] = Convert.ToDouble(st[2 + i * 3]);
            }
                return coordinate;
        }
       public static int Factorial(int x)//定义一个用于计算阶乘的方法;
        {
            int y=1;
            for (int i = x; i > 0; --i)
                y = y * i;
            return y;
        }
       public static int Com_number(int n, int m)//计算C(n,m)
        {

            int N = (Factorial(n) / (Factorial(n - m)) / Factorial(m));
            return N;
        }
       public static double[,] Combination_2(int C_n_m, int n, double[,] a)
        {
            double[,] com = new double[C_n_m, 6];int I = 0;int J = 0;          
                    for (int i_1 = 0; i_1 < n - 1; ++i_1)
                        for (int i_2 = 1 + i_1; i_2 < n ; ++i_2)
                            for (int j = 0; j < 3; ++j)
                                {
                                    com[I, J] = a[i_1, j]; ++J;
                                    com[I, J] = a[i_2, j]; ++J;
                                    if (J == 6) { J = 0; ++I; } 
                                }
            return com;
        }   
       public static double[,] Combination_3(int C_n_m,int n,double[,] a)//定义一个从n个点中抽取3个的组合方法;
        {
            double[,] com = new double[C_n_m, 9]; int I = 0; int J = 0;   
        
                    for (int i_1 = 0; i_1 < n - 2; ++i_1)
                        for (int i_2 = 1 + i_1; i_2 < n - 1; ++i_2)
                            for (int i_3 = 1 + i_2; i_3 < n; ++i_3)
                                for (int j = 0; j < 3; ++j)
                                {
                                    com[I, J] = a[i_1, j]; ++J;  com[I, J] = a[i_2, j]; ++J;
                                    com[I, J] = a[i_3, j]; ++J;
                                    if (J == 9) { J = 0; I = I + 1; }                                    
                                } 
            return com;
        }
       public static double[,] Combination_4(int C_n_m, int n, double[,] a)//定义一个从n个点中抽取4个的组合方法;
        {
            double[,] com = new double[C_n_m, 12]; int I = 0; int J = 0;
            for (int i_1 = 0; i_1 < n - 3; ++i_1)
                        for (int i_2 = 1 + i_1; i_2 < n - 2; ++i_2)
                            for (int i_3 = 1 + i_2; i_3 < n - 1; ++i_3)
                                for (int i_4 = 1 + i_3; i_4 < n; ++i_4 )
                                    for (int j = 0; j < 3; ++j)
                                    {
                                        com[I, J] = a[i_1, j]; ++J; com[I, J] = a[i_2, j]; ++J;
                                        com[I, J] = a[i_3, j]; ++J; com[I, J] = a[i_4, j]; ++J;
                                        if (J == 12) { J = 0; ++I; }
                                    }
            return com;
        }
       public static double[,] Combination_5(int C_n_m, int n, double[,] a)//定义一个从n个点中抽取5个的组合方法;
        {
            double[,] com = new double[C_n_m, 15]; int I = 0; int J = 0;
                    for (int i_1 = 0; i_1 < n - 4; ++i_1)
                        for (int i_2 = 1 + i_1; i_2 < n - 3; ++i_2)
                            for (int i_3 = 1 + i_2; i_3 < n - 2; ++i_3)
                                for (int i_4 = 1 + i_3; i_4 < n - 1; ++i_4)
                                    for (int i_5 = 1 + i_4; i_5 < n; ++i_5)
                                        for (int j = 0; j < 3; ++j)
                                        {
                                            com[I, J] = a[i_1, j]; ++J; com[I, J] = a[i_2, j]; ++J;
                                            com[I, J] = a[i_3, j]; ++J; com[I, J] = a[i_4, j]; ++J;
                                            com[I, J] = a[i_5, j]; ++J; if (J == 15) { J = 0; I = I + 1; }
                                        }
            return com;
        }
       public static double[,] Com_Array(int C_n_m, int n, int m, double[,] a)//定义一个生成组合数组的方法;
        {
            double[,] com_a = new double[C_n_m, m * 3]; 
            switch (m)
            {
                case 2:
                    com_a = Combination_2(C_n_m, n, a);
                    break;
                case 3:
                    com_a = Combination_3(C_n_m, n, a);
                    break;
                case 4:
                    com_a = Combination_4(C_n_m, n, a);
                    break;
                case 5:
                    com_a = Combination_5(C_n_m, n, a);
                    break;
            }
            return com_a;
        }
       public static double[,] R(int C_n_m, int m, double[,] a)//定义一个对组合数组安装每行进行求秩的方法,默认每个数都不相等,返回每行的秩;
        {
            double[,] R_a = new double[C_n_m, m * 3];//实现对数组内所有x、y、z元素排序后存储的空间;
            double[,] r = new double[C_n_m, m * 3];
            double[] b=new double[m * 3];
            for (int i = 0; i < C_n_m; ++i)//逐行进行排序;
            {
                for (int j = 0; j < m * 3; ++j)
                    b[j] = a[i, j];
                Array.Sort(b);
                Array.Reverse(b);    //实现倒序排列,即数值越大,秩越大;
                for (int k = 0; k < m * 3; ++k)
                    R_a[i,k] = b[k];
                Array.Clear(b, 0, 6);
            }
            for (int i = 0; i < C_n_m; ++i)
                for (int j = 0; j < m * 3; ++j)
                    for (int k = 0; k < m * 3; ++k)
                        if (a[i, j] == R_a[i, k])//定原数组a的元素,对排序好的数组R_a进行遍历;
                            r[i, j] = k + 1;
            return r;
        }
       public static double[] spearman(int C_n_m, int m, double[,] a, double[,] b)//求每个组合数组的spearman系数;
        {                                                                   //数组a、b分别为新、旧坐标秩数;每一行为一组公共点,列为新旧坐标值。
            double[,] Diffe_Sqr_R = new double[C_n_m, m * 3]; //每个元素的秩作差求平方;
            double[] sum = new double[C_n_m];                 //每组内的秩差平方求和;
            double[] r_s = new double[C_n_m];                 //每组的Spearman系数;
            for (int i = 0; i < C_n_m; ++i)
            {
                for (int j = 0; j < 3 * m; ++j)
                {
                    Diffe_Sqr_R[i, j] = Math.Pow((a[i, j] - b[i, j]), 2);
                    sum[i] = sum[i] + Diffe_Sqr_R[i, j];
                }
                r_s[i] = 1 - 6 * sum[i] / ((3 * m) * (Math.Pow(3 * m, 2) - 1));
            }
            return r_s;
        }
       public static double[] Sort(int C_n_m,double[] a)
       {
           double[] sort = new double[C_n_m];
           Array.Sort(a);
           for (int j = 0; j < C_n_m; ++j)
               sort[j] = a[j];
           return sort;
       }
       public static double[,] Print(int C_n_m,int n, int m, double[,] a, double[,] b)
        {
            double[,] R_N = new double[C_n_m, m * 3]; R_N = R(C_n_m, m, a);  //求新坐标中每种组合方法的秩;
            double[,] R_O = new double[C_n_m, m * 3]; R_O = R(C_n_m, m, b);
            double[] R_S = new double[C_n_m]; R_S = spearman(C_n_m, m, R_N, R_O);//求每一组的spearman系数;
            double[,] print = new double[C_n_m, 1 + 6 * m];
            int I=0,J=0;
            for (int i = 0; i < C_n_m; ++i)
            {
                for (int j = 0; j < 6 * m; ++j)
                {
                    if (j < 3 * m)
                    { print[I, J] = a[i, j]; ++J; }
                    else
                    { print[I, J] = b[i, j - (3 * m)]; ++J; }
                }
                print[I, J] = R_S[I]; ++I; J = 0;
            }            
           for (int i = 0; i < C_n_m; ++i)
           {
               Console.Write("{0},", i + 1);
               for (int j = 0; j < 1 + 6 * m; ++j)
                   Console.Write("{0:f5},", print[i, j]);
               Console.Write("\n");
           }
           Console.ReadLine();
           return print;
       }     
    }

    class parameter : Spearman
   {
       public static double[] M_para(int C_n_m, int m, double[,] a)//比例尺参数;//运行无误
       {
           double[,] I = new double[C_n_m, 6 * (m - 1)];
           double[,] m_i_j = new double[C_n_m, m - 1];
           double[] sum_m_i_j = new double[C_n_m]; sum_m_i_j[0] = 0;
           double[] M = new double[C_n_m];
           int k = 0;
           for (int i = 0; i < C_n_m; ++i)
           {
               for (int j = 0; j < 2 * 3 * m; ++j)
               {                         //例:m=3;
                   if (j < m - 1)        //k=0,1; I存储的是相邻x相减平方的值;                
                   { I[i, k] = Math.Pow(a[i, j] - a[i, j + 1], 2); ++k; }      //K=0,1
                   else if (j >= m && j < 2 * m - 1)  //k=3,4; I存储的是相邻Y相减平方的值;
                   { I[i, k] = Math.Pow(a[i, j] - a[i, j + 1], 2); ++k; }      //K=2,3
                   else if (j >= 2 * m && j < 3 * m - 1)  //k=6,7; Z
                   { I[i, k] = Math.Pow(a[i, j] - a[i, j + 1], 2); ++k; }      //K=4,5
                   else if (j >= 3 * m && j < 4 * m - 1)   //k=9,10; k
                   { I[i, k] = Math.Pow(a[i, j] - a[i, j + 1], 2); ++k; }      //K=6,7
                   else if (j >= 4 * m && j < 5 * m - 1)  //k=12,13;y
                   { I[i, k] = Math.Pow(a[i, j] - a[i, j + 1], 2); ++k; }      //K=8,9
                   else if (j >= 5 * m && j < 6 * m - 1)   //k=15,16;z
                   { I[i, k] = Math.Pow(a[i, j] - a[i, j + 1], 2); ++k; }      //K=10,11
                   else
                       continue;
               }
               k = 0;   //返回的数组I:(X1-X2)^2,(X2-X3)^2,(Y1-Y2)^2,(Y2-Y3)^2,(Z1-Z2)^2,(Z2-Z3)^2,
                        //             (x1-x2)^2,(x2-x3)^2,(y1-y2)^2,(y2-y3)^2,(z1-z2)^2,(z2-z3)^2;
           }
           for (int i = 0; i < C_n_m; ++i)
               for (int j = 0; j < m - 1; ++j)
               {
                   m_i_j[i, j] = Math.Sqrt((I[i, j] + I[i, j + (m - 1)] + I[i, j + (2 * (m - 1))])
                                         / (I[i, j + (3 * (m - 1))] + I[i, j + (3 * (m - 1)) + (m - 1)] + I[i, j + (3 * (m - 1)) + (2 * (m - 1))]));
                   //如m=4———————(I[0,0]+I[0,   3  )]+I[i,    6     ])/(I[i,     9    ))]+I[i,         12      ]+I[i,            15       ])
                   //m=3——3个点能做每个坐标能做2组差,I每行有2*(3+3);
                   sum_m_i_j[i] = sum_m_i_j[i] + m_i_j[i, j];
               }
           for (int i = 0; i < C_n_m; ++i)
               M[i] = (2 * sum_m_i_j[i] / (m * (m - 1)));           
           foreach(double i in M)
               Console.Write("{0:f5},",i);
           Console.Write("\n");
           Console.ReadLine();
           return M;
       }
       public static double[, ,] Rota_rel(int C_n_m, int m,double[] M, double[,] a)//求公共点旋转参数相关矩阵,最后一列为坐标差;//运行无误
       {           
           double[, ,] R_rel = new double[C_n_m, 3 * (m - 1), 4];//构建一个用于求罗格里德矩阵中三个参数的3*(m-1)×3反对称矩阵,
           double[,] Sub_N = new double[C_n_m, 3 * (m - 1)];  //       最后一列将存储sub;
           double[,] Sub_O = new double[C_n_m, 3 * (m - 1)]; //已经乘以尺度参数M;
           double[,] sub = new double[C_n_m, 3 * (m - 1)];//新坐标与旧坐标×M之后的差;
           double[,] add = new double[C_n_m, 3 * (m - 1)];//辅助建立反对称矩阵; 
           int K = 0;
           for (int i = 0; i < C_n_m; ++i)  //将新旧坐标分开存储;               //新:X2-X1,X3-X1,Y2-Y1,Y3-Y1,Z2-Z1,Z3-Z1;
           {                                                                     //旧:Move×(x2-x1,x3-x1,y2-y1,y3-y1,z2-z1,z3-z1);
               for (int j = 1; j < 6 * m; ++j)
               {                                                   //li:m=3;
                   if (j < m)                                      //k=1,2
                   { Sub_N[i, K] = a[i, j] - a[i, 0]; ++K; }
                   else if (j > m && j < 2 * m)                    //k=4,5
                   { Sub_N[i, K] = a[i, j] - a[i, m]; ++K; }
                   else if (j > 2 * m && j < 3 * m)                //k=7,8
                   {
                       Sub_N[i, K] = a[i, j] - a[i, 2 * m]; ++K;
                       if (K == 3 * (m - 1)) K = 0;
                   }
                   else if (j > 3 * m && j < 4 * m)                //k=10,11
                   { Sub_O[i, K] = M[i] * (a[i, j] - a[i, 3 * m]); ++K; }
                   else if (j > 4 * m && j < 5 * m)                //k=13,14
                   { Sub_O[i, K] = M[i] * (a[i, j] - a[i, 4 * m]); ++K; }
                   else if (j > 5 * m && j < 6 * m)                //k=16,17
                   { Sub_O[i, K] = M[i] * (a[i, j] - a[i, 5 * m]); ++K; }
                   else
                       continue;
               } K = 0;
           }
           for (int i = 0; i < C_n_m; ++i)
               for (int j = 0; j < 3 * (m - 1); ++j)
               {
                   sub[i, j] = Sub_N[i, j] - Sub_O[i, j];//完成求新坐标与旧坐标×M之后的差以及和计算,U21-X21,U31-X31,V21-Y21,V31-Y31,W21-Z21,W31-Z31;
                   add[i, j] = Sub_N[i, j] + Sub_O[i, j];//和计算用于辅助建立反对称阵;行之间为组合方式,行内是一种组合方式中关于点的计算
               }                                         //add数组: U21+X21,U31+X31,V21+Y21,V31+Y31,W21+Z21,W31+Z31;
           int L = 0;
           for (int i = 0; i < C_n_m; ++i)
           {
               for (int j = 0; j < 3 * (m - 1); ++j) //m=3  ,  k<6
               {
                   for (int k = 0; k < 4; ++k)
                   {
                       if (j % 3 == 0)
                       {
                           switch (k)
                           {
                               case 0:
                                   R_rel[i, j, k] = 0;
                                   break;
                               case 1:
                                   R_rel[i, j, k] = 0 - add[i, K + 2 * (m - 1)];
                                   break;
                               case 2:
                                   R_rel[i, j, k] = 0 - add[i, K + (m - 1)];
                                   break;
                               case 3:
                                   R_rel[i, j, 3] = sub[i, L];
                                   break;
                           }
                       }
                       if (j % 3 == 1)
                       {
                           switch (k)
                           {
                               case 0:
                                   R_rel[i, j, k] = R_rel[i, j - 1, 1];
                                   break;
                               case 1:
                                   R_rel[i, j, k] = 0;
                                   break;
                               case 2:
                                   R_rel[i, j, k] = add[i, K]; ++K;
                                   break;
                               case 3:
                                   R_rel[i, j, 3] = sub[i, (m - 1) + L];
                                   break;
                           }
                       }
                       if (j % 3 == 2)
                       {
                           switch (k)
                           {
                               case 0:
                                   R_rel[i, j, k] = R_rel[i, j - 2, 2];
                                   break;
                               case 1:
                                   R_rel[i, j, k] = R_rel[i, j - 1, 2];
                                   break;
                               case 2:
                                   R_rel[i, j, k] = 0;
                                   break;
                               case 3:
                                   R_rel[i, j, 3] = sub[i, 2 * (m - 1) + L]; ++L;
                                   break;
                           }
                       }
                   }
               } K = 0; L = 0;
           }           
           for (int i = 0; i < C_n_m; ++i)
           {
               for (int j = 0; j < 3*(m-1); ++j)
               {
                   for (int k = 0; k < 4; ++k)
                   {
                       Console.Write("{0:f5}", R_rel[i, j, k]);
                       if (k != 3) Console.Write(",");
                   }
                   Console.Write("\n");
               }Console.Write("\n");               
           }Console.ReadLine();           
           return R_rel;
       }
//借助MATLAB,求出a,b,c      
       public static double[, ,] Rota_para(int C_n_m, double[,] loge)//9个旋转参数,运行无误
       {
           double[] H = new double[C_n_m];
           for (int i = 0; i < C_n_m; ++i)
               H[i] = 1 + Math.Pow(loge[i, 0], 2) + Math.Pow(loge[i, 1], 2) + Math.Pow(loge[i, 2], 2);
           double[, ,] R = new double[C_n_m, 3, 3]; //最终旋转矩阵;
           for (int i = 0; i < C_n_m; ++i)
           {
               R[i, 0, 0] = (1 + Math.Pow(loge[i, 0], 2) - Math.Pow(loge[i, 1], 2) - Math.Pow(loge[i, 2], 2)) / H[i];
               R[i, 0, 1] = 0 - 2 * (loge[i, 2] + loge[i, 0] * loge[i, 1]) / H[i];
               R[i, 0, 2] = 0 - 2 * (loge[i, 1] - loge[i, 0] * loge[i, 2]) / H[i];
               R[i, 1, 0] = 2 * (loge[i, 2] - loge[i, 0] * loge[i, 1]) / H[i];
               R[i, 1, 1] = (1 - Math.Pow(loge[i, 0], 2) + Math.Pow(loge[i, 1], 2) - Math.Pow(loge[i, 2], 2)) / H[i];
               R[i, 1, 2] = 0 - 2 * (loge[i, 0] + loge[i, 1] * loge[i, 2]) / H[i];
               R[i, 2, 0] = 2 * (loge[i, 1] + loge[i, 0] * loge[i, 2]) / H[i];
               R[i, 2, 1] = 2 * (loge[i, 0] - loge[i, 1] * loge[i, 2]) / H[i];
               R[i, 2, 2] = (1 - Math.Pow(loge[i, 0], 2) - Math.Pow(loge[i, 1], 2) + Math.Pow(loge[i, 2], 2)) / H[i];
           }
           for (int i = 0; i < C_n_m; ++i)
           {
               for (int j = 0; j < 3; ++j)
               {
                   for (int k = 0; k < 3; ++k)
                       Console.Write("{0,5},", R[i, j, k]);
                   Console.Write("\n");
               } Console.Write("\n");
           } Console.ReadLine();
           return R;
       }
       public static double[,] Move_para(int C_n_m, int m, double[,] a,double[] M , double[, ,] R)//平移参数,运行无误;
       {                                                                                      //move的存储内容:m=3
           double[, ,] move = new double[C_n_m, 3, 3 * m];                                    //DX1 DX2 DX3  →相加 sum[,0]
           double[,] sum = new double[C_n_m, 3]; sum[0, 0] = sum[0, 1] = sum[0, 2] = 0;       //DY1 DY2 DY3  →相加 sum[,1]
           double[,] Move = new double[C_n_m, 3];  //返回最终的平移参数,即求平均后;         //DZ1 DZ2 DZ3  →相加 sum[,2]
           for (int i = 0; i < C_n_m; ++i)
           {
               for (int k = 0; k < m; ++k)
               {
                   move[i, 0, k] = a[i, k] - M[i] * (R[i, 0, 0] * a[i, k + 3 * m] + R[i, 0, 1] * a[i, k + 3 * m + m] + R[i, 0, 2] * a[i, k + 3 * m + 2 * m]);
                   sum[i, 0] = sum[i, 0] + move[i, 0, k];
                   move[i, 1, k] = a[i, m + k] - M[i] * (R[i, 1, 0] * a[i, k + 3 * m] + R[i, 1, 1] * a[i, k + 3 * m + m] + R[i, 1, 2] * a[i, k + 3 * m + 2 * m]);
                   sum[i, 1] = sum[i, 1] + move[i, 1, k];
                   move[i, 2, k] = a[i, 2 * m + k] - M[i] * (R[i, 2, 0] * a[i, k + 3 * m] + R[i, 2, 1] * a[i, k + 3 * m + m] + R[i, 2, 2] * a[i, k + 3 * m + 2 * m]);
                   sum[i, 2] = sum[i, 2] + move[i, 2, k];
               }
               Move[i, 0] = sum[i, 0] / m; Move[i, 1] = sum[i, 1] / m; Move[i, 2] = sum[i, 2] / m;
           }
           for (int i = 0; i < C_n_m; ++i)
           {
               for (int j = 0; j < 3; ++j)
                   Console.Write("{0,5},", Move[i, j]);
               Console.Write("\n");
           } Console.ReadLine();
           return Move;
       }
       public static double[] Va_error(int C_n_m, int m, double[,] a, double[] M,double[, ,] R, double[,] Move)//求方差,运行无误;
       {
           double[, ,] TheoCo = new double[C_n_m, m, 3];
           double[, ,] error_V = new double[C_n_m, m, 3];
           double[] Va = new double[C_n_m];
           double[] sum = new double[C_n_m]; sum[0] = 0;
           for (int i = 0; i < C_n_m; ++i)
           {
               for (int j = 0; j < m; ++j)
               {
                   TheoCo[i, j, 0] = Move[i, 0] + M[i] * (R[i, 0, 0] * a[i, 3 * m + j] + R[i, 0, 1] * a[i, 4 * m + j] + R[i, 0, 2] * a[i, 5 * m + j]);
                   error_V[i, j, 0] = a[i, j] - TheoCo[i, j, 0];
                   TheoCo[i, j, 1] = Move[i, 1] + M[i] * (R[i, 1, 0] * a[i, 3 * m + j] + R[i, 1, 1] * a[i, 4 * m + j] + R[i, 1, 2] * a[i, 5 * m + j]);
                   error_V[i, j, 1] = a[i, m + j] - TheoCo[i, j, 1];
                   TheoCo[i, j, 2] = Move[i, 2] + M[i] * (R[i, 2, 0] * a[i, 3 * m + j] + R[i, 2, 1] * a[i, 4 * m + j] + R[i, 2, 2] * a[i, 5 * m + j]);
                   error_V[i, j, 2] = a[i, 2 * m + j] - TheoCo[i, j, 2];
                   sum[i] = sum[0] + (Math.Pow(error_V[i, j, 0], 2) + Math.Pow(error_V[i, j, 1], 2) + Math.Pow(error_V[i, j, 2], 2));
               }
               Va[i] = sum[i] / (3 * m - 7);
           }       
           foreach (int i in Va)
               Console.Write("{0,5},", i);
           Console.ReadLine();
           return Va;
       }
       static void Main(string[] args)
       {
           Console.Write(" 请说明成对公共点的数量:\n");//应当大于3
           int n = Convert.ToInt32(Console.ReadLine());
           Console.Write(" 请说明要选择用于7参数计算的公共点数量(应当3~5对):\n");
           int m = Convert.ToInt32(Console.ReadLine());
           int C_n_m = Com_number(n, m);
           Console.Write(" {0}中选取{1}个点的组合方法共有{2}种。\n", n, m, C_n_m); Console.Write("\n");
           Console.Write(" 请输入新坐标系下点的三维坐标,以空格符分开,如: X Y Z\n");
           double[,] N = new double[n, m * 3]; N = Input(n); Console.Write("\n");
           Console.Write(" 请输入对应原坐标系下点的三维坐标,以空格符分开,如: x y z\n");
           double[,] O = new double[n, m * 3]; O = Input(n);
           double[,] Com_N = new double[C_n_m, m * 3]; Com_N = Com_Array(C_n_m, n, m, N); //对新坐标点进行组合,行数为组合数量C(n,m),列数为公共点坐标总量;            
           double[,] Com_O = new double[C_n_m, m * 3]; Com_O = Com_Array(C_n_m, n, m, O);//每种组合方法构成一行;
           Console.Write("\n");
           double[,] N_O_Spear = new double[C_n_m, 6 * m + 1];//对组合后新旧坐标以及spearman系数组成一行;
           N_O_Spear = Print(C_n_m, n, m, Com_N, Com_O);
           double[] M = new double[C_n_m]; M = M_para(C_n_m, m, N_O_Spear);//尺度参数;
           double[, ,] R_rel = new double[C_n_m, 3 * (m - 1), 4];//用于计算罗格里德参数a,b,c的系数矩阵;
           R_rel = Rota_rel(C_n_m, m, M, N_O_Spear);           
           double[,] loge = new double[C_n_m, 3];//从MATLAB中获取3个参数; 

           double[, ,] R = new double[C_n_m, 3, 3];
           R = Rota_para(C_n_m, loge);//完成旋转矩阵的计算;
           double[,] Move = new double[C_n_m, 3];
           Move = Move_para(C_n_m, m, N_O_Spear, M, R);//完成平移参数计算;
           double[] Va = new double[C_n_m];
           Va = Va_error(C_n_m, m, N_O_Spear, M, R, Move);//求方差计算;

           Print(C_n_m, n, m, Com_N, Com_O);
           Console.ReadLine();

       }   
   }
}
罗德里格斯(Rodrigues)旋转向量与矩阵的变换 在做双目立体视觉深度图像生成的时候,遇到旋转向量(1x3)与旋转矩阵(3x3)的概念,得知二者可以通过罗德里格斯相互转化。 1.旋转的表示      处理三维旋转问题时,通常采用旋转矩阵的方式来描述旋转变换。旋转矩阵有以下两种方式得到。       物体在三维空间中的旋转,可以被分为解为在直接坐标系下,分别先后围绕x,y,z坐标轴旋转得到。旋转的角度也就是我们常听到的角度roll,pit 阅读详情

相关推荐

罗德里格斯变换

罗德里格斯变换   当处理三维空间的时候,常常需要用3X3矩阵表征空间旋转。   这种表示方法通常是最方便的,因为一个向量乘以该矩阵等价于该向量某种方式的旋转。不便之处是它不能直观显示3X3矩阵的旋转含义。   另外一个容易可视化的表示方式是用向量形式表示旋转,而该旋转每次用单个角度来操作。这种情况下,最标准的方式是仅用一个向量来说明绕坐标轴的旋转,向量长度表示绕轴逆时针旋转的角度。这个很容...

3D视觉工坊 1万+

七参数坐标转换的几种解法

七参数坐标转换的几种解法1.简介2.七参数模型3.最小二乘的多种解法3.1参数平差3.2 布尔沙解法3.3 符有限制条件的间接平差3.4 罗德里格矩阵3.5四元数 1.简介 坐标转换是测量领域中数据处理的基础性工作。目前,广为接收的三维坐标转换模型是七参数模型,即1个缩放参数、3个旋转角度参数和3个平移参数。理论上9参数模型更加完善,但使用场景很少。 2.七参数模型 七参数的数学模型为: [XYZ]s=k∗[1000cosa−sina0sinacosa][cosb0sinb010−sinb0cosb][co

weixin_42088149的博客 5561

C#实现布尔莎模型中7个参数的求解

利用C#实现了布尔莎模型中7个参数的求解,最小二乘法,程序中包含了矩阵转置、矩阵求乘积、矩阵求逆三个类,本人亲测。

Python 罗德里格矩阵的空间坐标转换——两组公共点求所属坐标系的旋转矩阵与平移矩阵

【代码】Python 罗德里格矩阵的空间坐标转换——两组公共点求所属坐标系的旋转矩阵与平移矩阵。

windSnowLi 1405

第二十六届中国机器人及人工智能大赛CRAIC决赛小型桌面级-立体仓储代码分享

国二奖,精度还有不少问题,没有视觉模块,单线程,比起其他大佬写的确实还有欠缺,继续加油吧。

qq_68232259的博客 691

从门禁到支付:Uniapp+NFC开发避坑指南(支持Mifare Classic)

本文详细介绍了Uniapp结合NFC技术开发门禁与支付系统的实战指南,特别针对Mifare Classic卡片进行深度优化。内容涵盖环境配置、设备兼容性处理、卡片安全机制解析以及高性能读写优化策略,帮助开发者快速实现跨平台的智能硬件交互解决方案。

t1u2v的博客 750

C++/Python:罗德里格斯旋转矩阵

给定两向量求其旋转矩阵/罗德里格斯矩阵

己亥谷雨 2748

FP7195升降压恒流驱动IC:从AC/DC 12~24V输入到稳定输出的高效电源设计实战

本文详细解析FP7195升降压恒流驱动IC的工作原理与应用实战。该芯片支持4.5V-32V宽输入范围,能自动切换升降压模式并保持输出恒定,特别适用于车载LED照明、工业电源等电压波动场景。通过实际案例分享PCB布局、元件选型及调试技巧,帮助工程师实现高效稳定的电源设计。

vodka的博客 953

详解基于罗德里格斯(Rodrigues)公式由旋转向量到旋转矩阵的 Python 实现

运行结果: 使用NumPy编写的 Rodrigues 公式计算旋转矩阵的结果与调用 OpenCV 的函数计算结果一致, 验证了代码的正确性.后得到的向量(有些文献也直接叫做旋转向量),收集整理和创作不易, 若有帮助🉑, 请帮忙。为旋转角(单位: 弧度rad),任何一个旋转运动都可以通过一个。任何一个旋转都可以通过一个。. 此时可以通过一个。

KRISNAT 4598

一种导弹追踪算法的MATLAB仿真实现

以下是一个用于模拟机动变轨导弹和防空导弹追踪过程的 MATLAB 代码,同时会提供 3D 效果展示。你可以运行这段代码,从而观察机动变轨导弹和防空导弹的速度与位置变化。

SmartGridequation的博客 933

[Python]:热血传奇-Wzl,Wzx的解析

首先我们要了解,wzl与wzx的对应关系,wzx里面存的是每张二进制图片数据在wzl中的偏移量,所以取到wzx中的偏移数据就可以取到wzl每张图片数据,其实就这么简单。结构体为 [Byte][Byte][Byte][Byte][short][short][short][short][int]-读取44至48字节代表为,[wzx中偏移值总数量] [int类型] [4字节]-根据在wzx中取得的偏移值总数量,每张图片偏移值在wzl中取图片数据。2.[取wzl中图片偏据]:根据wzx中取得数据对[

qq_36138506的博客 3445

【机器视觉】旋转矩阵,坐标系变换

分享一下我搓机器人过程中遇到的问题在机器视觉中,常需要将物体的坐标从一个坐标系变换到另一个坐标系。旋转矩阵可以精确描述物体在三维空间中的旋转关系,常配合平移矢量一起完成刚体变换。相关算法放在文末,博主不是计算机专业,代码基本都是根据数学公式写出来的,没有优化~

weixin_73858308的博客 2738

Mamba-UNet:用于医学图像分割的类似UNet的纯视觉Mamba网络

所提出的Mamba-UNet的架构如图2所示,其灵感来源于UNet [24] 和 Swin-UNet [3]。首先将大小为 H × W × 1 的2D灰度图像分割成类似于ViT和VMamba的块 [5,16],然后转换为维度为 H/4 × W/4 × 16 的1D序列。一个初始的线性嵌入层将特征维度调整为任意大小C。这些块令牌随后通过多个VSS块和块合并层进行处理,以创建分层特征。块合并层负责下采样和维度增加,而VSS块则专注于学习特征表示。

AI浩 7549

罗德里格斯变换和坐标变换

#include #include void main() { int i; double r_vec[3]={-2.100418,-2.167796,0.273330}; double R_matrix[9]; CvMat pr_vec; CvMat pR_matrix; cvInitMatHeader(&pr_vec,1,3,CV_64FC1

yuyangyg的博客 3392

【干货】SAP特殊库存:Q库存(项目库存)全解析,搞懂ETO模式的核心!

在 SAP 系统中,

我小时候很黑的博客 905

Python 爬虫教程:抓取视频平台数据(观看量、评论数、点赞数等)

爬虫(Crawler)是通过编写程序模拟浏览器行为,从互联网上抓取并提取信息的技术。爬虫的核心任务是模拟用户访问网页,获取网页内容并解析出我们需要的数据。爬虫技术被广泛应用于搜索引擎、数据分析、电商价格监控、内容抓取等领域。Bilibili和YouTube。这两个平台都提供丰富的用户生成内容(UGC),且在中国和全球范围内都非常流行。Bilibili:以二次元文化为主的视频平台,用户活跃,视频内容丰富。Bilibili的网页数据较为简单,可以通过传统的HTML解析抓取。YouTube。

2201_76125261的博客 1854

罗德里戈公式的推导和实现C++

3d 中两个向量的叉乘的意义表示的是平行四边形的面积。

weixin_39354845的博客 850

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

罗德里格斯(Rodrigues)变换

opencv C++实现 #include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/core.hpp> int main() { double r_vec[3] = { -2.100418,-2.167796,0.273330 }; cv::Mat pr_vec(1, 3, CV_64FC1, r_vec); std::cout << "pr_vec = " <&l

open123852的博客 8706

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

C++/Eigen实现简单的坐标系转换、罗德里格公共点转换

【代码】C++/Eigen实现简单的坐标系转换、罗德里格公共点转换。

windSnowLi 1507

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

关于罗德里格斯公式(Rodrigues‘s Formula)的详细推导过程

关于罗德里格斯公式(Rodrigues‘sFormula)的详细推导过程

羊羊羊ox的博客 7072

几何基础 罗德里格公式

一开始没太搞明白,为什么其中的向量投影是v⋅k⋅kv\cdot k \cdot kv⋅k⋅k 也就是点成了两次kkk,看完才明白标量投影和向量投影之区别。不管怎样,搞明白了就是在进步,也不再感叹自己才疏学浅。 向量投影时,我们要考虑大小和方向。 大小好说,vvv的模乘以cosθcos \thetacosθ集可得到。 另外就是要考虑方向,和kkk同向,也就是要乘以k∣k∣\frac{k}{|k|}∣k∣k​。又cosθ=v⋅k∣v∣⋅∣k∣cos \theta=\frac{v \cdot k}{|v| .

m0_38139098的博客 808

坐标变换及旋转矩阵

最近由于研究UR机器人的运动控制,所以复习和查阅了一些关于坐标系旋转之类的资料,记录一下,以备使用。 以下公式中,规定几种标识: 1) 坐标系A用{A}表示,同理,有{B}; 2) 左上角表示所在坐标系标识,如Ap^ApAp和Bp^BpBp表示点p分别在坐标系{A}和{B}中的坐标。 1 空间点的坐标变换 1.1 平移坐标变换 Ap=Bp+ApBO^Ap={^Bp}+{^Ap_{B_O}}Ap=B...

hangl_ciom的博客 1万+

罗德里格斯公式 理解、推导

罗德里格斯公式(Rodriguez formula)是计算机视觉中的一大经典公式,在描述相机位姿的过程中很常用。公式:R=I+sin(θ)K+(1−cos(θ))K2R = I + sin(\theta)K + (1 - cos(\theta))K^{2}   从旋转矩阵RR讲起,在三维空间中,旋转矩阵RR可以对坐标系(基向量组)进行刚性的旋转变换

GongBingjian 6万+

矩阵补全低秩结构

相反,如果低秩矩阵的奇异向量是"铺展"的——能量分散在所有行与所有列上,与采样矩阵的坐标基"不相干"——那么随机抽取有限个元素,就有很大概率覆盖到足以确定那几个潜在因子的信息。核范数是秩的凸松弛,就像 ℓ1 是 ℓ0 的凸松弛一样,它是"秩这个非凸目标在凸方向上最紧的替代"。报告里如果把矩阵补全压缩成几条可执行原则:第一,在动手做任何"从几行数据推断整张表"的任务前,先检验低秩假设是否成立——用已有的数据估计一下矩阵的近似秩,若秩接近满秩,那么低秩恢复这条路就不该走,应换用其他方法或引入领域约束降低秩。

2602_95606446的博客 300
上一篇: MySql小异常 —— Duplicate entry ‘1‘ for key ‘PRIMARY‘
下一篇: Composer安装与PHPWord的下载与使用
苏苏苏苏2018
博客等级 码龄7年 81粉丝 20原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值