視覺slam十四講ch6曲線擬合 代碼注釋(筆記版)

  1 #include <opencv2/core/core.hpp>
  2 #include <ceres/ceres.h>
  3 #include <chrono>
  4 
  5 using namespace std;
  6 
  7 // 代價函數的計算模型
  8 struct CURVE_FITTING_COST
  9 {
 10     CURVE_FITTING_COST ( double x, double y ) : _x ( x ), _y ( y ) {}
 11     // 殘差的計算
 12     template <typename T>
 13     bool operator() (
 14         const T* const abc,     // 模型參數,有3維 當沒有必要分類的時候 就用一個數組來存儲未知的系數,方便管理,而不是設3個變量,之后在()重載函數的形式參數個數變為3個
 15         T* residual ) const     // 殘差
 16     {
 17         residual[0] = T ( _y ) - ceres::exp ( abc[0]*T ( _x ) *T ( _x ) + abc[1]*T ( _x ) + abc[2] ); // y-exp(ax^2+bx+c)
 18         return true;
 19     }
 20     const double _x, _y;    // x,y數據
 21 };
 22 
 23 int main ( int argc, char** argv )
 24 {
 25     double a=1.0, b=2.0, c=1.0;         // 真實參數值
 26     int N=100;                          // 數據點
 27     double w_sigma=1.0;                 // 噪聲Sigma值(根號下方差)
 28     cv::RNG rng;                        // OpenCV隨機數產生器
 29     double abc[3] = {0.8,2.1,0.9};      // abc參數的估計值 (修改初始值 下面求解迭代過程會不同)
 30 
 31     vector<double> x_data, y_data;      // 數據
 32 
 33     /*生成符合曲線的樣本*/
 34     cout<<"generating data: "<<endl;   //下面是從真實的曲線中取得樣本數據
 35     for ( int i=0; i<N; i++ )
 36     {
 37         double x = i/100.0;
 38         x_data.push_back ( x );
 39         y_data.push_back (
 40             exp ( a*x*x + b*x + c ) + rng.gaussian ( w_sigma )
 41         );
 42         //cout<<x_data[i]<<" "<<y_data[i]<<endl;//輸出生成數據
 43     }
 44 
 45     // 構建最小二乘問題
 46     ceres::Problem problem;
 47     for ( int i=0; i<N; i++ )
 48     {
 49         /* 第一個參數 CostFunction* : 描述最小二乘的基本形式即代價函數 例如書上的116頁fi(.)的形式
 50          * 第二個參數 LossFunction* : 描述核函數的形式 例如書上的ρi(.)
 51          * 第三個參數 double* :       待估計參數(用數組存儲)
 52          * 這里僅僅重載了三個參數的函數,如果上面的double abc[3]改為三個double a=0 ,b=0,c = 0;
 53          * 此時AddResidualBlock函數的參數除了前面的CostFunction LossFunction 外后面就必須加上三個參數 分別輸入&a,&b,&c
 54          * 那么此時下面的 ceres::AutoDiffCostFunction<>模板參數就變為了 <CURVE_FITTING_COST,1,1,1,1>后面三個1代表有幾類未知參數
 55          * 我們修改為了a b c三個變量,所以這里代表了3類,之后需要在自己寫的CURVE_FITTING_COST類中的operator()函數中,
 56          * 把形式參數變為了const T* const a, const T* const b, const T* const c ,T* residual
 57          * 上面修改的方法與本例程實際上一樣,只不過修改的這種方式顯得亂,實際上我們在用的時候,一般都是殘差種類有幾個,那么后面的分類 就分幾類
 58          * 比如后面講的重投影誤差,此事就分兩類 一類是相機9維變量,一類是點的3維變量,然而殘差項變為了2維
 59          *
 60          * (1): 修改后的寫法(當然自己定義的代價函數要對應修改重載函數的形式參數,對應修改內部的殘差的計算):
 61          *      ceres::CostFunction* cost_function
 62          *              = new ceres::AutoDiffCostFunction<CURVE_FITTING_COST, 1, 1 ,1 ,1>(
 63          *                  new CURVE_FITTING_COST ( x_data[i], y_data[i] ) );
 64          *      problem.AddResidualBlock(cost_function,nullptr,&a,&b,&c);
 65          * 修改后的代價函數的計算模型:
 66          *   struct CURVE_FITTING_COST
 67          *   {
 68          *       CURVE_FITTING_COST ( double x, double y ) : _x ( x ), _y ( y ) {}
 69          *       // 殘差的計算
 70          *       template <typename T>
 71          *       bool operator() (
 72          *          const T* const a,
 73          *          const T* const b,
 74          *          const T* const c,
 75          *          T* residual   ) const     // 殘差
 76          *       {
 77          *           residual[0] = T ( _y ) - ceres::exp ( a[0]*T ( _x ) *T ( _x ) + b[0]*T ( _x ) + c[0] ); // y-exp(ax^2+bx+c)
 78          *           return true;
 79          *       }
 80          *       const double _x, _y;    // x,y數據
 81          *   };//代價類結束
 82          *
 83          *
 84          * (2): 本例程下面的語句通常拆開來寫(看起來方便些):
 85          * ceres::CostFunction* cost_function
 86          *              = new ceres::AutoDiffCostFunction<CURVE_FITTING_COST, 1, 3>(
 87          *                  new CURVE_FITTING_COST ( x_data[i], y_data[i] ) );
 88          * problem.AddResidualBlock(cost_function,nullptr,abc)
 89          * */
 90         problem.AddResidualBlock (     // 向問題中添加誤差項
 91         // 使用自動求導,模板參數:誤差類型,Dimension of residual(輸出維度 表示有幾類殘差,本例程中就一類殘差項目,所以為1),輸入維度,維數要與前面struct中一致
 92                 /*這里1 代表*/
 93             new ceres::AutoDiffCostFunction<CURVE_FITTING_COST, 1, 3> ( 
 94                 new CURVE_FITTING_COST ( x_data[i], y_data[i] )// x_data[i], y_data[i] 代表輸入的獲得的試驗數據
 95             ),
 96             nullptr,            // 核函數,這里不使用,為空  這里是LossFunction的位置
 97             abc                 // 待估計參數3維
 98         );
 99     }
100 
101     // 配置求解器ceres::Solver (是一個非線性最小二乘的求解器)
102     ceres::Solver::Options options;     // 這里有很多配置項可以填Options類嵌入在Solver類中 ,在Options類中可以設置關于求解器的參數
103     options.linear_solver_type = ceres::DENSE_QR;  // 增量方程如何求解 這里的linear_solver_type 是一個Linear_solver_type的枚舉類型的變量
104     options.minimizer_progress_to_stdout = true;   // 為真時 內部錯誤輸出到cout,我們可以看到錯誤的地方,默認情況下,會輸出到日志文件中保存
105 
106     ceres::Solver::Summary summary;                // 優化信息
107     chrono::steady_clock::time_point t1 = chrono::steady_clock::now();//記錄求解時間間隔
108     //cout<<endl<<"求解前....."<<endl;
109     /*下面函數需要3個參數:
110      * 1、 const Solver::Options& options <----> optione
111      * 2、 Problem* problem               <----> &problem
112      * 3、 Solver::Summary* summary       <----> &summart (即使默認的參數也需要定義該變量 )
113      * 這個函數會輸出一些迭代的信息。
114      * */
115     ceres::Solve ( options, &problem, &summary );  // 開始優化
116     //cout<<endl<<"求解后....."<<endl;
117     chrono::steady_clock::time_point t2 = chrono::steady_clock::now();
118     chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>( t2-t1 );
119     cout<<"solve time cost = "<<time_used.count()<<" seconds. "<<endl;
120 
121     // 輸出結果
122     // BriefReport() : A brief one line description of the state of the solver after termination.
123     cout<<summary.BriefReport() <<endl;
124     cout<<"estimated a,b,c = ";
125     /*auto a:abc  或者下面的方式都可以*/
126     for ( auto &a:abc ) cout<<a<<" ";
127     cout<<endl;
128 
129     return 0;
130 }

?

轉載于:https://www.cnblogs.com/newneul/p/8407365.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/252397.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/252397.shtml
英文地址,請注明出處:http://en.pswp.cn/news/252397.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Dojo 如何測試 widget

測試 dojo/framework/src/testing/README.mdcommit 84e254725f41d60f624ab5ad38fe82e15b6348a2 用于測試和斷言 Dojo 部件期望的虛擬 DOM 和行為的簡單 API。 測試 Features harness APICustom Comparatorsselectors harness.expect harness.expectPartial harness.triggerharn…

python中將四元數轉換為旋轉矩陣

在制作bundlefusion時,想測試TUM數據集,并且將groundtruth寫入到數據集中,TUM中給定的groundtruth中的旋轉是使用四元數表示的,而bundlefusion中需要SE3的形式,所以我需要首先將四元數轉換為旋轉矩陣,然后再將其與平移向量合并在一起,因為我之前關于生成bundlefusion數據集寫了…

js -- 時間轉年月日

/*** 時間轉年月日* param sdate 開始的時間* param edate 結束的時間* returns {*}*/function day2ymrStr2(sdate, edate) {var day2ymrStr "";var date1 new Date(edate);var date2 new Date(sdate);var y 0, m 0, d 0;var y1 date1.getFullYear();var m1 …

iOS sha1加密算法

最近在項目中使用到了網絡請求簽名認證的方法&#xff0c;于是在網上找關于OC sha1加密的方法&#xff0c;很快找到了一個大眾使用的封裝好的方法&#xff0c;以下代碼便是 首先需要添加頭文件 #import<CommonCrypto/CommonDigest.h> 然后直接使用下面的方法就可以了 //s…

Linux開發5款實用工具推薦

今天安利給大家5款實用的Linux開發工具&#xff0c;希望對大家工作效率的提升有所幫助。容器放眼于現實&#xff0c;現在已經是容器的時代了。容器既及其容易部署&#xff0c;又可以方便地構建開發環境。如果你針對的是特定的平臺的開發&#xff0c;將開發流程所需要的各種工具…

TUM數據集制作BundleFusion數據集

BundleFusion的數據集中,在生成.sens文件之前,包括彩色圖,深度圖和一個位姿文件,并且這個pose文件中的位姿態是有變化的,所以我懷疑,推測,在這個pose文件中可以寫入groundtruth的位姿,然后在重建的時候就按照傳入的位姿進行計算.為了測試一下效果,我從TUM數據集開始入手,這個數…

Linq查詢datatable的記錄集合

通過linq查詢datatable數據集合滿足條件的數據集 1.首先定義查詢字段的變量&#xff0c;比方深度 string strDepth查詢深度的值&#xff1b; var dataRows from datarow in dataTable(須要查詢的datatable數據集).AsEnumerable() where …

Java 概述和編程基礎

First of all&#xff0c;Java概述&#xff1a; 類是Java程序設計的基石和基本單元&#xff1b; main()方法是程序的入口&#xff0c;它是共有的、靜態的&#xff0c;參數String[] args表示一個字符串數組可以傳入該程序&#xff0c;用來傳遞外部數據以初始化程序。   計算機…

19、Fragment

一、Fragment 1.1、fragment介紹 fragment的出現是為了同時適應手機和平板&#xff0c;可以將其看做Activity的組成部分&#xff0c;甚至Activity界面完全由不同的Fragment組成&#xff0c;它擁有自己的生命 周期和接收、處理用戶的事件&#xff0c;更為重要的是&#xff0c;可…

喜好:

不喜歡吃&#xff1a;一瓣瓣的蘑菇、海帶、豆腐皮、 不喜歡喝&#xff1a;魚湯&#xff1b; 不喜歡吃&#xff1a;山楂片、法式小面包&#xff08;軟軟的&#xff09;、果凍、 不喜歡喝&#xff1a;對飲料無感、不喜歡脈動、可樂雪碧等少量還行、 喜歡&#xff1a;啃骨頭、排骨…

將TUM數據集制作成BundleFusion數據集

在上一篇文章中,我寫到了如何將TUM數據生成BundleFusion所需要的數據集,生成的數據集如下圖中所示.并且是將每一組數據的groundtruth.txt中的位姿數據寫如到這里的pose文件中,作為每一幀圖像的先驗位姿. 今天我便將生成的數據集轉換為了.sens格式,然后運行bundlefusion算法,第…

每一次突破都是一種進步

一直以來&#xff0c;我接觸一門新技術&#xff0c;都是先看開發文檔&#xff0c;了解了這個技術是做什么的&#xff0c;能做什么。但是不知道怎么起步&#xff0c;也不敢貿然動手。我的解決辦法是看視頻&#xff0c;看別人怎么使用&#xff0c;跟著別人做&#xff0c;然后聽別…

mysql盲注學習-1

mysql: 1.left() //left()函數 left(a,b)從左側截取a,的b位 2.mid() //mid()函數 參數 描述 column_name 必需。要提取字符的字段。 start 必需。規定開始位置&#xff08;起始值是 1&#xff09;。 length 可選。要返回的字符數。如果省略&#xff0c;則 MID() 函數…

二分學習筆記

寫在前面 二分是一種常用且非常精妙的算法&#xff0c;常常是我們解決問題的突破口。二分的基本用途是在單調序列或單調函數中做查找。因此當問題的答案具有單調性時&#xff0c;就可以通過二分把求解轉化為判定。進一步地&#xff0c;我們還可以通過三分法解決單調函數的極值以…

解析.sens數據集

python腳本在下面網址中https://github.com/ScanNet/ScanNet/tree/master/SensReader/python 一定要使用python2運行此腳本. 使用指令如下 python reader.py --filename /media/yunlei/YL/DATASETS/ICL_DATABASE/lr_kt1/living_room_traj1n_frei_png.sens --output_path /me…

ConcurrentHashMap 解讀

初始化&#xff1a; 問題&#xff1a;如何當且僅只有一個線程初始化table 1 private final Node<K,V>[] initTable() {2 Node<K,V>[] tab; int sc;3 while ((tab table) null || tab.length 0) {4 if ((sc sizeCtl) < 0)5 …

XML Schema 基本結構

<?xml version1.0?> <Schema name"cangchuSchema" metamodelVersion"4.0"><PhysicalSchema><Table name"highway_toll"><Key><Column name"uid"/></Key></Table><Table name&qu…

關于系統自帶 .NET Framework 版本的說明

系統自帶版本&#xff1a; Windows XP (SP3) .NET Framework 1.1Windows 7 (SP1) .NET Framework 3.5.1Windows 8.1 .NET Framework 4.5.1Windows 10 (1507) .NET Framework 4.6Windows 10 (1511) .NET Framework 4.6.1Windows 10 (1607) .NET Framework 4.6.2Windows 10 (1703…

BundleFusion那些事兒

背景&#xff1a;前面幾篇博客中寫了很多關于BundleFusion的東西&#xff0c;主要包括bundlefusion的論文閱讀筆記&#xff0c;.sens數據集的生成等&#xff0c;經過最近幾天的工作&#xff0c;我對bundlefusion又有了新的技術積累&#xff0c;在這里整理一下&#xff0c;也算是…

問題:圖片怎么保存到數據庫, 以及怎么把圖片從數據庫中取出來使用?(已解決)...

簡單&#xff0c;不保存圖片到數據庫&#xff0c;而是圖片的路徑。 也就是說&#xff0c;先把圖片下載到服務器的指定目錄下&#xff0c;然后&#xff0c;在把相對的路徑保存到數據庫中。 如果下次獲取圖片&#xff0c;就訪問數據庫&#xff0c;獲取圖片路徑&#xff0c;然后根…