[OpenGL]基于点云的植物建模

我的新博客:http://ryuzhihao.cc/

本文在我的新博客中的链接为:http://ryuzhihao.cc/?p=725

 

从Kinect获取植物的三维点云是一件很轻松的事情。

那么,能否利用这些点云,重建植物的三维模型?如果可以实现,将意味着我们只需用扫描到的植物点云,就可以快速重建出植物的真实三维模型。与手工建模相比,这将更加接近真实的植物形状。

1 参考文献

本文参考的文献主要是下面这一篇:

Knowledge and Heuristic Based Modeling of Laser-Scanned TreesHui Xu,Nathan Gossett, Baoquan Chen.

2 我的程序效果

在阅读上述参考文献后,我实现了其中的核心算法。其流程图和最终效果如下:

图1:本文程序的效果以及流程。(a) 输入的原始点云数据,共计33956个点。(b) 分割后,形成的红色的树叶区域和白色的枝干区域。(c) 将枝干点云划分为若干个bin。(d) 将bins得到树的骨架。(e)树木的最终重建效果。

二、具体步骤

1. 输入点云数据

实验数据可采用Kinect采集的单视角点云(single scan)。输入的点云如图2

图2:输入的点云数据(共计33956pts)

 

2. 分离枝干、叶片区域,得到枝干部分点云的连通图

首先,假定我们已经知道了根节点root的位置。根节点root可以是人工选定的、也可以来自竖直方向最低的点。

然后,从根节点开始,不断加入相邻的点到一个枝干点集合(vector<Point> m_branchPts)中。可以认为相距0.3px的点就是相邻,这取决于扫描的精度。

建议使用基于kd-Tree进行范围搜索(range search),在30000的数据量上计算,总耗时约为0.2秒。

下面是该部分的伪代码和分离的效果图:

 

假设点云总数为N,且存储在vector<Point> m_vertexs中。

定义 
vector<Point> m_branchPts;  // 枝干点云
bool m_visited[N]; // 标记各点是否已经被访问过
int m_rootIndex;   // 根节点在m_vertexs中的索引 

初始化
foreach i = 0,1,...N-1
  m_visited[i] = false;
// 将根节点放入
m_visited[m_rootIndex] = true;
m_branchPts.push_back(m_vertexs[m_rootIndex]);

算法循环:不断加入新的点到m_branchPts中
double radius = 0.3px;  // 搜索半径
for(int i=0; i<m_branchPts.size(); i++)
{
  vector<int> neighbors =
    KdTree_RangeSearch(radius,m_branchPts[i]);

  foreach k = 0,1,....,neighbors.size()
  {
    if(m_visited[neighbors[k]] == false)
    {
      m_branchPts.push_back(neighbors[k]);
      m_visited[neighbors[k]] = true;
    }
  }
}

图3:分离枝干点云和树冠点云。红色为叶片、白色为树干。

 

3. 将枝干区域的点云划分为若干个bin

在第二步,我们已经得到了一个仅仅包含枝干部分的点云集合(即vector<Point>m_branchPts)。下面需要将该部分点云,划分为若干个小枝段。

首先,将枝干部分的点云集合m_branchPts中的所有点,与其相邻的点连接起来,形成一个连通图(这里仍然可以定义“相邻”为间距0.3px)。

然后,我们需要一种单源点最短路径算法来寻找从根节点到其他所有结点的最短路径长度。当然使用Dijkstra最短路径算法是完全可行的。

一旦最短路径长度确立了,我们可以将所有结点按照与root的距离划分为若干个区域,将距离长度相近的点加入到一个Bin中。可以认为:bin就是一段最小的枝元。

图4:将枝干部分点云划分为若干个bins

图5:划分后的若干个bins和树叶区域点云的效果

 

4. 按照深度优先遍历所有的Bins,得到树的骨架(Product main skeleton)

对于刚求解出来的每一个bin,都计算其中点。取每个bin的中点作为骨架图的结点,通过对连通图的深度优先搜索+KdTree的最邻近查询的策略,可以连接相邻的结点形成骨架。

同时,对初步连接成的骨架图,若存在环路,则可应用Prim算法可得到其最小生成树。骨架的最终效果图如下:

图6:树的骨架图(红色为结点,黄色为连线,白色为原枝干区域点云)

 

5. 利用树的骨架图,重建树的三维模型

在得到skeleton之后,工作就变得简单了。用一个Cylinder或者三角网格的枝段模型将骨架图的每一段显示出来,就能得到最终的三维树模型。其效果如下:

图7:树重建的最终效果。

  • 14
    点赞
  • 88
    收藏
    觉得还不错? 一键收藏
  • 26
    评论
### 回答1: OpenGL是一个强大的图形库,可以用于显示点云数据。要在OpenGL中显示点云,需要首先将点云数据转换为OpenGL可以理解的格式,即将点云的坐标数据放入顶点数组中。然后,可以使用OpenGL的渲染函数将点云渲染在屏幕上。 在将点云数据转换为顶点数组之前,需要确定点云的坐标系和顶点格式。通常,点云数据可以是XYZ坐标格式或是XYZRGB格式,其中RGB代表颜色信息。在转换为顶点数组时,需要将每个点的坐标和颜色值分别存储到顶点数组的各自位置。 一旦点云数据被转换为顶点数组,并且设置了正确的坐标系和顶点格式,就可以使用OpenGL的渲染函数进行渲染。最基本的渲染函数是glDrawArrays,该函数可以将指定的顶点数组渲染为点云。 然而,仅仅使用glDrawArrays函数可能无法充分展示点云数据的特征,因此可以使用一些其他的OpenGL的特性,如分色器和纹理贴图,来增强点云的显示效果。 总之,使用OpenGL显示点云的过程包括将点云数据转换为顶点数组,设置坐标系和顶点格式,使用OpenGL渲染函数进行渲染,并可以使用其他OpenGL功能来增强显示效果。 ### 回答2: OpenGL可以在3D场景中显示大量的点云数据。点云是由大量离散坐标点组成的三维数据,这些点在场景中共同形成一个物体或环境。通过OpenGL,我们可以将这些点逐一绘制在屏幕上,形成真实感和体验。更重要的是,OpenGL可以呈现点云的变化,如旋转、缩放、移动等操作。 在OpenGL中,点云数据通常存储在一个数组中。我们需要使用OpenGL的各种函数来绘制点。OpenGL提供了两种不同的方式来绘制点云数据,一种是传统的glBegin/glEnd方式,另一种是VBO(Vertex Buffer Object,顶点缓存对象)方式。两种方式各有优缺点,需要根据实际场景来进行选择。 在使用OpenGL绘制点云的时候,我们需要设置点的大小、颜色和形状等属性,这些属性可以在OpenGL中进行设置。此外,我们还可以对点云进行处理,如剔除过于密集的点、滤波等操作,以保证点云的质量和清晰度。 综上所述,OpenGL是一种强大而灵活的工具,可以有效地显示点云数据。通过灵活调节各种参数,可以实现各种效果和应用。在3D仿真、虚拟现实、机器人视觉等领域,OpenGL显示点云数据已成为必不可少的技术手段。 ### 回答3: OpenGL是一种开放源代码的图形库,提供了强大的2D和3D图形渲染功能,广泛应用于游戏、CAD、数据可视化等领域。点云是一种表示3D物体的数据格式,它以点的坐标和颜色等属性来描绘一个物体的表面。 如果要使用OpenGL显示点云,首先需要加载点云数据,通常使用txt、ply等格式的文件。读取点云文件后,需要将每个点的坐标、颜色等属性传给OpenGL渲染引擎,这通常涉及到顶点缓存对象、着色器程序等OpenGL技术。 在OpenGL中,可以使用点渲染、线渲染和面渲染三种方式来显示点云。通过在OpenGL渲染管道中设置点大小、颜色等参数,可以实现不同样式的点云渲染效果。此外,还可以通过相机视角、光照等参数来调整点云的显示效果。 总的来说,使用OpenGL显示点云需要了解OpenGL基础知识和点云数据格式。同时需要掌握OpenGL的各种渲染技术,以实现不同效果的点云显示。
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值