“一起做RGB_D SLAM”学习笔记(123)

一直在蒙着头跑程序,之前只会复制粘贴,真正从头开始才发现之前根本没理解,现将学习记录如下:

PS:此篇仅为高博一起做RGB_D SLAM的学习记录,感谢高博~

1.1写CMakeLists.txt时:

  • 我们前面建立的这几个分立的文件夹,本身其实是没有任何联系的,要想产生联系(变成有关系分工的一个工程),就是通过CMakeLists.txt创建联系的。
CMAKE_MINIMUM_REQUIRED( VERSION 2.8 ) #设定版本
PROJECT( slam ) #设定工程名
SET( CMAKE_CXX_COMPILER "g++") #设定编译器
	
#设定可执行二进制文件的目录
SET( EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) 
	
#设定存放编译出来的库文件的目录
SET( LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) 
#并且把该目录设为连接目录
LINK_DIRECTORIES( ${PROJECT_SOURCE_DIR}/lib)
	
#设定头文件目录
INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/include)
	
#增加子文件夹,也就是进入源代码文件夹继续构建;lib bin文件夹中无
ADD_SUBDIRECTORY( ${PROJECT_SOURCE_DIR}/src)
  • 二进制就是可以直接运行的程序啦,库文件呢,就是为这些二进制提供函数的啦。有main函数的代码可以编译成二进制,其他的则编译成库文件。链接时,把库文件链到二进制上,就可以运行啦。
  • 上文中提到的,跳至src子文件夹中继续构建,所以在src中还需要有一个CMakeLists.txt(Cmake实践中说,需要为任何子目录建立一个 CMakeLists.txt。这里的子目录也就是在上层CMakeLists.txt中添加的子目录,而不是指工程中任何一个子目录,比如承接库文件和可执行文件的bin和lib文件夹中就没有)。  
  • 每级文件夹中的CMakeLists.txt主要负责对所在文件夹中的文件或文件夹进行操作,比如项目根目录RGBD-SLAM中的,串联各个目录,设定输出位置和头文件引用目录等工作。src中的CMakeLists.txt就只操作src中的main.cpp,用其添加一个可执行文件。 参考:RGBD-SLAM学习1
  • 上级CMakeLists.txt添加的子目录,子目录中必须要有CMakeLists.txt!

1.2 make编译main函数时报错

/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_line): relocation 0 has invalid symbol index 2
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o:在函数‘_start’中:
(.text+0x20):对‘main’未定义的引用
collect2: error: ld returned 1 exit status
make[2]: *** [../bin/main] 错误 1
make[1]: *** [src/CMakeFiles/main.dir/all] 错误 2
make: *** [all] 错误 2

解决:重新打了一遍main.cpp中的int main


2.1  Kinect(或其他rgb-d相机)里直接采到的RGB图和深度图存在的问题:

  • 有一些时差(约几到十几个毫秒)。这个时差的存在,会产生“RGB图已经向右转了,怎么深度图还没转”的感觉。
  • 光圈中心未对齐。因为深度毕竟是靠另一个相机获取的,所以深度传感器和彩色传感器参数可能不一致。
  • 深度图里有很多“洞”。因为RGB-D相机不是万能的,它有一个探测距离的限制啦!太远或太近的东西都是看不见的。关于这些“洞”,我们暂时睁一只眼闭一只眼,不去理它。以后我们也可以靠双边bayes滤波器去填这些洞。但是!这是RGB-D相机本身的局限性。软件算法顶多给它修修补补,并不能完全弥补它的缺陷。

2.2 data文件夹放置位置

//这样的话,date文件夹应在build文件夹下(或项目文件夹)
rgb=cv::imread("./data/rgb.png");
depth=cv::imread("./data/depth.png",-1);
//生成的.pcd文件也在build文件夹下
pcl::io::savePCDFile( "./pointcloud.pcd", *cloud );

可改为

//重新编译运行,则在项目文件夹中
rgb=cv::imread("../data/rgb.png");
depth=cv::imread("../data/depth.png",-1);
pcl::io::savePCDFile( "../pointcloud.pcd", *cloud );

2.3遍历深度图--先列后行!!!

 for(int m=0;m<depth.rows;m++)
	for(int n=0;n<depth.cols;n++)
  • 我们使用OpenCV的imread函数读取图片。在OpenCV2里,图像是以矩阵(cv::MAt)作为基本的数据结构。Mat结构既可以帮你管理内存、像素信息,还支持一些常见的矩阵运算,是非常方便的结构。
  • 彩色图像含有R,G,B三个通道,每个通道占8个bit(也就是unsigned char),故称为8UC3(8位unsigend char, 3通道)结构。而深度图则是单通道的图像,每个像素由16个bit组成(也就是C++里的unsigned short),像素的值代表该点离传感器的距离。通常1000的值代表1米,所以我们把camera_factor设置成1000. 这样,深度图里每个像素点的读数除以1000,就是它离你的真实距离了。

注意:换行符为endl而非end1 !!!

######运行#######

cd ./slam
cd ./build
cmake ..
make

cd ..
./bin/generate_pointcloud
pcl_viewer pointcloud.pcd


3.1 CMakeLists.txt添加书写

##在lib中生成了一个名为libslambase.a的静态库文件,注意,这个库的名称叫slambase(add_library中定义的名字),所以后面使用时,链接此库的时候,就是用它的库名slambase
ADD_LIBRARY( slambase slamBase.cpp )
TARGET_LINK_LIBRARIES( slambase
    ${OpenCV_LIBS} 
    ${PCL_LIBRARIES} )

# 增加特征点匹配的可执行文件
ADD_EXECUTABLE(detectfeatures detectFeatures.cpp )
# 链接上我们自己写的库
target_link_libraries(detectfeatures slambase )

  • 一个程序编译链接之后,并不一定都生成可执行程序,有的是生成了库,以备其他程序调用。所以这两个有点并行的意味。首先,一个库要有头文件和库文件.
  • CMakelist中,命令名字是不区分大小写的,而参数和变量是大小写相关的。在 src/CMakeLists.txt 中加入以下几行,将 slamBase.cpp 编译成一个库,供将来调用.

3.2 OpenCV未安装nonfree模块以至于SIFT算法不能正常使用引发的错误(变为ORB匹配算法可跳过)

fatal error: opencv2/nonfree/nonfree.hpp: 没有那个文件或目录
 #include <opencv2/nonfree/nonfree.hpp>

安装&使用opencv的nonfree模块

3.3 由SIFT算法到ORB算法的一些改动(参考:RGBD-SLAM学习3

// 声明特征提取器与描述子提取器
// 如果使用 sift, surf ,之前要初始化nonfree模块
// cv::initModule_nonfree();
// _detector = cv::FeatureDetector::create( "SIFT" );
// _descriptor = cv::DescriptorExtractor::create( "SIFT" );
detector = cv::FeatureDetector::create("ORB");
descriptor = cv::DescriptorExtractor::create("ORB");

cv::FlannBasedMatcher matcher;  //这是高博的
//auto matcher = cv::DescriptorMatcher::create ( "BruteForce-Hamming" );//匹配器matcher的创建要随动ORB,改成Brute Force match(编译未通过)

//求解PnP时,solvePnPRansac函数增加了confidence参数:算法产生有用结果的置信系数。具体改动就是增加一个参数值(这里就用函数默认值0.99好了):
cv::solvePnPRansac( pts_obj, pts_img, cameraMatrix, cv::Mat(), rvec, tvec, false, 100, 1.0, 0.99, inliers );

######运行#######

cd ..
./bin/detectfeatures

显示:keypoints<任意键>matches<任意键>good matches<任意键>inlier matches<任意键>关闭所有窗口

输出:

Key points of two images: 500, 500

Find total 500 matches.

min dis = 16.1555
good matches=70
inliers: 31
R=[-0.02381573964575079; 0.03008252220205883; 0.02061441187646476]
t=[0.02775634088144215; 0.008762443617165343; 0.01745294408849403]

猜你喜欢

转载自blog.csdn.net/qq_40313712/article/details/80871742
今日推荐