SLCM真是博大精深。之前简单的学习了OpenCV,主要是是使用python语言,现在学习SLAM需要使用C++,略难,但比起SLAM本身,不值一提。

     《视觉SLAM十四讲》里面的环境主要是在Ubuntu下的,我在虚拟机和JetsonTX2上分别试了一下,按照教程就可以。不过我觉着在Windows10下也能行,所以就搭建了一遍环境,运行完全没问题。其源码的3rdparty文件夹中提供了几个功能库,只需要把头文件和可能有的链接库等加进去就好了,完全可以通过编译,个别还是不行的话,把.cpp文件也用 #include 包含进去试试。后来在第五章时遇到点小问题,但最终还是跑起来了。

  安装PCL等主要参考博客如下: https://blog.csdn.net/weixin_41991128/article/details/83864713

      他用的visual studio 2017,我用的visual studio 2019,但是没发现啥区别,所有东西都按2017的装就可以了。

      就像里面介绍的,需要把那一大堆的.lib链接库都写进去。注意查看自己的链接库对应的版本,把后面的数字修改为自己的版本就可以了。而且里面有一个快速获取自己的链接库的做法,很方便。还要注意在 属性->c++目录 中的 可执行文件库、包含目录、引用目录、库目录 等选项中将所有的 .h .lib .dll 文件所在的文件夹的绝对目录都加进去。 而一旦报错:..无法解析的外部函数..  以我的经验来看都是链接库没加全造成的。报错:找不到 xx.dll xx.lib  xx.h等都是你的绝对路径没包含全的问题,在前面说的属性中对应的项目里面包含上这些地址好让编译器能找到就可以了。最后就是,包含完后还有问题的话,重新启动一次visual studio 再编译试试。

    另外,本测试需要支持opencv,我用的opencv4.1.0版本。因为使用了最基本的opencv操作,所以我觉得opencv3.x以上的版本都能正常运行。

     所有的处理都做完后,就可以测试代码了。源码->ch5->joinMap 中的代码直接复制粘贴,修改其中 psoe.txt 和两种图片的地址,然后就能编译了。可是编译后人家是在Ubuntu中显示点云的,在Windows10下命令没用,所以就自己加一个显示的函数。整个函数如下:

  1 #include <opencv2/opencv.hpp>
  2 #include<opencv2\core\core.hpp>  
  3 #include<opencv2\highgui\highgui.hpp> 
  4 
  5 #include <boost/format.hpp>  // for formating strings
  6 #include <pcl/visualization/cloud_viewer.h>
  7 #include <iostream>
  8 #include <pcl/io/io.h>
  9 #include <pcl/io/pcd_io.h>
 10 #include <pcl/surface/3rdparty/poisson4/vector.h>
 11 #include <pcl/point_types.h>
 12 
 13 
 14 int main()
 15 {
 16     pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);//创建一个共享指针并且实例化。注意两个PointXYZRGB要统一,最后显示时还有一个也要统一。当改为PointXYZ表示只输入XYZ坐标值,凸显改为黑白的
 17     
 18     //以下为十四讲中的源码
 19     //向量 vector 是一种对象实体, 能够容纳许多其他类型相同的元素, 因此又被称为容器。
 20     std::vector<cv::Mat> colorImgs, depthImgs;    // 彩色图和深度图
 21     std::vector<Eigen::Isometry3d, Eigen::aligned_allocator<Eigen::Isometry3d>> poses;         // 相机位姿
 22 
 23     std::ifstream fin("D:\\Mystudy\\opencv_forc\\mycode\\ConsoleApplication1\\ConsoleApplication1\\pose.txt");//注意改成自己存放pose.txt的地址
 24     if (!fin)
 25     {
 26         std::cerr << "请在有pose.txt的目录下运行此程序" << std::endl;
 27         return 1;
 28     }
 29 
 30     for (int i = 0; i < 5; i++)
 31     {
 32         boost::format fmt("D:/Mystudy/SLAM/视觉SLAM十四讲源码slambook-master/slambook-master/ch5/joinMap/%s/%d.%s"); //图像文件格式,
 33         colorImgs.push_back(cv::imread((fmt % "color" % (i + 1) % "png").str()));
 34         depthImgs.push_back(cv::imread((fmt % "depth" % (i + 1) % "pgm").str(), -1)); // 使用-1读取原始图像
 35 
 36         double data[7] = { 0 };
 37         for (auto& d : data)
 38             fin >> d;
 39         Eigen::Quaterniond q(data[6], data[3], data[4], data[5]);
 40         Eigen::Isometry3d T(q);
 41         T.pretranslate(Eigen::Vector3d(data[0], data[1], data[2]));
 42         poses.push_back(T);
 43     }
 44 
 45     // 计算点云并拼接
 46     // 相机内参 
 47     double cx = 325.5;
 48     double cy = 253.5;
 49     double fx = 518.0;
 50     double fy = 519.0;
 51     double depthScale = 1000.0;
 52 
 53     std::cout << "正在将图像转换为点云..." << std::endl;
 54 
 55     // 定义点云使用的格式:这里用的是XYZRGB
 56     typedef pcl::PointXYZRGB PointT;
 57     typedef pcl::PointCloud<PointT> PointCloud;
 58 
 59     // 新建一个点云
 60     PointCloud::Ptr pointCloud(new PointCloud);
 61     for (int i = 0; i < 5; i++)
 62     {
 63         std::cout << "转换图像中: " << i + 1 << std::endl;
 64         cv::Mat color = colorImgs[i];
 65         cv::Mat depth = depthImgs[i];
 66         Eigen::Isometry3d T = poses[i];
 67         for (int v = 0; v < color.rows; v++)
 68             for (int u = 0; u < color.cols; u++)
 69             {
 70                 unsigned int d = depth.ptr<unsigned short>(v)[u]; // 深度值
 71                 if (d == 0) continue; // 为0表示没有测量到
 72                 Eigen::Vector3d point;
 73                 point[2] = double(d) / depthScale;
 74                 point[0] = (u - cx) * point[2] / fx;
 75                 point[1] = (v - cy) * point[2] / fy;
 76                 Eigen::Vector3d pointWorld = T * point;
 77 
 78                 PointT p;
 79                 p.x = pointWorld[0];
 80                 p.y = pointWorld[1];
 81                 p.z = pointWorld[2];
 82                 p.b = color.data[v * color.step + u * color.channels()];
 83                 p.g = color.data[v * color.step + u * color.channels() + 1];
 84                 p.r = color.data[v * color.step + u * color.channels() + 2];
 85 
 86                 //std::cout << p.x<<" "<<p.y<<" "<<p.b<<" " << i + 1 << std::endl;
 87                 pointCloud->points.push_back(p);
 88             }
 89     }
 90 
 91     pointCloud->is_dense = false;
 92     std::cout << "点云共有" << pointCloud->size() << "个点." << std::endl;
 93     pcl::io::savePCDFileBinary("map.pcd", *pointCloud);
 94     
 95     //以下为点云显示代码
 96     if (pcl::io::loadPCDFile<pcl::PointXYZRGB>("D:\\Mystudy\\opencv_forc\\mycode\\ConsoleApplication1\\ConsoleApplication1\\map.pcd", *cloud) == -1)//*cloud,指针的内容是文件内容,记得标明点云类型<pcl::PointXYZ>
 97     {
 98         PCL_ERROR("请检查 xx.pcd 是否存在\n");//pcl有专门的报错函数PCL_ERROR
 99         return(-1);
100     }
101     pcl::visualization::CloudViewer viewer("pcd viewer");//给显示窗口命名,CloudViewer
102     viewer.showCloud(cloud);//定义要显示的对象,showCloud
103     //viewer.showCloud(pointCloud);//也可以直接显示上面编译好的点云图,不必保存再读出了
104     system("pause");//此处防止显示闪退
105     
106 
107     return 0;
108 }

 效果图就和在Ubuntu下运行的一样,能够鼠标拖动查看。

 

本文水平有限,内容很多词语由于知识水平问题不严谨或很离谱,但主要作为记录作用,能理解就好了,希望以后的自己和路过的大神对必要的错误提出批评与指点,对可笑的错误不要嘲笑,指出来我会改正的。 

 另外,转载使用请注明出处。                                                                                                

                                                                                                                                                         随梦,随心,随愿,恒执念,为梦执战,执战苍天!    ------------------执念执战

 

 

      

posted on 2019-06-17 13:39  执念执战  阅读(1315)  评论(0编辑  收藏  举报