点云技术相关产学研社区

 找回密码
 立即注册加入PCL中国点云技术相关产学研社区

扫一扫,访问微社区

查看: 5529|回复: 2

KinectSDK1.8+pcl1.6+OpenNI2点云获取详解

[复制链接]
发表于 2017-1-4 17:43:20 | 显示全部楼层 |阅读模式
1.基本思路与开发环境

(首先声明下,这是个广告,但是也确实是一个用KINECT获取点云的方法,也有些干货)

用KinectSDK驱动Kinect
用OpenNI2获取深度流和色彩流并转换为点云数据
用PCL展示并保存PCD文件

开发环境:win7(64位)+vs(10)+KinectSDK1.8+pcl1.6+OpenNI2

(首先假设大家的环境搭建的没有问题,如果不会可以看这个(里面有本示例的安装程序和安装文档):
https://weidian.com/s/1030566254?wfr=c&ifr=shopdetail )
2.程序

首先给出思路:
1.打开Kinect设备并对Kinect设备进行设置,这里需要注意Kinect捕捉RGB数据和D数据的分辨率。
2.获取深度流和颜色流后,获取其中一帧的RGBD信息。
3.将RGBD信息格式转化为XYZRGB信息格式。(难点:D数据转化为XYZ,D数据与RGB数据的对齐)
4.在PCL中进行保存和显示。

核心代码分析:

首先要打开Kinect设备并对Kinect设备进行设置。
========================================================================
        openni::Status rc = openni::STATUS_OK;
        rc = openni::OpenNI::initialize();
        CheckOpenNIError( rc, "initialize context" );  
        openni::Device device;
        rc = device.open( openni::ANY_DEVICE );
       
        //设置并获取深度流
        openni::VideoStream depth, color;
        rc = depth.create( device, openni::SENSOR_DEPTH );
        // set depth video mode  
        VideoMode modeDepth;  
        modeDepth.setResolution( 640, 480 );  //深度数据的像素
        modeDepth.setFps( 30 );  
        modeDepth.setPixelFormat( PIXEL_FORMAT_DEPTH_1_MM );  
        depth.setVideoMode(modeDepth);  
        // start depth stream  
        rc = depth.start();  
       //设置并获取色彩流
        rc = color.create( device, openni::SENSOR_COLOR );  
        // set color video mode  
        VideoMode modeColor;  
        modeColor.setResolution( 1280,960);  
        modeColor.setFps( 30 );  
        modeColor.setPixelFormat( PIXEL_FORMAT_RGB888 );  
        color.setVideoMode( modeColor);
        rc = color.start();

===========================================================================
至此,深度流和颜色流已经保存在了内存中,现在需要提取其中一帧的数据核心的程序如下:
==========================================================================
        VideoFrameRef frame, frameColor;
        depth.readFrame(&frame);
        color.readFrame(&frameColor);
==========================================================================
接下来将每一帧的数据,转化为XYZRGB格式保存再一个叫mydata的结构体中。
这里需要注意连个问题:
1.D数据向xyz数据的转化,可以利用OPENNI自带的convertDepthToWorld 函数。
2.Kinect捕捉RGB数据和D数据的分辨率是不同的,而且KINECT中RGB摄像机和深度摄像机之间存在视差,因此在生成XYZRGB数据前需要对齐D数据和RGB数据。这个对齐算法是目前的研究难点之一,示例中采用的方法比较简单,只进行了简单的对齐。
==========================================================================
                data mydata;
                vector<data> point;
                DepthPixel *pDepth = (DepthPixel*)frame.getData();
                const openni::RGB888Pixel* pImageRow = (const openni::RGB888Pixel*)frameColor.getData();
                //进行对齐操作
                for(float i=0,row=0;i<frame.getHeight();i=i+1,row=row+2)
                {       
                        for(float j=0,lin=0;j<frame.getWidth();j=j+1,lin=lin+2)
                        {
                                int k = i;
                                int m = j;
                                int r=row;
                                int l=lin;
                                xx = pDepth[k*frame.getWidth()+m];
                             //将D转化为XYZ
                                CoordinateConverter::convertDepthToWorld (depth,i,j,xx,&x,&y,&z);

                                if (x!=0 &&y!=0 &&z!=0)//去除NULL点,并保存
                                {
                                        mydata.x=x*0.001;
                                        mydata.y=y*0.001;
                                        mydata.z=z*0.001;
                                        mydata.r= pImageRow[r*frameColor.getWidth()+l].r;
                                        mydata.g= pImageRow[r*frameColor.getWidth()+l].g;
                                        mydata.b= pImageRow[r*frameColor.getWidth()+l].b;
                                        point.push_back(mydata);
                                }                               
                        }
                }
============================================================================
至此,point中就是XYZRGB类型的数据了,然后利用PCL对点云进型分割存储就行了。
我的存储分成了全景ALL和局部SUB,每种场景又分了XYZ型和XYZRGB型。 下面以XYZ型为例:
============================================================================
                //生成并保存XYZ全景
                pcl::PointCloud<pcl::PointXYZ> cloud0XYZ;
                cloud0XYZ.width=point.size();
                cloud0XYZ.height=1;
                cloud0XYZ.is_dense=false;
                cloud0XYZ.points.resize(cloud0.width);
                for (size_t i=0;i<cloud0XYZ.points.size();i++)
                {
                        cloud0XYZ.points.x=point.x;
                        cloud0XYZ.points.y=point.y;
                        cloud0XYZ.points.z=point.z;
                       
                }
                //保存XYZ全景
                pcl::io::savePCDFileASCII("ALL_XYZ.pcd",cloud0XYZ);

                //生成并保存XYZ局部
                pcl::PointCloud<pcl::PointXYZ>::Ptr cloud0XYZSUB(new pcl::PointCloud<pcl::PointXYZ>);
                pcl::PointCloud<pcl::PointXYZ>::Ptr cloud0XYZSUB1(new pcl::PointCloud<pcl::PointXYZ>);
                pcl::PointCloud<pcl::PointXYZ>::Ptr cloud0XYZSUB2(new pcl::PointCloud<pcl::PointXYZ>);
                pcl::PointCloud<pcl::PointXYZ>::Ptr cloud0XYZPrt (&cloud0XYZ);
                // 创建滤波器对象
                pcl::PassThrough<pcl::PointXYZ> pass1;
                pass1.setInputCloud (cloud0XYZPrt);
                pass1.setFilterFieldName ("z");
                pass1.setFilterLimits (Z1,Z2);
                pass1.filter (*cloud0XYZSUB1);

                pass1.setInputCloud (cloud0XYZSUB1);
                pass1.setFilterFieldName ("x");
                pass1.setFilterLimits (X1, X2);
                pass1.filter (*cloud0XYZSUB2);

                pass1.setInputCloud (cloud0XYZSUB2);
                pass1.setFilterFieldName ("y");
                pass1.setFilterLimits (Y1, Y2);
                pass1.filter (*cloud0XYZSUB);
                //保存XYZ局部
                pcl::io::savePCDFileASCII("SUB_XYZ.pcd",*cloud0XYZSUB);
============================================================================
最后,显示点云就可以了。
===========================================================================
如果想获取全部的源码和相关资讯服务可以点下面链接:
https://weidian.com/s/1030566254?wfr=c&ifr=shopdetail
(如果本文对你有用,感谢各位通过以上链接进行打赏,随便下个2元的单就行了,留言打赏就OK了)
       

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册加入PCL中国点云技术相关产学研社区

x
回复

使用道具 举报

发表于 2017-12-20 15:07:31 | 显示全部楼层
楼主,点开链接是空的啊?:o
回复 支持 反对

使用道具 举报

发表于 2017-12-20 15:08:12 | 显示全部楼层
求源码~谢楼主
回复 支持 反对

使用道具 举报

本版积分规则

QQ|小黑屋|点云技术相关产学研社区 ( 陕ICP备13001629号 )

GMT+8, 2024-4-25 14:32 , Processed in 2.125711 second(s), 17 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表