第九讲 设计前端 3D-2D位姿计算(一)
2017-05-25 17:16
316 查看
注:代码引用高翔的slambook,感谢他的开源奉献,祝贺他毕业答辩顺利圆满。
检测特征点,计算描述符,通过判断特征点对应的深度值的有效性进一步筛选.
2.读取第二帧的彩色图,检测特征点,计算描述符。
3.通过比较描述符的汉明距离来寻找最佳匹配。
4.构建3d 2d的数组,通过solvePnPRansac函数获得相机位姿
代码如下
下一步计划,加入BA优化,加入ICP估计位姿选项
设计最简单的基于3D-2D的位姿计算
1.读取第一帧的深度图和彩色图(进行对齐操作,并通过相机内参进行矫正),进行如下操作:检测特征点,计算描述符,通过判断特征点对应的深度值的有效性进一步筛选.
2.读取第二帧的彩色图,检测特征点,计算描述符。
3.通过比较描述符的汉明距离来寻找最佳匹配。
4.构建3d 2d的数组,通过solvePnPRansac函数获得相机位姿
代码如下
cv::Ptr<cv::ORB> orb_; // orb detector and computer orb_ = cv::ORB::create ( 500, 1.2, 8 ); vector<cv::KeyPoint> keypoints1; // keypoints in current frame Mat descriptors1; vector<cv::Point3f> pts_3d_valid; Mat descriptors1_valid; vector<cv::DMatch> feature_matches_; Mat K = ( Mat_<double>(3,3) << 517.3, 0, 325.1, 0, 516.5, 249.7, 0, 0, 1 ); Mat img_1 =imread("./rgb/3.026000.png"); Mat img_1depth=imread("./depth/3.026000.png",-1); imshow("rgb",img_1); imshow("depth",img_1depth); waitKey(1); orb_->detect ( img_1, keypoints1 ); cout<<"keypoints1.size is "<<keypoints1.size()<<endl; orb_->compute ( img_1, keypoints1, descriptors1 ); cout<<"descriptors1.size is "<<descriptors1.size()<<endl; descriptors1_valid = Mat(); ofstream out("3Dsetpoint_valid_choice.txt",ios::out); out<<"K camera intrinsic is "<<K<<endl; out<<"keypoints1.size() is "<<keypoints1.size()<<endl; for ( size_t i=0; i<keypoints1.size(); i++ ) { int x = cvRound(keypoints1[i].pt.x); int y = cvRound(keypoints1[i].pt.y); double d =0;//出错的问题在于求取深度值误判为-1,而不是先判断邻域内是否有真值存在 ushort temp= img_1depth.ptr<ushort>(y)[x]; if ( temp!=0 ) { d= double(temp/5000.0); } else { // check the nearby points int dx[4] = {-1,0,1,0}; int dy[4] = {0,-1,0,1}; for ( int i=0; i<4; i++ ) { temp = img_1depth.ptr<ushort>( y+dy[i] )[x+dx[i]]; if ( temp!=0 ) { d= double(temp/5000.0); } } } if(d==0) d=-1; Vector3d p_cam = Vector3d((keypoints1[i].pt.x-K.at<double>(0,2))*d/K.at<double>(0,0), (keypoints1[i].pt.y-K.at<double>(1,2))*d/K.at<double>(1,1), d ); if ( d > 0) { Vector3d p_cam = Vector3d((keypoints1[i].pt.x-K.at<double>(0,2))*d/K.at<double>(0,0), (keypoints1[i].pt.y-K.at<double>(1,2))*d/K.at<double>(1,1), d ); pts_3d_valid.push_back( cv::Point3f( p_cam(0,0), p_cam(1,0), p_cam(2,0) )); descriptors1_valid.push_back(descriptors1.row(i)); } } cout<<"pts_3d_valid.size is "<<pts_3d_valid.size()<<endl; cout<<"descriptors1_valid.size is "<<descriptors1_valid.size()<<endl; cv::Ptr<cv::ORB> orb_2; // orb detector and computer orb_2 = cv::ORB::create ( 500, 1.2, 8 ); vector<cv::KeyPoint> keypoints2; // keypoints in current frame Mat descriptors2; // descriptor in current frame Mat img_2=imread("./3.183000.png",-1); orb_2->detect ( img_2, keypoints2 ); orb_2->compute ( img_2, keypoints2, descriptors2 ); cout<<"descriptors2.size is "<<descriptors2.size()<<endl; // match desp_ref and desp_curr, use OpenCV's brute force match vector<cv::DMatch> matches; cv::BFMatcher matcher ( cv::NORM_HAMMING ); matcher.match ( descriptors1_valid, descriptors2, matches ); cout<<"descriptors1_valid.size is "<<descriptors1_valid.size()<<endl; cout<<"descriptors2.size is "<<descriptors2.size()<<endl; cout<<"matches.size is "<<matches.size()<<endl; // select the best matches float min_dis = std::min_element ( matches.begin(), matches.end(), [] ( const cv::DMatch& m1, const cv::DMatch& m2 ) { return m1.distance < m2.distance; } )->distance; feature_matches_.clear(); for ( cv::DMatch& m : matches ) { if ( m.distance < max<float> ( min_dis*2, 30.0 ) ) { feature_matches_.push_back(m); } } cout<<"good matches: "<<feature_matches_.size()<<endl; //construct the 3d 2d observations vector<cv::Point3f> pts3d; vector<cv::Point2f> pts2d; for ( cv::DMatch m:feature_matches_ ) { pts3d.push_back( pts_3d_valid[m.queryIdx] ); pts2d.push_back( keypoints2[m.trainIdx].pt ); } cout<<"pts3d.size "<<pts3d.size()<<endl; cout<<"pts2d.size "<<pts2d.size()<<endl; Mat rvec, tvec, inliers; cv::solvePnPRansac( pts3d, pts2d, K, Mat(), rvec, tvec, false, 100, 4.0, 0.99, inliers ); int num_inliers_ = inliers.rows; cout<<"pnp inliers: "<<num_inliers_<<endl; SE3 T_c_r_estimated_ = SE3( Sophus::SO3(rvec.at<double>(0,0), rvec.at<double>(1,0), rvec.at<double>(2,0)), Vector3d( tvec.at<double>(0,0), tvec.at<double>(1,0), tvec.at<double>(2,0)) ); cout<<"Sophus::SO3(rvec.at<double>(0,0), rvec.at<double>(1,0), rvec.at<double>(2,0)) "<<Sophus::SO3(rvec.at<double>(0,0), rvec.at<double>(1,0), rvec.at<double>(2,0))<<endl; cout<<"Vector3d( tvec.at<double>(0,0), tvec.at<double>(1,0), tvec.at<double>(2,0)) "<<Vector3d( tvec.at<double>(0,0), tvec.at<double>(1,0), tvec.at<double>(2,0))<<endl; ofstream kout("out.txt",ios::out); if(!kout.eof()) { kout<<"pts3d.size "<<pts3d.size()<<endl; kout<<"pts2d.size "<<pts2d.size()<<endl; kout<<"K camera intrinsic is \n"<<K<<endl; kout<<"\npts_3d_ref_ "<<" pts2d is "<<endl; for(int i=0;i<pts3d.size();i++) { kout<<pts3d[i]<<" "<<pts2d[i]<<endl; } kout<<"T_c_r_estimated_ is \n"<<T_c_r_estimated_<<endl; }
下一步计划,加入BA优化,加入ICP估计位姿选项
相关文章推荐
- 一种Flash页游前端3D转2D显示技术——PV2D, 颠覆传统吧!
- 软件开发全套视频教程汇总(javaSE,javaEE,linux,android开发,C# ,web前端,大数据云计算,数据挖掘,web前端,php开发,UI设计,C++开发,3D视频)
- 对于2D/3D空间的元素坐标计算 (Matlab)
- 2D和3D空间中计算两点之间的距离
- opencv中3D点根据相机参数投影成2D点+solvePnP函数计算相机姿态+2D坐标到3D+相机参数calibration(标定与配准,求得深度彩色相机的内参与外参,再进行配准)
- 基础篇:1)时代的发展与结构设计—3d与2d的设计变化(夸夸其谈中)
- Neurons字幕组 | 2分钟看AI通过2D照片设计出面部3D模型(附论文下载)
- Agent Dash游戏设计之美:如何用2D打造3D体验?
- 计算几何之求取三维维点集的凸包/ 凸多边形包围盒(2D、3D点集)
- Mathcad 是一种工程计算软件,主要运算功能:代数运算、线性代数、微积分、符号计算、2D和3D图表、动画、函数、程序编写、逻辑运算、变量与单位的定义和计算等。
- 设计自己的软渲染器2-构建3D世界到2D屏幕显示的基本变换
- WEB前端 | H5基础——(2)2D/3D形变、过渡及渐变
- IMSI.Design.TurboCAD.Designer.v14-ISO 1CD(多功能的2D/3D图形设计软件)
- 改进版 对于2D/3D空间的元素坐标计算 (Matlab)
- unity3d 3d场景中人物的2d头像/血条位置计算
- 特征提取、匹配以及位姿计算(2D-2D)--参考视觉SLAM十四讲7.4
- Mathcad 是一种工程计算软件,主要运算功能:代数运算、线性代数、微积分、符号计算、2D和3D图表、动画、函数、程序编写、逻辑运算、变量与单位的定义和计算等。
- 一个表达式计算案例的设计和实现!〈转贴〉
- 3D引擎设计和架构
- Draw2D设计--3. LightweightSystem设计和实现剖析(2)