CloudCompare——基于八叉树的点云下采样

一、八叉树采样(1)

1.功能概述

   'octree'模式需要选择八叉树的细分级别,点云将在该细分级别内“简化”——在八叉树的每个体素单元中,保留距八叉树单元中心最近的点。

2.软件实现

1、找到采样滤波的功能
在这里插入图片描述
2、选择八叉树采样并设置相关参数
在这里插入图片描述

  • subbdivision level:八叉树层级,级别越高,体素越小,保留点越多。
  • 在32位版本的CloudCompare中,八叉树最大层级为10,在64位版本中为21。
  • 该下采样方法是用八叉树体素中心的最近邻点代替该体素单元格内所有的点。

3.结果展示

采样前
在这里插入图片描述
采样后
在这里插入图片描述

二、八叉树采样(2)

1.算法原理

   'Resample'模式需要选择八叉树的细分级别,可以实现将点云在该细分级别内下采样——在八叉树的每个体素单元中,保留八叉树单元的中心点。

2.软件实现

1、找到八叉树重采样功能
在这里插入图片描述
2、设置采样点个数
在这里插入图片描述

  • 设置采样点的个数
    此方法创建一个新的点云,其中的点不一定与输入点云中的点在空间中的位置相同。因此,不可能将输入点云的各种特征(颜色、法线、标量值等)附加到输出点上。(所以采样后为纯白色)

3.结果展示

采样前
在这里插入图片描述
采样后
在这里插入图片描述

三、算法源码

void MainWindow::doActionResampleWithOctree()
{
    
    
	bool ok;
	int pointCount = QInputDialog::getInt(this,"Resample with octree", "Points (approx.)", 1000000, 1, INT_MAX, 100000, &ok);
	if (!ok)
		return;

	ccProgressDialog pDlg(false, this);
	pDlg.setAutoClose(false);

	assert(pointCount > 0);
	unsigned aimedPoints = static_cast<unsigned>(pointCount);

	bool errors = false;

	for ( ccHObject *entity : getSelectedEntities() )
	{
    
    
		ccPointCloud* cloud = nullptr;

		/*if (ent->isKindOf(CC_TYPES::MESH)) //TODO
			cloud = ccHObjectCaster::ToGenericMesh(ent)->getAssociatedCloud();
		else */
		if (entity->isKindOf(CC_TYPES::POINT_CLOUD))
		{
    
    
			cloud = static_cast<ccPointCloud*>(entity);
		}

		if (cloud)
		{
    
    
			ccOctree::Shared octree = cloud->getOctree();
			if (!octree)
			{
    
    
				octree = cloud->computeOctree(&pDlg);
				if (!octree)
				{
    
    
					ccConsole::Error(QString("Could not compute octree for cloud '%1'").arg(cloud->getName()));
					continue;
				}
			}

			cloud->setEnabled(false);
			QElapsedTimer eTimer;
			eTimer.start();
			CCLib::GenericIndexedCloud* result = CCLib::CloudSamplingTools::resampleCloudWithOctree
			(
				cloud,
				aimedPoints,
				CCLib::CloudSamplingTools::CELL_GRAVITY_CENTER,
				&pDlg,
				octree.data()
			);

			if (result)
			{
    
    
				ccConsole::Print("[ResampleWithOctree] Timing: %3.2f s.", eTimer.elapsed() / 1.0e3);
				ccPointCloud* newCloud = ccPointCloud::From(result, cloud);

				delete result;
				result = nullptr;

				if (newCloud)
				{
    
    
					addToDB(newCloud);
					newCloud->setDisplay(cloud->getDisplay());
					newCloud->prepareDisplayForRefresh();
				}
				else
				{
    
    
					errors = true;
				}
			}
		}
	}

	if (errors)
		ccLog::Error("[ResampleWithOctree] Errors occurred during the process! Result may be incomplete!");

	refreshAll();
}

四、相关代码

[1] PCL 基于八叉树的体素滤波

猜你喜欢

转载自blog.csdn.net/qq_36686437/article/details/126551043