ceres-solver拟合椭球

1. 库编译及引入。windows下用VS build ceres solver 库,  

http://blog.csdn.net/h349117102/article/details/12680261; 

http://blog.csdn.net/woaik110/article/details/45970031;

2. 

下面是椭球方程的公式。

我们要求解的就是。为了演示,我通过程序生成了一个单位球上面的一系列坐标,也就是上面的abc均为1,偏移量均为0。为了验证ceres-solver是否可以完成这个工作。

首先我们编写下面的测试代码。

下面是椭球方程的公式。

我们要求解的就是。为了演示,我通过程序生成了一个单位球上面的一系列坐标,也就是上面的abc均为1,偏移量均为0。为了验证ceres-solver是否可以完成这个工作。

首先我们编写下面的测试代码。

  1. #include "glog/logging.h"  
  2. #include "ceres/ceres.h"  
  3. #include <vector>  
  4.    
  5. using ceres::AutoDiffCostFunction;  
  6. using ceres::CostFunction;  
  7. using ceres::Problem;  
  8. using ceres::Solver;  
  9. using ceres::Solve;  
  10.    
  11. struct EllipsoidResidual  
  12. {  
  13.     /* 
  14.      * x, y, z 分别为观测值 
  15.     */  
  16.     EllipsoidResidual(double x, double y, double z):_x(x), _y(y), _z(z){}  
  17.    
  18.     /* 
  19.      *pEllipsoidParameters:-2分别为a、b、c,3-5分别为x0、y0、z0 
  20.     */  
  21.     template <typename T> bool operator () (const T * const pEllipsoidParameters,  T * residual) const  
  22.     {  
  23.         residual[0] = T(1.0) - T(_x - pEllipsoidParameters[3])*T(_x - pEllipsoidParameters[3])/T(pEllipsoidParameters[0]*pEllipsoidParameters[0]) -  
  24.             T(_y - pEllipsoidParameters[4])*T(_y - pEllipsoidParameters[4])/T(pEllipsoidParameters[1]*pEllipsoidParameters[1]) -  
  25.             T(_z - pEllipsoidParameters[5])*T(_z - pEllipsoidParameters[5])/T(pEllipsoidParameters[2]*pEllipsoidParameters[2]);  
  26.         return true;  
  27.     }  
  28. private:  
  29.     const double _x;  
  30.     const double _y;  
  31.     const double _z;  
  32. };  
  33.    
  34. struct Point3D  
  35. {  
  36.     double x;  
  37.     double y;  
  38.     double z;  
  39. };  
  40.    
  41. /* 
  42.  * 用于解算椭球参数的类 
  43.  * m_EllipsoidParameters:椭球参数的初始值 
  44.  * m_bInitParameters:椭球参数是否已经进行初始化 
  45.  * m_data:观测值 
  46.  * m_options:解算方式选项,可以进行设置 
  47.  * m_summary:解算的报告信息 
  48.  * 
  49.  * 使用方式: 
  50.  * ()设置椭球参数的初始值(m_EllipsoidParameters),并标记m_bInitParameters为true 
  51.  * ()设置观测值m_data(个数大于) 
  52.  * ()调用SolveParameters()函数 
  53.  * ()得到结果m_EllipsoidParameters与解算报告信息m_summary 
  54. */  
  55. struct EllipsoidFittingSolver  
  56. {  
  57.     EllipsoidFittingSolver()  
  58.     {  
  59.         m_options;  
  60.         m_options.max_num_iterations = 25;  
  61.         m_options.linear_solver_type = ceres::DENSE_QR;  
  62.         m_options.minimizer_progress_to_stdout = true;  
  63.         m_bInitParameters = false;  
  64.     }  
  65.    
  66.     bool SolveParameters()  
  67.     {  
  68.         if (m_data.size() < 6 || !m_bInitParameters)  
  69.         {  
  70.             return false;  
  71.         }  
  72.          
  73.         Problem problem;  
  74.         const int nObservations = m_data.size();  
  75.         for (int i = 0; i < nObservations; ++i)  
  76.         {  
  77.             problem.AddResidualBlock(new AutoDiffCostFunction<EllipsoidResidual, 1, 6>(  
  78.                 new EllipsoidResidual(m_data[i].x, m_data[i].y, m_data[i].z)),  
  79.                 NULL,  
  80.                 m_EllipsoidParameters);  
  81.         }  
  82.    
  83.         Solve(m_options, &problem, &m_summary);  
  84.         return true;  
  85.     }  
  86.    
  87.     bool                        m_bInitParameters;  
  88.     double                      m_EllipsoidParameters[6];  
  89.     std::vector<Point3D>        m_data;  
  90.     Solver::Options             m_options;  
  91.     Solver::Summary             m_summary;  
  92. };  
  93.    
  94. double* readFile(const char* szFilename,int& nCount)  
  95. {  
  96.     if(!szFilename)return NULL;  
  97.     FILE* fid=fopen(szFilename,"rt");  
  98.     if(!fid)return NULL;  
  99.    
  100.     nCount=0;  
  101.     fscanf(fid,"%d",&nCount);//读第一行数据,是行数,赋给nCount  
  102.    
  103.     int nSize=sizeof(double)*3*nCount;//根据行数分配大小,要取列数据所以是*nCount  
  104.     double* dbData=(double*)malloc(nSize);  
  105.     if(!dbData)return NULL;  
  106.     memset(dbData,0,nSize);//将申请的内存空间初始化为  
  107.    
  108.     double dbInvalid=0.;  
  109.     for(int i=0;i<nCount;i++)  
  110.     {  
  111.         double* dbTmp=dbData+3*i;  
  112.         fscanf(fid,"%lf %lf %lf",dbTmp,dbTmp+1,dbTmp+2);  
  113.     }  
  114.     fclose(fid);  
  115.    
  116.     return dbData;  
  117. }  
  118.    
  119. int main(int argc, char** argv)  
  120. {  
  121.     google::InitGoogleLogging(argv[0]);  
  122.    
  123.     EllipsoidFittingSolver efs;  
  124.     double dInit[6] = {0.5,0.5,0.5,0.5,0.5,0.5};  
  125.     memcpy(efs.m_EllipsoidParameters, dInit, sizeof(double)*6);  
  126.     efs.m_bInitParameters = true;  
  127.    
  128.     const char* pszFilename = "testdata2.txt";  
  129.     fprintf(stderr,"ReadFile begins.\n");  
  130.     int nCount=-1;  
  131.     double* dbSrcData= readFile(pszFilename, nCount);  
  132.     if(nCount<0)  
  133.     {  
  134.         fprintf(stderr,"ReadFile Error!\n");  
  135.         return -1;  
  136.     }  
  137.     else  
  138.         fprintf(stderr,"ReadFile Completed.!\n");  
  139.    
  140.     for (int i=0; i<nCount; i++)  
  141.     {  
  142.         Point3D pt;  
  143.         pt.x = dbSrcData[i*3+0];  
  144.         pt.y = dbSrcData[i*3+1];  
  145.         pt.z = dbSrcData[i*3+2];  
  146.    
  147.         efs.m_data.push_back(pt);  
  148.     }  
  149.      
  150.     free(dbSrcData);  
  151.    
  152.     if(efs.SolveParameters())  
  153.     {  
  154.         fprintf(stdout,"Solver Success!\n");  
  155.    
  156.         fprintf(stdout,"a=%lf b=%lf c=%lf\n",efs.m_EllipsoidParameters[0],efs.m_EllipsoidParameters[1],efs.m_EllipsoidParameters[2]);  
  157.         fprintf(stdout,"x0=%lf y0=%lf z0=%lf\n",efs.m_EllipsoidParameters[3],efs.m_EllipsoidParameters[4],efs.m_EllipsoidParameters[5]);  
  158.         fprintf(stdout,"%s\n",efs.m_summary.FullReport().c_str());  
  159.     }  
  160.     else  
  161.         fprintf(stdout,"Solver Failed!\n");  
  162.    
  163.     return 0;  
}

测试数据部分截图如下:

新建一个控制台应用程序,然后将第一篇的include和lib目录分别添加到工程中,同时配置引用的lib文件(RELEASE版本引用libglog.lib和ceres_r.lib,DEBUG版本引用libglog.lib和ceres_d.lib),然后编译即可。执行结果如下图所示。

红色区域为迭代过程,蓝色区域为计算的结果,最下面的为拟合报告。从蓝色的区域可以看出,拟合的abc的值为1,偏移量为0,和我们开始指定的球体方程一致。

从代码中可以看出,ceres-solver库不需要对非线性的方程进行求偏导数进行线性化然后再使用最小二乘求解系数。这大大方便了人们手动计算偏导数列系数矩阵,可以避免复杂的计算以及手工计算过程中出现的错误。

最后感谢@末末_happy提供的测试数据,感谢@AegeanSea87编写的测试代码。

测试数据部分截图如下:

新建一个控制台应用程序,然后将第一篇的include和lib目录分别添加到工程中,同时配置引用的lib文件(RELEASE版本引用libglog.lib和ceres_r.lib,DEBUG版本引用libglog.lib和ceres_d.lib),然后编译即可。执行结果如下图所示。

红色区域为迭代过程,蓝色区域为计算的结果,最下面的为拟合报告。从蓝色的区域可以看出,拟合的abc的值为1,偏移量为0,和我们开始指定的球体方程一致。

从代码中可以看出,ceres-solver库不需要对非线性的方程进行求偏导数进行线性化然后再使用最小二乘求解系数。这大大方便了人们手动计算偏导数列系数矩阵,可以避免复杂的计算以及手工计算过程中出现的错误。

最后感谢@末末_happy提供的测试数据,感谢@AegeanSea87编写的测试代码。
测试数据部分截图如下:

新建一个控制台应用程序,然后将第一篇的include和lib目录分别添加到工程中,同时配置引用的lib文件(RELEASE版本引用libglog.lib和ceres_r.lib,DEBUG版本引用libglog.lib和ceres_d.lib),然后编译即可。执行结果如下图所示。

红色区域为迭代过程,蓝色区域为计算的结果,最下面的为拟合报告。从蓝色的区域可以看出,拟合的abc的值为1,偏移量为0,和我们开始指定的球体方程一致。

从代码中可以看出,ceres-solver库不需要对非线性的方程进行求偏导数进行线性化然后再使用最小二乘求解系数。这大大方便了人们手动计算偏导数列系数矩阵,可以避免复杂的计算以及手工计算过程中出现的错误。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值