系統:Ubuntu 14
Kintinuous + Elastic Fusion代碼來源:https://github.com/mp3guy
準備工作
安裝git
- sudo apt-get install git
- git config --global user.name 你的git username
- git config --global user.email 你的郵箱
直接在ubuntu軟件中心下載安裝,但是配置Elastic Fusion需要升級到3.2,否則自帶的是2.8
參考:http://askubuntu.com/questions/610291/how-to-install-cmake-3-2-on-ubuntu-14-04
- sudo apt-get install build-essential
- wget http://www.cmake.org/files/v3.2/cmake-3.2.2.tar.gz
- tar xf cmake-3.2.2.tar.gz
- cd cmake-3.2.2
- ./configure
- make
- sudo make install
如果提示找不到bin/cmake,那麼sudo apt-get upgrade就可以了
配置Kinect運行環境(一個參考,實際上我並沒有用Kinect跑,最後用的是Xtion)
參考:http://www.cc.gatech.edu/grads/a/ahuaman3/docs/tutorials/software/build/perception.html
OpenNI2安裝:
- sudo apt-get install g++
- sudo apt-get install python
- sudo apt-get install libusb-1.0-0-dev
- sudo apt-get install libudev-dev
- sudo apt-get install openjdk-6-jdk
- sudo apt-get install freeglut3-dev
- sudo apt-get install graphviz
- sudo apt-get install doxygen
- git clone https://github.com/occipital/OpenNI2
- cd OpenNI2
- make
在其中加入:
- UBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02b0", MODE:="0666", OWNER:="root", GROUP:="video"
- SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02ad", MODE:="0666", OWNER:="root", GROUP:="video"
- SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02ae", MODE:="0666", OWNER:="root", GROUP:="video"
- SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02c2", MODE:="0666", OWNER:="root", GROUP:="video"
- SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02be", MODE:="0666", OWNER:="root", GROUP:="video"
- SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02bf", MODE:="0666", OWNER:="root", GROUP:="video"
- git clone https://github.com/OpenKinect/libfreenect.git
- cd libfreenect
- mkdir build; cd build
- cmake .. -DBUILD_OPENNI2_DRIVER=ON
- make
- cp -L lib/OpenNI2-FreenectDriver/libFreenectDriver.so ${OPENNI2_DIR}/Bin/x64-Release/OpenNI2/Drivers #將驅動拷貝到OpenNI2的解壓文件夾下,OPENNI2_DIR:OpenNI2的解壓文件夾
插上kinect後,使用lsusb命令查看確保有以下三個:
Xbot camera
Xbot motor
Xbot audio
安裝成功檢查:
- cd ${OPENNI2_DIR}/Bin/x64-Release/
- ./NiViewer
- git clone https://github.com/mp3guy/Kintinuous
1.新系統:
找到build.sh,在屬性中設置爲可執行
./build.sh
等待配置成功
2.非新系統:
安裝CUDA:
下載deb文件 https://developer.nvidia.com/cuda-downloads查看是否成功運行cuda- sudo dpkg -i cuda-repo-ubuntu1404_7.5-18_amd64.deb
- sudo apt-get update
- sudo apt-get install cuda
- sudo reboot
- cd /usr/local/cuda/samples
- sudo make all -j4
- cd /usr/local/cuda/samples/bin/x86_64/linux/release
- sudo ./deviceQuery
CUDA Device Query (Runtime API) version (CUDART static linking)
Detected 1 CUDA Capable device(s)我在這裏遇到了一定問題,找了很久,發現是Secure Boot沒關掉,關掉之後就好了。解決的流程如下:
運行deviceQuery:no capable device
嘗試解決:
1.懷疑是內核問題
add in: GRUB_CMDLINE_LINUX_DEFAULT with: pci=nocrs pci=realloc
依然:no capable device
2.裝最新的nvidia 367
新問題:CUDA driver version is insufficient for CUDA runtime version
3.查看當前的kernel版本
kernel:3.19.0-65-generic
4.查看一些參數
sudo dpkg --list | grep nvidia
lspci | grep -i nvidia 設備裏的確有nvidia顯卡
lsmod 發現video一覽只有i915_bpo,說明nvidia獨顯並沒有被啓用
sudo modprobe nvidia-367 手動啓用nvidia顯卡,提示ERROR: could not insert 'nvidia_367': Required key not available
終於找到問題:不是顯卡驅動沒裝好,而是無法啓動顯卡(被BIOS禁了?)
5.裝回nvidia 352
sudo apt-get remove --purge nvidia-*
(***提示cmake-qt-gui依賴cmake 2.8出錯,卸載cmake-qt-gui。卸載後cmake命令沒出錯,其他情況會不會出錯有待觀察)
sudo add-apt-repository ppa:xorg-edgers/ppa -y
sudo apt-get update
sudo apt-get install nvidia-352
6.查看安裝的版本
sudo dpkg --list | grep nvidia
ii nvidia-352 352.93-0ubuntu1 amd64 NVIDIA binary driver - version 352.93
ii nvidia-modprobe 352.93-0ubuntu1 amd64 Load the NVIDIA kernel driver and create device files
ii nvidia-opencl-icd-352 352.93-0ubuntu1 amd64 NVIDIA OpenCL ICD
ii nvidia-prime 0.6.2 amd64 Tools to enable NVIDIA's Prime
ii nvidia-settings 367.35-0ubuntu0~gpu14.04.1 amd64 Tool for configuring the NVIDIA graphics driver
安裝正確,運行devieQuery依然提示no device found,回到原點
7.現在的問題:
sudo modprobe nvidia-352 手動啓用nvidia顯卡,提示ERROR: could not insert 'nvidia_352': Required key not available
網上給出的解決方法:turn off the secure boot feature of the motherboard
8.嘗試解決:開機F12,secure boot勾選爲disable,legacy勾選
sudo modprobe nvidia-352 成功!
nvidia-settings 顯示獨顯成功!
deviceQuery 檢測到顯卡!應該可以了!
9.新問題:kinect無法連接了。。。(之前是可以的)
lsusb 能看到XBOX的三個設備
從頭重新配置,發現有幾個依賴包沒有安裝(可能之前哪一步把他卸載了)
sudo apt-get install openjdk-6-jdk
sudo apt-get install graphviz
sudo apt-get install doxygen
之後NiViewer可以正常運行了
安裝依賴項:
- sudo apt-get install -y cmake-qt-gui git build-essential libusb-1.0-0-dev libudev-dev openjdk-7-jdk freeglut3-dev python-vtk libvtk-java libglew-dev cuda-7-5 libsuitesparse-dev
安裝pcl:
- sudo add-apt-repository ppa:v-launchpad-jochen-sprickerhof-de/pcl
- sudo apt-get update
- sudo apt-get install libpcl-all
安裝opengl:
- sudo apt-get install build-essential
- sudo apt-get install libgl1-mesa-dev
- sudo apt-get install libgl1-mesa-dev
- sudo apt-get install libglu1-mesa-dev
- sudo apt-get install freeglut3-dev
安裝opencv:
(不可以直接在ubuntu的apt-get裏面獲取opencv,因爲ubuntu提供的opencv沒有nonfree模塊)
下載http://opencv.org/downloads.html
- sudo apt-get install build-essential libgtk2.0-dev libjpeg-dev libtiff4-dev libjasper-dev libopenexr-dev cmake python-dev python-numpy python-tk libtbb-dev libeigen2-dev yasm libfaac-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev libx264-dev libqt4-dev libqt4-opengl-dev sphinx-common texlive-latex-extra libv4l-dev libdc1394-22-dev libavcodec-dev libavformat-dev libswscale-dev
- unzip opencv-2.4.9.zip
- cd opencv-2.4.9
- mkdir build
- cd build
- cmake -D BUILD_NEW_PYTHON_SUPPORT=OFF -D WITH_OPENCL=OFF -D WITH_OPENMP=ON -D INSTALL_C_EXAMPLES=OFF -D BUILD_DOCS=OFF -D BUILD_EXAMPLES=OFF -D WITH_QT=OFF -D WITH_OPENGL=OFF -D WITH_VTK=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_TESTS=OFF -D WITH_CUDA=OFF -D BUILD_opencv_gpu=OFF ..
- make
- sudo make install
安裝Dlib:
- sudo apt-get install libboost-dev
- git clone https://github.com/dorian3d/DLib
- cd DLib/build
- cmake ..
- make
- sudo make install
安裝DBoW2:
- git clone https://github.com/dorian3d/DBoW2#dbow2
- cd DBoW2/build
- cmake ..
- make
- sudo make install
安裝DLoopDetector:
- git clone https://github.com/dorian3d/DLoopDetector
- cd DLoopDetector/build
- cmake ..
- make
- sudo make install
安裝iSAM:
- svn co https://svn.csail.mit.edu/isam
- cd isam
- make
安裝Pangolin:
- sudo apt-get install libglew-dev
- sudo apt-get install libboost-dev libboost-thread-dev libboost-filesystem-dev
- sudo apt-get install libpython2.7-dev
- sudo apt-get install ffmpeg libavcodec-dev libavutil-dev libavformat-dev libswscale-dev
- sudo apt-get install libdc1394-22-dev libraw1394-dev
- sudo apt-get install libjpeg-dev libpng12-dev libtiff5-dev libopenexr-dev
- git clone https://github.com/stevenlovegrove/Pangolin
- cd Pangolin/build
- cmake -DCPP11_NO_BOOST=1 ..
- make -j
運行Kintinuous:
作者的一些說明:
The GUI (Kintinuous) can take a bunch of parameters when launching it from the command line. They are as follows:
-c : Loads a camera calibration file specified by a depth_intrinsics matrix in OpenCV format.
-l : Processes the specified .klg log file.
-v : Loads DBoW vocabulary file.
-p : Loads ground truth poses to use instead of estimated pose.
-gpu : Sets which GPU should be used by CUDA.
-n : Number of frames to process.
-t : Voxel threshold for volume shifting (default 14).
-cw : Removes voxels below this threshold when extracting slices (default 8).
-lt : Disallow loop closures within this time period of the last (default 30s).
-s : Size of the fusion volume (default 6m).
-dg : Rate of pose sampling for deformation (default 0.8m).
-il : Inlier threshold for RANSAC (default 0.35).
-it : Residual threshold for pose graph optimisation (default 10).
-sm : Static mode (disable volume shifting).
-f : Flip RGB/BGR.
-od : Perform online deformation (required for loop closure).
-m : Enable mesh generation.
-no : Disable overlap of extracted slices.
-nos : Remove overlap when saving map.
-r : Use RGB tracking only.
-ri : Use combined ICP+RGB tracking.
-d : Enable dynamic cube positioning.
-dc : Disable color weighting by angle.
-fl : Subsample pose graph for faster loop closure.
-fod : Enable fast odometry.
以上所有配置以後就可以正常運行kintinuous了,運行的命令可以看上面的作者說明,比如:
- ./Kintinuous
默認從華碩Xtion中讀取圖像,如果沒有Xtion則會報錯找不到設備
沒有話說Xtion的可以試試作者給的幾個log,在原網址上有下載。
使用log的運行方法如下:
- ./Kintinuous -s 7 -v ../vocab.yml.gz -l loop.klg -ri -fl -od
# author has provided a sample dataset loop.klg which you can run easily with Kintinuous
配置ElasticFusion
準備工作和相關的依賴項包括開源包的配置方法和KIntinous一樣,只需要額外安裝開源包openni2
安裝OpenNI2:- git clone https://github.com/occipital/OpenNI2.git
- cd OpenNI2
- make -j8
- cd ..
生成 ./ElasticFusion
注意源碼裏有三個項目,Core、GPUTest和GUI
如果要使用作者的程序,則需要把三個項目安裝順序依次配置成功
- cd ../Core
- mkdir build
- cd build
- cmake -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-7.5 ../src
- make -j8
- cd ../../GPUTest
- mkdir build
- cd build
- cmake -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-7.5 ../src
- make -j8
- cd ../../GUI
- mkdir build
- cd build
- cmake -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-7.5 ../src
- make -j8
- cd ../../myfusion
- mkdir build
- cd build
- cmake -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-7.5 ../src
- make -j8
直接調用以下命令,默認從華碩Xtion中獲取圖像並開始三位重建
- ./ElasticFusion
也可以使用參數控制,一些Elastci Fusion的運行參數如下:
- -cal : Loads a camera calibration file specified as fx fy cx cy. 載入相機參數(默認參數爲華碩Xtion的參數)
- -l : Processes the specified .klg log file. 不使用攝像頭讀取,使用log文件模擬相機的圖像採集過程
- -p : Loads ground truth poses to use instead of estimated pose. 讀取ground truth的位姿來作爲三位重建的依據之一(默認會自動估計當前的位置,如果傳入ground truth的位姿則直接使用傳入的位姿)
- -c : Surfel confidence threshold (default 10). Surfel的信任閾值
- -d : Cutoff distance for depth processing (default 3m). 多少距離以上的深度數據視爲無用數據(單位mm,默認爲3000,即3m)
- -i : Relative ICP/RGB tracking weight (default 10). ICP/RGB的tracking閾值
- -ie : Local loop closure residual threshold (default 5e-05).
- -ic : Local loop closure inlier threshold (default 35000).
- -cv : Local loop closure covariance threshold (default 1e-05).
- -pt : Global loop closure photometric threshold (default 115).
- -ft : Fern encoding threshold (default 0.3095). 關鍵幀編碼閾值
- -t : Time window length (default 200).
- -s : Frames to skip at start of log. 如果使用log,跳過初始幀的數目
- -e : Cut off frame of log.
- -f : Flip RGB/BGR.
- -icl : Enable this if using the ICL-NUIM dataset (flips normals to account for negative focal length on that data).
- -o : Open loop mode.
- -rl : Enable relocalisation.
- -fs : Frame skip if processing a log to sim
- ulate real-time.
- -q : Quit when finished a log.
- -fo : Fast odometry (single level pyramid).
- -nso : Disables SO(3) pre-alignment in tracking.
- -r : Rewind and loop log forever.
- -ftf : Do frame-to-frame RGB tracking.
- -sc : Showcase mode (minimal GUI).
使用Elastic Fusion的CoreAPI
作者還提供了使用他的Core作爲基礎庫的方法。
首先編譯Core項目
- cd ../Core
- mkdir build
- cd build
- cmake -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-7.5 ../src
- make -j8
然後在CMakelist.txt中加入
- find_package(efusion REQUIRED)
- include_directories(${EFUSION_INCLUDE_DIR})
- target_link_libraries(MyProject ${EFUSION_LIBRARY})
在頭文件中加入
- #include <ElasticFusion.h>
初始化
- Resolution::getInstance(640, 480); #圖像大小
- Intrinsics::getInstance(528, 528, 320, 240); #相機參數
- pangolin::Params windowParams; #GUI窗口
- windowParams.Set("SAMPLE_BUFFERS", 0);
- windowParams.Set("SAMPLES", 0);
- pangolin::CreateWindowAndBind("Main", width, height, windowParams);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
使用封裝好的ElasticFusion類,可以精確定義每一個參數
默認的構造函數
- ElasticFusion eFusion;
精確定義每一個參數後調用構建函數
- float confidence = 10.0f; //fusion的confidence閾值
- float depth = 3.0f; //去掉depth大於某個閾值的幀
- float icp = 10.0f; //icp的閾值
- float icpErrThresh = 5e-05; //icp錯誤閾值
- float covThresh = 1e-05;
- float photoThresh = 115;
- float fernThresh = 0.3095f; //新fern的閾值
- int timeDelta = 200;
- int icpCountThresh = 35000;
- bool openLoop = 0; //open loop模式:不開啓
- bool iclnuim = 0; //使用icl dataset:不使用
- bool reloc = 0; //重定位模式:不開啓
- bool fastOdom = 0; //Fast odometry (single level pyramid) mode :不開啓
- bool so3 = 1; //SO(3) pre-alignment in tracking:開啓
- bool frameToFrameRGB = 0; //只做rgb圖像的tracking:不開啓
- int timestamp = 0;
- std::string savefilename = "test";
- ElasticFusion eFusion(openLoop ? std::numeric_limits<int>::max() / 2 : timeDelta,icpCountThresh, icpErrThresh, covThresh, !openLoop, iclnuim, reloc,photoThresh, confidence, depth, icp, fastOdom, fernThresh, so3,frameToFrameRGB, savefilename);
處理輸入幀:
- eFusion.processFrame(rgb, depth, timestamp, currentPose, weightMultiplier);
可選參數1:currentPose——先驗的current pose,比如傳入了標定好的ground truth三維座標數據,則可以用上一時刻和這一時刻的三位座標來估計相機姿態
- Eigen::Matrix4f * currentPose;//當前的位姿
- currentPose = new Eigen::Matrix4f;
- currentPose->setIdentity();
- *currentPose = groundTruthOdometry->getTransformation(timestamp); }
- eFusion.processFrame(rgb, depth, timestamp, currentPose, weightMultiplier);
- delete currentPose;
可選參數2:weightMultiplier (full frame fusion weight)——默認爲1.f 可以自己調整,比如針對前面跳過的幀數對參數進行調整
- float weightMultiplier = framesToSkip + 1;
- eFusion.processFrame(rgb, depth, timestamp, currentPose, weightMultiplier);
一個簡單的使用CoreAPI的程序:
- #include "myfusion_base.h"
- int main() {
- //圖像的尺寸以及相機參數
- int width = 640;
- int height = 480;
- int camera_fx = 528;
- int camera_fy = 528;
- int camera_cx = 320;
- int camera_cy = 240;
- cout << "Initializing ..." << endl;
- Resolution::getInstance(width, height);
- Intrinsics::getInstance(camera_fx, camera_fy, camera_cx, camera_cy);
- cout << "Initializing done." << endl;
- cout << "Setting parameters..." << endl;
- float confidence = 10.0f; //fusion的confidence閾值
- float depth = 3.0f; //去掉depth大於某個閾值的幀
- float icp = 10.0f; //icp的閾值
- float icpErrThresh = 5e-05; //icp錯誤閾值
- float covThresh = 1e-05;
- float photoThresh = 115;
- float fernThresh = 0.3095f; //新fern的閾值
- int timeDelta = 200;
- int icpCountThresh = 35000;
- //int start = 1;
- //int end = std::numeric_limits<unsigned short>::max(); //Funny bound, since we predict times in this format really!
- bool openLoop = 0; //open loop模式:不開啓
- bool iclnuim = 0; //使用icl dataset:不使用
- bool reloc = 0; //重定位模式:先做重建,不開啓重定位
- bool fastOdom = 0; //Fast odometry (single level pyramid) mode :不開啓
- bool so3 = 1; //SO(3) pre-alignment in tracking:開啓
- bool frameToFrameRGB = 0; //只做rgb圖像的tracking:不開啓
- int timestamp = 0;
- std::string savefilename = "test";
- cout << "Setting parameters done." << endl;
- cout << "Building eFusion..." << endl;
- pangolin::Params windowParams;
- windowParams.Set("SAMPLE_BUFFERS", 0);
- windowParams.Set("SAMPLES", 0);
- pangolin::CreateWindowAndBind("Main", width, height, windowParams);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
- ElasticFusion eFusion(
- openLoop ? std::numeric_limits<int>::max() / 2 : timeDelta,
- icpCountThresh, icpErrThresh, covThresh, !openLoop, iclnuim, reloc,
- photoThresh, confidence, depth, icp, fastOdom, fernThresh, so3,
- frameToFrameRGB, savefilename);
- cout << "Building eFusion done" << endl;
- //待處理文件的位置和下標
- std::string filedir = "../pic/";
- int file_start = 1;
- int file_end = 782;
- vector<Eigen::Matrix4f> pose;
- //三位重建
- for (int file_ptr = file_start; file_ptr <= file_end; file_ptr = file_ptr +1) {
- cout << "Processing frame : "<<file_ptr << " ..."<<endl;
- FRAME f = readFrame(file_ptr, filedir);
- unsigned char * rgb = f.rgb;
- unsigned short * dep = f.dep;
- eFusion.processFrame(rgb, dep, timestamp);
- Eigen::Matrix4f currPose = eFusion.getCurrPose();
- pose.push_back(currPose);
- cout << "current pose is : " << endl<<currPose << endl;
- }
- cout << "Processing frames done." << endl<<endl;
- cout<<"Saving Elastic-Fusion model..."<<endl;
- cout<<"Saving Elastic-Fusion model done"<<endl<<endl;
- /*
- //查看處理的結果
- int time = eFusion.getTick();//查看此時eFusion的系統時間
- cout<<"time : "<<time<<endl;
- Ferns keyfern = eFusion.getFerns();//關鍵幀dataset
- int ld_num = eFusion.getDeforms();//局部deformations的數量
- Deformation ld = eFusion.getLocalDeformation();//局部deformation圖
- int gd_num = eFusion.getFernDeforms();//全局deformations的數量
- GlobalModel gm = eFusion.getGlobalModel();//全局deformation model:
- int CloudPoint_num = eFusion.globalModel.lastCount(); //點雲的點數量
- Eigen::Vector4f * mapData = eFusion.globalModel.downloadMap(); //點雲圖
- for (unsigned int i = 0; i < CloudPoint_num; i++) {
- Eigen::Vector4f pos = mapData[(i * 3) + 0];
- if (pos[3] > eFusion.confidenceThreshold) {
- //這是個有效的頂點,validCount++;
- }
- }//調用點雲中的每一個點
- */
- cout << "saving cloud points..." << endl;
- eFusion.savePly(); //保存當前的點雲圖至ply
- cout << "cloud point has saved to " << savefilename << ".ply" << endl;
- return 0;
- }
- FRAME readFrame(int index, std::string filedir) {
- FRAME f;
- // 文件目錄
- string rgbDir = filedir + "rgb/";
- string depthDir = filedir + "depth/";
- // 文件後綴
- string rgbExt = ".png";
- string depthExt = ".png";
- stringstream ss;
- // 讀rgb圖
- ss << rgbDir << index << rgbExt;
- string filename;
- ss >> filename;
- f.rgb_mat = cv::imread(filename);
- f.rgb = f.rgb_mat.data;
- // 讀depth圖
- ss.clear();
- filename.clear();
- ss << depthDir << index << depthExt;
- ss >> filename;
- f.dep_mat = cv::imread(filename, -1);
- f.dep = (unsigned short*) f.dep_mat.data;
- f.frameID = index;
- return f;
- }