Advertisement

jeston nano 下调用csi摄像头来运行orbslam2

阅读量:

1.首先对摄像头进行标定

​ 正确安装好摄像头之后,可以在终端下输入,摄像头就会开启

复制代码
    nvgstcapture-1.0


想关掉摄像头的话,直接在终端输入q再按回车;
​ 想获图片的话,在终端输入j再按回车,图片将保存当前目录下;

利用张正友标定法对相机进行标定:

​ 首先打印一张用于标定的棋盘格,然后按照上述方式,从不同角度不同具体拍摄棋盘格照片(大约20张左右),然后用Matlab工具箱进行标定。

参考:<>

2.重写一个接口,用来调用ORBSLAM2

​ 对于数据集上的示例,ORB-SLAM2 会首先读取数据集中的图像,再放到 SLAM 中处理。那么对于我们自己的摄像头,同样可以这样处理。所以最方便的方案是直接将我 们的程序作为一个新的可执行程序,加入到 ORB-SLAM2 工程中。

复制代码
    cd Examples/Monocular/
    vim myslam.cc
    vim myslam.yaml

在myslam.cc 中写入以下内容

复制代码
    // 该文件将打开你电脑的摄像头,并将图像传递给ORB-SLAM2进行定位
    
    // 需要opencv
    #include <opencv2/opencv.hpp>
    
    // ORB-SLAM的系统接口
    #include "System.h"
    
    #include <string>
    #include <chrono>   // for time stamp
    #include <iostream>
    
    using namespace std;
    
    
    
    int main(int argc, char **argv) {
    	//传入参数文件和词典文件
    string parameterFile = argv[1];
    string vocFile = argv[2];
    // 声明 ORB-SLAM2 系统
    ORB_SLAM2::System SLAM(vocFile, parameterFile, ORB_SLAM2::System::MONOCULAR, true);
    
    // 获取相机图像代码
    cv::VideoCapture cap(0);    // change to 1 if you want to use USB camera.
    
    // 分辨率设为640x480
    cap.set(CV_CAP_PROP_FRAME_WIDTH, 640);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
    
    // 记录系统时间
    auto start = chrono::system_clock::now();
    
    while (1) {
        cv::Mat frame;
        cap >> frame;   // 读取相机数据
        auto now = chrono::system_clock::now();
        auto timestamp = chrono::duration_cast<chrono::milliseconds>(now - start);
        SLAM.TrackMonocular(frame, double(timestamp.count())/1000.0);
    }
    
    return 0;
    }

在myslam.yaml 中写入自己标定的相机内参

复制代码
    %YAML:1.0
    
    #--------------------------------------------------------------------------------------------
    # Camera Parameters. Adjust them!
    #--------------------------------------------------------------------------------------------
    
    # Camera calibration and distortion parameters (OpenCV) 
    # 主要是在这里写入自己的标定参数,这个文件可以通过copy 数据集的yaml文件进行修改即可
    Camera.fx: 
    Camera.fy: 
    Camera.cx: 
    Camera.cy: 
    
    Camera.k1: 
    Camera.k2: 
    Camera.p1: 
    Camera.p2: 
    Camera.k3: 
    
    # Camera frames per second 
    Camera.fps: 30.0
    
    # Color order of the images (0: BGR, 1: RGB. It is ignored if images are grayscale)
    Camera.RGB: 0
    
    #--------------------------------------------------------------------------------------------
    # ORB Parameters
    #--------------------------------------------------------------------------------------------
    
    # ORB Extractor: Number of features per image
    ORBextractor.nFeatures: 1000
    
    # ORB Extractor: Scale factor between levels in the scale pyramid 	
    ORBextractor.scaleFactor: 1.2
    
    # ORB Extractor: Number of levels in the scale pyramid	
    ORBextractor.nLevels: 8
    
    # ORB Extractor: Fast threshold
    # Image is divided in a grid. At each cell FAST are extracted imposing a minimum response.
    # Firstly we impose iniThFAST. If no corners are detected we impose a lower value minThFAST
    # You can lower these values if your images have low contrast			
    ORBextractor.iniThFAST: 10
    ORBextractor.minThFAST: 5
    
    #--------------------------------------------------------------------------------------------
    # Viewer Parameters
    #--------------------------------------------------------------------------------------------
    Viewer.KeyFrameSize: 0.05
    Viewer.KeyFrameLineWidth: 1
    Viewer.GraphLineWidth: 0.9
    Viewer.PointSize: 2
    Viewer.CameraSize: 0.08
    Viewer.CameraLineWidth: 3
    Viewer.ViewpointX: 0
    Viewer.ViewpointY: -0.7
    Viewer.ViewpointZ: -1.8
    Viewer.ViewpointF: 500

并修改ORM_SLAM2文件夹下的CMakeLists.txt, 在最后一行加上

复制代码
    add_executable(myslam
    Examples/Monocular/myslam.cc)
    target_link_libraries(myslam ${PROJECT_NAME})

到这一步其实已经写好了接口,但是在jeston nano上是不能直接使用cv::VideoCapture cap(0)的,这个时候编译也会通过,但是实际调用时会出现摄像头显示为纯灰色,不能正确工作。板载csi摄像头的开启,需要使用到GSTREAMER,如果opencv编译的时候没有开启该选项,那么是不能打开摄像头的。

3.编译opencv+GStreamer

安装依赖项

复制代码
    sudo apt-get install -y build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
    sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
    sudo apt-get install -y python2.7-dev python3.6-dev python-dev python-numpy python3-numpy
    sudo apt-get install -y libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
    sudo apt-get install -y libv4l-dev v4l-utils qv4l2 v4l2ucp
    sudo apt-get install -y curl

下载opencv源码,注意这里同时需要opencv_contrib-3.4.0文件夹,将其与opencv-3.4.0并列放在一起(注意版本号的对应)

对源码进行编译:

复制代码
    cd opencv-3.4.0/
    sudo mkdir build
    cd build/
    cmake -D WITH_CUDA=ON -D CUDA_ARCH_BIN="5.3" -D CUDA_ARCH_PTX="" -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-3.4.0/modules -D WITH_GSTREAMER=ON -D WITH_LIBV4L=ON -D BUILD_opencv_python2=ON -D BUILD_opencv_python3=ON -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_EXAMPLES=OFF -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..
    make -j3
    sudo make install
编译时出现了libGL.so的链接问题:

1.搜索libGL.so文件路径: 比如,本机中路径为:/usr/lib/libGL.so

2.建立symlink: sudo ln -s /usr/lib/libGL.so.1 /usr/lib/aarch64-linux-gnu/libGL.so

(之所以链接到libGL.so.1而不是libGL.so可能是为了便于区分)

3.如果出现错误: ln: failed to create symbolic link ‘/usr/lib/aarch64-linux-gnu/libGL.so‘ : File exists

则删除已有链接: sudo rm /usr/lib/aarch64-linux-gnu/libGL.so

4.重新执行步骤2建立symlink

参考:http://www.mamicode.com/info-detail-2779089.html
板载摄像头的测试:

github有一个写好的测试脚本

复制代码
    git clone https://github.com/JetsonHacksNano/CSI-Camera.git
    cd CSI-Camera
    python3 simple_camera.py
参考:https://www.squirrelzoo.com/archives/1805

同时测试一下c++的支持

复制代码
    g++ -std=c++11 -Wall -I/usr/lib/opencv simple_camera.cpp -L/usr/lib -lopencv_core -lopencv_highgui -lopencv_videoio -o simple_camera
    ./simple_camera

可以看到在c++代码中成功开启了csi摄像头,让我们去查看一下simple_camera.cpp代码

复制代码
    // simple_camera.cpp
    // MIT License
    // Copyright (c) 2019 JetsonHacks
    // See LICENSE for OpenCV license and additional information
    // Using a CSI camera (such as the Raspberry Pi Version 2) connected to a 
    // NVIDIA Jetson Nano Developer Kit using OpenCV
    // Drivers for the camera and OpenCV are included in the base image
    
    #include <iostream>
    #include <opencv2/opencv.hpp>
    #include <opencv2/videoio.hpp>
    #include <opencv2/highgui.hpp>
    
    std::string gstreamer_pipeline (int capture_width, int capture_height, int display_width, int display_height, int framerate, int flip_method) {
    return "nvarguscamerasrc ! video/x-raw(memory:NVMM), width=(int)" + std::to_string(capture_width) + ", height=(int)" +
           std::to_string(capture_height) + ", format=(string)NV12, framerate=(fraction)" + std::to_string(framerate) +
           "/1 ! nvvidconv flip-method=" + std::to_string(flip_method) + " ! video/x-raw, width=(int)" + std::to_string(display_width) + ", height=(int)" +
           std::to_string(display_height) + ", format=(string)BGRx ! videoconvert ! video/x-raw, format=(string)BGR ! appsink";
    }
    
    int main()
    {
    int capture_width = 1280 ;
    int capture_height = 720 ;
    int display_width = 1280 ;
    int display_height = 720 ;
    int framerate = 60 ;
    int flip_method = 0 ;
    
    std::string pipeline = gstreamer_pipeline(capture_width,
    	capture_height,
    	display_width,
    	display_height,
    	framerate,
    	flip_method);
    std::cout << "Using pipeline: \n\t" << pipeline << "\n";
     
    cv::VideoCapture cap(pipeline, cv::CAP_GSTREAMER);
    if(!cap.isOpened()) {
    	std::cout<<"Failed to open camera."<<std::endl;
    	return (-1);
    }
    
    cv::namedWindow("CSI Camera", cv::WINDOW_AUTOSIZE);
    cv::Mat img;
    
    std::cout << "Hit ESC to exit" << "\n" ;
    while(true)
    {
    	if (!cap.read(img)) {
    		std::cout<<"Capture read error"<<std::endl;
    		break;
    	}
    	
    	cv::imshow("CSI Camera",img);
    	int keycode = cv::waitKey(30) & 0xff ; 
        if (keycode == 27) break ;
    }
    
    cap.release();
    cv::destroyAllWindows() ;
    return 0;
    }

可以看到主要是写了一个pipeline,然后使用了cv::VideoCapture cap(pipeline, cv::CAP_GSTREAMER);

这就给我们提供了一个思路,用同样的方式对之前的myslam.cc进行修改;

4.编译好之后重写接口

重写myslam.cc

复制代码
    #include <opencv2/opencv.hpp>
    #include "System.h"
    
    #include <string>
    #include <chrono>
    #include <iostream>
    #include <opencv2/videoio.hpp>
    #include <opencv2/highgui.hpp>
    
    
    using namespace std;
    using namespace cv;
    
    std::string gstreamer_pipeline (int capture_width, int capture_height, int display_width, int display_height, int framerate, int flip_method) {
        return "nvarguscamerasrc ! video/x-raw(memory:NVMM), width=(int)" + std::to_string(capture_width) + ", height=(int)" +
               std::to_string(capture_height) + ", format=(string)NV12, framerate=(fraction)" + std::to_string(framerate) +
               "/1 ! nvvidconv flip-method=" + std::to_string(flip_method) + " ! video/x-raw, width=(int)" + std::to_string(display_width) + ", height = (int)" +
               std::to_string(display_height) + ", format=(string)BGRx ! videoconvert ! video/x-raw, format=(string)BGR ! appsink";
    }
    
    
    int main(int argc,char** argv)
    {
    string parameterFile = argv[1];
    string vocFile = argv[2];
    
    ORB_SLAM2::System SLAM(vocFile,parameterFile,ORB_SLAM2::System::MONOCULAR,true);
    
    		int capture_width = 640 ;
    	int capture_height = 480 ;
        int display_width = 640 ;
        int display_height = 480 ;
        int framerate = 30 ;
        int flip_method = 0 ;
    
        std::string pipeline = gstreamer_pipeline(capture_width,
        capture_height,
        display_width,
        display_height,
        framerate,
        flip_method);
        std::cout << "Using pipeline: \n\t" << pipeline << "\n";
    
    
    VideoCapture cap(pipeline,cv::CAP_GSTREAMER);
    if(!cap.isOpened())
    {
        std::cout << "failed to open cam" << endl;
        return -1;
    }
    
    auto start = chrono::system_clock::now();
    
    while(1)
    {
        Mat frame;
        cap.read(frame);
        if(frame.empty()){
            cerr << "error ,blank frame." << endl;
            break;
        }
        auto now = chrono::system_clock::now();
        auto timestamp = chrono::duration_cast<chrono::milliseconds>(now - start);
        SLAM.TrackMonocular(frame,double(timestamp.count())/1000.0);
    }
    cap.release();
    SLAM.Shutdown();
    return 0;
    }

然后再进行重新编译即可。

6.运行测试

复制代码
    ./Examples/Monocular/myslam Examples/Monocular/myslam.yaml Vocabulary/ORBvoc.txt
在这里插入图片描述

全部评论 (0)

还没有任何评论哟~