SLCM真是博大精深。以前簡單的學習了OpenCV,主要是是使用python語言,如今學習SLAM須要使用C++,略難,但比起SLAM自己,不值一提。python
《視覺SLAM十四講》裏面的環境主要是在Ubuntu下的,我在虛擬機和JetsonTX2上分別試了一下,按照教程就能夠。不過我覺着在Windows10下也能行,因此就搭建了一遍環境,運行徹底沒問題。其源碼的3rdparty文件夾中提供了幾個功能庫,只須要把頭文件和可能有的連接庫等加進去就行了,徹底能夠經過編譯,個別仍是不行的話,把.cpp文件也用 #include 包含進去試試。後來在第五章時遇到點小問題,但最終仍是跑起來了。ios
安裝PCL等主要參考博客以下: https://blog.csdn.net/weixin_41991128/article/details/83864713c++
他用的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下命令沒用,因此就本身加一個顯示的函數。整個函數以下:ui
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下運行的同樣,可以鼠標拖動查看。spa
本文水平有限,內容不少詞語因爲知識水平問題不嚴謹或很離譜,但主要做爲記錄做用,能理解就行了,但願之後的本身和路過的大神對必要的錯誤提出批評與指點,對好笑的錯誤不要嘲笑,指出來我會改正的。 .net
另外,轉載使用請註明出處。 3d
隨夢,隨心,隨願,恆執念,爲夢執戰,執戰蒼天! ------------------執念執戰