Kinect2.0 + libfreenect2 + iai_kinect2 + NiTE2 + ROS + Ubuntu18.04

最近入手一个Kinect2.0,在Ubuntu18.04中进行驱动安装测试以及深度图像的保存。



1. 驱动安装与测试

Kinect 2.0 在Windows系统中是有官方提供的现成的驱动程序可以使用的,并且有对应的SDK可以辅助开发人员进行应用开发,但在Linux系统中,就需要在Github上找对应的开源驱动代码,并且进行安装调试。

Kinect 2.0 的开源驱动包位于:https://github.com/OpenKinect

在其内有两类驱动,

  1. 一类是 libfreenect 用于Kinect1.0的驱动;
  2. 二类是 libfreenect2 用于二代Kinect2.0的驱动

在本文中用的是Kinect2.0驱动程序,以下内容是针对Ubuntu18.04系统

  • 安装依赖:
    sudo apt-get install build-essential cmake pkg-config libturbojpeg libturbojpeg0-dev libjpeg-turbo8-dev mesa-common-dev freeglut3-dev libxrandr-dev libxi-dev

  • clone下载kinect2.0驱动包libfreenect2:

cd ~/Compile/Kinect2/ 
git clone https://github.com/OpenKinect/libfreenect2.git  
cd libfreenect2
  • 编译
mkdir build && cd build  
cmake ..
make -j
sudo make install

编译报错

cmake编译报错

解决: 安装sudo apt-get install libturbojpeg0-dev
安装libturbojpeg0-dev库


make -j编译
sudo make install安装到/usr/local/中
  • 设置udev规则文件
    sudo cp ../platform/linux/udev/90-kinect2.rules /etc/udev/rules.d/

lsusb命令查看kinect2.0是否识别出来,其中045e:02c4045e:02d8045e:02d9就是微软的kinect2.0

  • 测试驱动是否安装成功

Kinnect2.0重新插拔后,运行测试./bin/Protonect


2.OpenCV通过libfreenect2显示Kinect2深度图与彩色图

编程实现通过Ubuntu读取Kinect的数据,同样需要借助于驱动包所提供的库函数,下面就详细解释如何在程序中实现数据的获取与处理。

找一个工作区间workspace进行测试
touch CMakeLists.txt kinect2test.cpp

kinect2test.cpp

#include <libfreenect2/libfreenect2.hpp>
#include <libfreenect2/frame_listener_impl.h>
#include <libfreenect2/registration.h>
#include <libfreenect2/packet_pipeline.h>
#include <libfreenect2/logger.h> //用于输出log日志信息

#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/objdetect.hpp>
#include <iostream>
#include <cstdlib>
using namespace std;
using namespace cv;
enum Processor { cl, gl, cpu };

int main(int argc, char *argv[])
{
        // 定义全局变量方便调用
        libfreenect2::Freenect2 freenect2;
        libfreenect2::Freenect2Device *dev = nullptr;
        libfreenect2::PacketPipeline *pipeline = nullptr;
         //初始化Kinect2.0
        if(freenect2.enumerateDevices() == 0)
        {
                std::cout << "no device connected!" << std::endl;
                return -1;
        }
       string serial = freenect2.getDefaultDeviceSerialNumber();
        if(serial == "")  return -1;
        cout<<"The serial number is :"<<serial<<endl;


        int depthProcessor = Processor::cl;
        if(depthProcessor == Processor::cpu)
        {
                if(!pipeline)
                {
                     //! [pipeline]
                    pipeline = new libfreenect2::CpuPacketPipeline();
                    //! [pipeline]
                }
        } 
        else 
                if (depthProcessor == Processor::gl) 
                {
                        #ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT
                        if(!pipeline)
                                pipeline = new libfreenect2::OpenGLPacketPipeline();
                        #else
                                std::cout << "OpenGL pipeline is not supported!" << std::endl;
                        #endif
                } 
                else 
                        if (depthProcessor == Processor::cl) 
                        {
                                #ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT
                                 if(!pipeline)
                                        pipeline = new libfreenect2::OpenCLPacketPipeline();
                                #else
                                        std::cout << "OpenCL pipeline is not supported!" << std::endl;
                                #endif
                        }

       if(pipeline)
        {
        //! [open]
                dev = freenect2.openDevice(serial, pipeline);
        //! [open]
        } 
        else 
        {
                dev = freenect2.openDevice(serial);
         }
        if(dev == 0)
        {
                std::cout << "failure opening device!" << std::endl;
                return -1;
         }

        //! [listeners]
        libfreenect2::SyncMultiFrameListener listener(libfreenect2::Frame::Color |libfreenect2::Frame::Depth |libfreenect2::Frame::Ir);
        libfreenect2::FrameMap frames;
        dev->setColorFrameListener(&listener);
        dev->setIrAndDepthFrameListener(&listener);
        //! [listeners]

        //! [start]
        dev->start();
        std::cout << "device serial: " << dev->getSerialNumber() << std::endl;
        std::cout << "device firmware: " << dev->getFirmwareVersion() << std::endl;
        //! [start]
        libfreenect2::Registration* registration = new libfreenect2::Registration(dev->getIrCameraParams(), dev->getColorCameraParams());
        libfreenect2::Frame undistorted(512, 424, 4), registered(512, 424, 4), depth2rgb(1920, 1080 + 2, 4); 
        Mat rgbmat, depthmat, irmat, depthmatUndistorted, rgbd, rgbd2;

    while(!(waitKey(1)==27))
    {
        listener.waitForNewFrame(frames);
        libfreenect2::Frame *rgb = frames[libfreenect2::Frame::Color];
        libfreenect2::Frame *ir = frames[libfreenect2::Frame::Ir];
        libfreenect2::Frame *depth = frames[libfreenect2::Frame::Depth];
        //! [loop start]

        Mat rgbmat = cv::Mat(rgb->height, rgb->width, CV_8UC4, rgb->data);
        Mat irmat = cv::Mat(ir->height, ir->width, CV_32FC1, ir->data);
        Mat depthmat =cv::Mat(depth->height, depth->width, CV_32FC1, depth->data);    

        cv::imshow("rgb", rgbmat);
        cv::imshow("ir", irmat / 4500.0f); 
        cv::imshow("depth", depthmat / 4500.0f); 

        // //! [registration]
        // registration->apply(rgb, depth, &undistorted, &registered, true, &depth2rgb);
        // //! [registration]

        // cv::Mat(undistorted.height, undistorted.width, CV_32FC1, undistorted.data).copytTo(depthmatUndistorted);
        // cv::Mat(registered.height, registered.width, CV_8UC4, registered.data).copyTo(rgbd);
        // cv::Mat(depth2rgb.height, depth2rgb.width, CV_32FC1, depth2rgb.data).copyTo(rgbd2);


        // cv::imshow("undistorted", depthmatUndistorted / 4500.0f);
        // cv::imshow("registered", rgbd);
        // cv::imshow("depth2RGB", rgbd2 / 4500.0f);
      //! [loop end]
        listener.release(frames);
    }
    //! [loop end]

    //! [stop]
    dev->stop();
    dev->close();
    //! [stop]

    delete registration;

    std::cout << "Goodbye World!" << std::endl;
    return 0;
}

CMakeLists.txt

# cmake needs this line
cmake_minimum_required(VERSION 2.8)
# Enable C++11
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
# Define project name
project(kinect)

# Find OpenCV, you may need to set OpenCV_DIR variable
# to the absolute path to the directory containing OpenCVConfig.cmake file
# via the command line or GUI
find_package(OpenCV REQUIRED)
FIND_PACKAGE(PkgConfig REQUIRED)
FIND_PACKAGE(freenect2 REQUIRED)

include_directories( ${OpenCV_INCLUDE_DIRS} )
include_directories( ${freenect2_INCLUDE_DIRS} )

# Declare the executable target built from your sources
add_executable(kinect kinect.cpp)

# Link your application with OpenCV libraries
target_link_libraries(kinect ${freenect2_LIBRARIES} ${OpenCV_LIBS})

编译

mkdir build  &&  cd build 
cmake ..  &&  make

运行./kinect


3. ROS中配置Kinect2

在ROS中配置Kinect的是通过 IAI Kinect2 包的安装实现的,这个包为 ROS 和 Kinect 的连接提供了必要的工具和库。

3.1 IAI Kinect2 功能

IAI Kinect2包提供了以下功能:

  • a calibration tool for calibrating the IR sensor of the Kinect One to the RGB sensor and the depth measurements
  • a library for depth registration with OpenCL support
  • the bridge between libfreenect2 and ROS
  • a viewer for the images / point clouds
    从以上功能中可以看出,IAI Kinect2包的使用,需要在系统中安装libfreenect2,就是我们第一步中所安装的驱动包。

3.2 安装编译

cd ~/Workspace/catkin_ws_kinect2 && mkdir src && cd src
git clone https://github.com/code-iai/iai_kinect2.git
cd iai_kinect2
rosdep install --from-paths . --ignore-src -r
cd ~/Workspace/catkin_ws_kinect2
catkin_make -DCMALE_BUILD_TYPE="Release"

在执行rosdep install -r --from-paths .时可能汇报错:

没有关系,这些依赖库就是我们之后要安装的,忽视就好了.

catkin_make
source devel/setup.bash 
roslaunch kinectt2_bridge kinect2_bridge.launch #使用roslaunch启动相关节点

再开一个终端

source devel/setup.bash 
rosrun kinect2_viewer kinect2_viewer sd cloud

在窗口中按下s键进行彩色图像与深度图像的保存,默认保存终端开启的当前目录,可以先建立一个save目录,再执行上述命令进行保存操作用于保存深度图彩色图


可以看出每按一次S键都会保存四副图像(cloud.pcd、color.jpg、depth.png、depth_colored.png),命名从0000开始,同一窗口不断按空格就0001,0002依次保存下去,重新run的话在新窗口又是从0000开始保存,在控制窗口可以使用ctrl+c 关闭节点,在iai_kinect2/kinect2_viewer/src/下打开viewer.cpp可以去查看对应的源码来了解对应参数的意义

0000_color.jpg
0000_depth_colored.png
0000_depth.png

5. 保存彩色图像png和深度图像pgm

6. PCL库安装与kinect2数据读取

7. NiTE2

    1. 这里下载NiTE2的SDKNiTE-Linux-x64-2.2.tar1.zip(因为我的台式机是64位系统)
    1. 解压


      下载下来解压NiTE_SDK
  • 3.配置环境变量到.bashrc中

cd /home/clark/Compile/NiTE-Linux-x64-2.2
chmod 777 install.sh
sudo ./install.sh  #这一步后会生成一个NiTEDevEnvironment文件
cat NiTEDevEnvironment >> ~/.bashrc  #添加到.bashrc环境变量中
.bashrc
    1. 配置libfreenect2-openni2的路径
      前往/home/clark/Compile/NiTE-Linux-x64-2.2/Samples/Bin修改文件OpenNI.ini中的最后一行为Repository=/usr/local/lib/OpenNI2/Drivers指向OpenNI2的两个libfreenect2-openni2.so文件所在的目录

    1. 运行Sample的UserViewer例子
cd /home/clark/Compile/NiTE-Linux-x64-2.2/Samples/Bin
./UserViewer

7. 总结

至此,完成了Ubuntu1804环境下利用libfreenect2读取Kinect2数据并在opencv进行显示,利用iai_kinect库建立ROS与Kinect之间的通道Bridge并完成彩色图像深度图像的保存。

8. 参考

  1. Ubuntu 16.04 中 Kinect 2.0 的 libfreenect2 驱动配置及其图像读取编程实现
  2. 基于libfreenect2 &ROS 下的iai_kinect2 实现kinectV2的图像获取和保存 【ubuntu18.04】
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 225,015评论 6 522
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 96,373评论 3 404
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 172,253评论 0 368
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 61,069评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 70,079评论 6 400
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,550评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,911评论 3 429
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,892评论 0 279
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,435评论 1 324
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,465评论 3 346
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,586评论 1 355
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,178评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,920评论 3 340
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,356评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,493评论 1 277
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 50,151评论 3 381
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,663评论 2 366

推荐阅读更多精彩内容