本文提纲
先热热身
点云是啥
你知道点云优缺点吗?
点云库 PCL: 开发者的福音
PCL 安装指北
炒鸡简单的 PCL 实践
留个作业再走
先热热身
小白: hi, 师兄, 好久不见
师兄: 师妹好, 上周单应矩阵作业做了吗?
小白: 嗯, 做了, 这个单应矩阵真的挺有意思的. 作业之外, 我发现了一个新技能...
师兄: 什么技能?
小白: 我发现很多网上流传的图片都可以用上次我学过的单应矩阵实现, 你看这张图, 我第一次看到还以为是真的
现在知道这不就是我们上节课讲的单应矩阵的变换吗?
果然我在网上找到了原图
现在我也会用 OpenCV 里的单应函数做这样的图了~
师兄: 哈哈, 厉害了, 会学以致用了. 话说回来, 今天有啥想问的?
小白: 嗯, 最近在看点云相关的, 师兄要不给我扫扫盲吧?
师兄: 这个我也有些了解, 就把我知道的给你说说吧
小白: yeah, 师兄最棒!
点云是啥
师兄: 那我就当你是个小白吧, 从点云的定义说起. 点云的英文是 "point cloud", 点云的意思和它的名字一样, 就是一堆点的集合, 看起来像是一坨 "云".
小白: 一坨...
师兄: 哦, 一坨不太文雅, 应该是像一片 "云" 一样. 上面只是一种形象的说法, 其实点云在编程实现的时候是一种数据结构, 用来表达多维空间中点的集合, 这个多维空间一般对我们来说是三维空间.
小白: 哦, 原来如此, 也就是我们所在的 XYZ 空间咯
师兄: 对, 因此点云在三维相关的领域内用的很多, 比如三维扫描, 三维重建, 三维感知等方面.
小白: 那点云是怎么得到的啊?
师兄: 一般是通过三维成像传感器得到的, 比如双目相机, 三维扫描仪, RGB-D 相机等, 除了可以用这种特殊的硬件得到, 也可以用计算机合成.
小白: 嗯嗯, 师兄说了这么多, 还是没有一个直观的印象, 这个点云到底长什么样?
师兄: 想要直观一点的话, 我直接给你看点云图吧, 你看下面就是室外一个街道的点云图, 远看能看清房子, 树木的轮廓啊
小白: 嗯嗯, 确实能看出轮廓出来, 不过不像是我们平时拍的照片, 这个点云好像看着不是很清楚哎!
你知道点云优缺点吗?
师兄: 确实是这样的, 这也是点云的一个缺点吧
小白: 那师兄能否顺便说说, 这个点云的表达有啥优缺点呢?
师兄: 这个问题问的有水平, 额, 我想想, 我先说说优点吧.
第一个优点就是可以表达物体的空间轮廓和具体位置, 比如上面这个图, 我们能看出来街道的样子, 房屋的形状, 距离摄像机的距离也是知道的.
第二个优点我觉得就是, 点云本身和视角无关, 也就是你可以任意旋转, 可以从不同角度和方向观察一个点云, 而且不同的点云只要在同一个坐标系下就可以直接融合, 还是很方便的.
至于缺点嘛, 我们先来放大一下点云看看. 如下图所示, 如果拉近一直放大最后看到的就是一个个的点. 也就是空间中成千上万的点组成了一个点的集合, 他们构成了上面的街道房屋等.
小白: 这个点云放大了啥都看不出来啊
师兄: 对, 这个是点云的其中一个缺点, 那我想想点云还有哪些缺点哈!
第一个缺点就是点云并不是稠密的表达, 一般比较稀疏, 你放大了看, 会看到一个个孤立的点. 它的周围是黑的, 也就是没有信息. 所以在空间很多位置其实没有点云, 这部分的信息是缺失的.
第二个缺点嘛, 就是点云的分辨率和离相机的距离有关. 你离近了看是看不清是个什么东西的, 只能拉的很远才能看个大概.
点云库 PCL: 开发者的福音
小白: 嗯, 了解了, 好像缺点也没啥影响哈. 再问个问题, 那这些点云怎么显示和保存啊, 感觉点云很多的话, 好像很复杂的样子...
师兄: 的确, 比如一张 640 x 480 尺寸的深度图就可以转换为拥有三十万个空间点的点云, 大的点云可能有百万千万以上, 不过, 不用担心, 有一个开源的点云库, 英文名为 Point Cloud Library , 简称 PCL , 专门用来进行点云的读写, 处理等各种操作.
小白: 那太好了, 这个 PCL 是谁做的啊? 好用吗?
师兄: 这个 PCL 是由一大批世界范围内的名校和科技公司合作开发的, 你看下面是他们的名字
小白: 哇塞, 好多不认识啊! 不过我看到了 ETH, 也就是苏黎世联邦理工大学, 还有 TUM, 也就是德国慕尼黑工业大学, 我看论文经常看到他们学校的, 他们都是 SLAM 领域非常顶级的研究机构呢
师兄: 嗯, 看来你论文看了不少啊, 哈哈. 我们继续说 PCL,PCL 真的挺方便, 支持跨平台, 可以在 Windows,Linux,macOS,iOS,Android 上部署, 可以说非常全了, 而且 PCL 可以分为很多小的库文件, 在非常适合于计算资源有限或者内存有限的应用场景, 非常方便移动端开发.
小白: 那可以说很通用了哈! 对了师兄, 那这个 PCL 都有啥功能?
师兄: 功能很丰富了, 基本 PCL 的操作都有, 比如读写, 滤波, 特征估计, 表面重建, 配准, 分割等等, 你看这个图就是 PCL 的功能啦
小白: 嗯嗯, 那是不是平时我们操作点云, 调 PCL 的函数就行了?
师兄: 怎么说呢, 其实 PCL 类似于 OpenCV 那样, 有很多功能模块, 每个模块里有封装好的函数, 你可以调这些函数进行基本处理, 但是有些功能 PCL 里可能没有, 这时候需要自己写一些代码实现.
小白: 嗯, 师兄, 总之就是要多编程实践啦
PCL 安装指北
师兄: 对, 那我们开始实践环节吧, 带着你做一些 PCL 的基础编程实现
小白: 太好啦!
师兄: 首先, 我们先来看看点云库, 也就是 PCL 的安装方法, 推荐用 Linux 环节哈, 安装很方便
小白: 嗯, 我之前听师兄说 Linux 环境配置比较简单, 就开始学 Linux 了, 确实, 比 Windows 方便多啦, 就是刚开始用命令行不太习惯, 好多命令记不住...
师兄: 没事的, 命令行不用刻意去记, 忘记了就去查一下, 用多了自然知道了
小白: 知道啦!
师兄: PCL 在 Linux 下安装有两种方式, 一种是安装编译好的库, 一种是从源码编译. 你看这个是 PCL GitHub 上的安装包, 前面几种是不同环境下的编译好的库了, 最后的 source code 就是源码安装
小白: 那这两种方式有什么不一样的?
师兄: 第一种方式比较简单, 几行命令就可以搞定, 比如如果你用的是 Ubuntu 16.04 版本的 Linux 系统的话, 只需要打开一个终端, 输入
sudo apt-get install libpcl-dev pcl-tools
就可以自动安装啦, 优点是安装的版本都是稳定版本(当然也比较旧一点), 不需要处理依赖关系, 安装非常方便, 不过这种安装方式也有一些缺点. 一个是一般安装的都不是最新的, 二是安装的都是别人已经编译好的通用的二进制库, 所以不能根据自己的需求进行调整
小白: 只要一行代码确实方便啊! 那第二种从源码安装的优缺点呢?
师兄: 第二种从源码编译安装也没有麻烦多少, 它是把所有的源代码都下载了下来, 所以会占用较多的存储空间. 但好处很多, 比如可以下载最新的版本或者指定的版本, 可以根据自己的需求在编译时进行选择, 可以查看甚至修改某个函数的源代码等等
小白: 感觉都挺好, 选择恐惧症了, 不知道该选哪个了...
师兄: 推荐用第二种吧, 从源码自己编译安装, 更方便一些
小白: 好, 具体如何操作呢?
师兄: 首先打开 PCL GitHub 的网址: https://github.com/PointCloudLibrary/pcl
然后选择你需要的版本号, 如下图所示
如果没什么特殊需要可以不选择, 我们打开一个终端, 输入下面一行代码
Git clone https://github.com/PointCloudLibrary/pcl pcl-trunk
然后 PCL 源代码就 clone 到你的电脑上了
下一步就是 Ubuntu 下安装的老一套了, 进入目录, 新建一个 build 文件夹存放编译的文件, 然后进入 build 文件夹, cmake 一下, 然后 make, 最后 install, 这一系列流程就是下面这段代码了
- cd pcl-trunk && mkdir build && cd build
- cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
- make -j2
- sudo make -j2 install
静静的等待编译结束就好啦!
炒鸡简单的 PCL 实践
小白: 嗯嗯, 我照着做一下... 嗯, 编译好啦, 我们开始用 PCL 写代码吧
师兄: 那我们来写一个读取 RGB-D 相机的一帧图像并用 PCL 转化为点云的代码吧
首先, 我们需要定义点云的结构, 我们这里使用 typedef 来定义两个常用的类型
- typedef pcl::PointXYZRGB PointT;
- typedef pcl::PointCloud<PointT> PointCloud;
这里的 pcl::PointXYZRGB 就是我们定义的空间点, 它包括空间坐标 XYZ 以及颜色信息 RGB, 此外常用的点的 类型还有
pcl::PointXYZRGBA ( 多了一个 alpha 通道), pcl::PointXYZ (只有空间位置, 不包含颜色信息),pcl::PointXYZHSV (空间位置 + HSV 颜色空间表示的颜色)等, 总之, 我们这里输入的 RGB-D 图像就定义为 pcl::PointXYZRGB.
小白: 师兄, 为什么这里要用 typedef 啊? 我看好多地方都这样写的
师兄: 这样是为了把那么长的一个类型用一个简单的别名 PointT 来代替, 不至于代码显得特别冗长
小白: 这样啊, 懂了, 那么 pcl::PointCloud 就是点云了吧? 它里面可以包含许多类型为 PointT 的点
师兄: 对, 我们继续. 其实 RGB-D 图像转换为点云的方式也简单, 代码如下
- for (int m = 0; m <depth.rows; m++)
- for (int n = 0; n < depth.cols; n++)
- {
- // 获取深度图中 (m,n) 处的值
- ushort d = depth.ptr<ushort>(m)[n];
- // d 可能没有值, 若如此, 跳过此点
- if (d == 0)
- continue;
- // d 存在值, 则向点云增加一个点
- PointT p;
- // 计算这个点的空间坐标
- p.z = double(d) / camera.scale;
- p.x = (n - camera.cx) * p.z / camera.fx;
- p.y = (m - camera.cy) * p.z / camera.fy;
- // 从 rgb 图像中获取它的颜色
- p.b = rgb.ptr<uchar>(m)[n * 3];
- p.g = rgb.ptr<uchar>(m)[n * 3 + 1];
- p.r = rgb.ptr<uchar>(m)[n * 3 + 2];
- // 把 p 加入到点云中
- cloud->points.push_back(p);
- }
- ---------------------
来源: https://www.cnblogs.com/CV-life/p/10105480.html