CloudCompare——点云二次曲面拟合


在这里插入图片描述

本文由CSDN点云侠原创,原文链接。爬虫网站自重。博客长期更新,本文最新更新时间为:2023年8月6日。

1.二次曲面拟合

  二次曲面方程如下:
z ( x , y ) = a x 2 + b x y + c y 2 + d x + e y + f (1) z(x,y)=ax^2+bxy+cy^2+dx+ey+f \tag{1} z(x,y)=ax2+bxy+cy2+dx+ey+f(1)
采用最小二乘法拟合局部二次曲面,建立目标函数为:
z = ∑ i = 0 k [ z ( x i , y i ) − z i ] 2 (2) z=\sum_{i=0}^{k}[z(x_i,y_i)-z_i]^2 \tag{2} z=i=0k[z(xiyi)zi]2(2)
联立式( 1) 和式( 2) ,对各项系数求偏导,并令偏导数等于零,得到线性方程组,见式( 3) ,求解线性方程组,得到局部二次拟合曲面方程。
[ ∑ i = 0 k x i 4 ∑ i = 0 k x i 3 y i ∑ i = 0 k x i 2 y i ∑ i = 0 k x i 3 ∑ i = 0 k x i 2 y i ∑ i = 0 k x i 2 ∑ i = 0 k x i 3 y i ∑ i = 0 k x i 2 y i 2 ∑ i = 0 k x i y i 3 ∑ i = 0 k x i 2 y i ∑ i = 0 k x i y i 2 ∑ i = 0 k x i y i ∑ i = 0 k x i 2 y i 2 ∑ i = 0 k x i y i 3 ∑ i = 0 k y i 4 ∑ i = 0 k x i y i 2 ∑ i = 0 k y i 3 ∑ i = 0 k y i 2 ∑ i = 0 k x i 3 ∑ i = 0 k x i 2 y i ∑ i = 0 k x i y i 2 ∑ i = 0 k x i 2 ∑ i = 0 k x i y i ∑ i = 0 k x i ∑ i = 0 k x i 2 y i ∑ i = 0 k x i y i 2 ∑ i = 0 k y i 3 ∑ i = 0 k x i y i ∑ i = 0 k y i 2 ∑ i = 0 k y i ∑ i = 0 k x i 2 ∑ i = 0 k x i y i ∑ i = 0 k y i 2 ∑ i = 0 k x i ∑ i = 0 k y i ∑ i = 0 k 1 ] [ a b c d e f ] = [ ∑ i = 0 k z i x i 2 ∑ i = 0 k z i x i y i ∑ i = 0 k z i y i 2 ∑ i = 0 k z i x i ∑ i = 0 k z i y i ∑ i = 0 k z i ] (3) \left[ \begin{matrix} \sum_{i=0}^{k}x_i^4 & \sum_{i=0}^{k}x_i^3y_i & \sum_{i=0}^{k}x_i^2y_i& \sum_{i=0}^{k}x_i^3& \sum_{i=0}^{k}x_i^2y_i& \sum_{i=0}^{k}x_i^2\\ \sum_{i=0}^{k}x_i^3y_i & \sum_{i=0}^{k}x_i^2y_i^2 & \sum_{i=0}^{k}x_iy_i^3 & \sum_{i=0}^{k}x_i^2y_i& \sum_{i=0}^{k}x_iy_i^2& \sum_{i=0}^{k}x_iy_i\\ \sum_{i=0}^{k}x_i^2y_i^2 & \sum_{i=0}^{k}x_iy_i^3 & \sum_{i=0}^{k}y_i^4 & \sum_{i=0}^{k}x_iy_i^2 & \sum_{i=0}^{k}y_i^3 & \sum_{i=0}^{k}y_i^2\\ \sum_{i=0}^{k}x_i^3 & \sum_{i=0}^{k}x_i^2y_i & \sum_{i=0}^{k}x_iy_i^2 & \sum_{i=0}^{k}x_i^2 & \sum_{i=0}^{k}x_iy_i & \sum_{i=0}^{k}x_i\\ \sum_{i=0}^{k}x_i^2y_i & \sum_{i=0}^{k}x_iy_i^2 & \sum_{i=0}^{k}y_i^3 & \sum_{i=0}^{k}x_iy_i & \sum_{i=0}^{k}y_i^2 & \sum_{i=0}^{k}y_i\\ \sum_{i=0}^{k}x_i^2 & \sum_{i=0}^{k}x_iy_i & \sum_{i=0}^{k}y_i^2 & \sum_{i=0}^{k}x_i & \sum_{i=0}^{k}y_i & \sum_{i=0}^{k}1\\ \end{matrix} \right] \left[ \begin{matrix} a \\ b \\ c \\ d \\ e \\ f \\ \end{matrix} \right]= \left[ \begin{matrix} \sum_{i=0}^{k}z_ix_i^2 \\ \sum_{i=0}^{k}z_ix_iy_i \\ \sum_{i=0}^{k}z_iy_i^2 \\ \sum_{i=0}^{k}z_ix_i \\ \sum_{i=0}^{k}z_iy_i \\ \sum_{i=0}^{k}z_i \\ \end{matrix} \right]\tag{3} i=0kxi4i=0kxi3yii=0kxi2yi2i=0kxi3i=0kxi2yii=0kxi2i=0kxi3yii=0kxi2yi2i=0kxiyi3i=0kxi2yii=0kxiyi2i=0kxiyii=0kxi2yii=0kxiyi3i=0kyi4i=0kxiyi2i=0kyi3i=0kyi2i=0kxi3i=0kxi2yii=0kxiyi2i=0kxi2i=0kxiyii=0kxii=0kxi2yii=0kxiyi2i=0kyi3i=0kxiyii=0kyi2i=0kyii=0kxi2i=0kxiyii=0kyi2i=0kxii=0kyii=0k1 abcdef = i=0kzixi2i=0kzixiyii=0kziyi2i=0kzixii=0kziyii=0kzi (3)

2.参考文献

[1] 方程喜,隋立春,朱海雄.用于公路勘测设计的LiDAR点云抽稀算法[J].测绘通报,2017(10):58-61+88.

3.操作流程

在这里插入图片描述
  输出二次曲面 a + b x + c y + d x 2 + e x y + f y 2 = 0 a+bx+cy+dx^2+exy+fy^2=0 a+bx+cy+dx2+exy+fy2=0的表达式和拟合误差RMS。经实测,CloudCompare的拟合结果偏差较大。

在这里插入图片描述

  此外,还生成了拟合曲面的mesh模型,可以用来计算点云到模型的距离。
在这里插入图片描述

4.完整操作

在这里插入图片描述

5.算法源码

ccQuadric* ccQuadric::Fit(CCLib::GenericIndexedCloudPersist *cloud, double* rms/*=0*/)
{
	//number of points
	unsigned count = cloud->size();
	if (count < CC_LOCAL_MODEL_MIN_SIZE[QUADRIC])
	{
		ccLog::Warning(QString("[ccQuadric::fitTo] Not enough points in input cloud to fit a quadric! (%1 at the very least are required)").arg(CC_LOCAL_MODEL_MIN_SIZE[QUADRIC]));
		return nullptr;
	}

	//project the points on a 2D plane
	CCVector3 G;
	CCVector3 X;
	CCVector3 Y;
	CCVector3 N;
	{
		CCLib::Neighbourhood Yk(cloud);
		
		//plane equation
		const PointCoordinateType* theLSPlane = Yk.getLSPlane();
		if (!theLSPlane)
		{
			ccLog::Warning("[ccQuadric::Fit] Not enough points to fit a quadric!");
			return nullptr;
		}

		assert(Yk.getGravityCenter());
		G = *Yk.getGravityCenter();

		//local base
		N = CCVector3(theLSPlane);
		assert(Yk.getLSPlaneX() && Yk.getLSPlaneY());
		X = *Yk.getLSPlaneX(); //main direction
		Y = *Yk.getLSPlaneY(); //secondary direction
	}

	//project the points in a temporary cloud
	ccPointCloud tempCloud("temporary");
	if (!tempCloud.reserve(count))
	{
		ccLog::Warning("[ccQuadric::Fit] Not enough memory!");
		return nullptr;
	}

	cloud->placeIteratorAtBeginning();
	for (unsigned k=0; k<count; ++k)
	{
		//projection into local 2D plane ref.
		CCVector3 P = *(cloud->getNextPoint()) - G;

		tempCloud.addPoint(CCVector3(P.dot(X),P.dot(Y),P.dot(N)));
	}

	CCLib::Neighbourhood Zk(&tempCloud);
	{
		//set exact values for gravity center and plane equation
		//(just to be sure and to avoid re-computing them)
		Zk.setGravityCenter(CCVector3(0,0,0));
		PointCoordinateType perfectEq[4] = { 0, 0, 1, 0 };
		Zk.setLSPlane(	perfectEq,
						CCVector3(1,0,0),
						CCVector3(0,1,0),
						CCVector3(0,0,1));
	}

	Tuple3ub dims;
	const PointCoordinateType* eq = Zk.getQuadric(&dims);
	if (!eq)
	{
		ccLog::Warning("[ccQuadric::Fit] Failed to fit a quadric!");
		return nullptr;
	}

	//we recenter the quadric object
	ccGLMatrix glMat(X,Y,N,G);

	ccBBox bb = tempCloud.getOwnBB();
	CCVector2 minXY(bb.minCorner().x,bb.minCorner().y);
	CCVector2 maxXY(bb.maxCorner().x,bb.maxCorner().y);

	ccQuadric* quadric = new ccQuadric(minXY, maxXY, eq, &dims, &glMat);

	quadric->setMetaData(QString("Equation"),QVariant(quadric->getEquationString()));

	//compute rms if necessary
	if (rms)
	{
		const unsigned char dX = dims.x;
		const unsigned char dY = dims.y;
		//const unsigned char dZ = dims.z;

		*rms = 0;

		for (unsigned k=0; k<count; ++k)
		{
			//projection into local 2D plane ref.
			const CCVector3* P = tempCloud.getPoint(k);

			PointCoordinateType z = eq[0] + eq[1]*P->u[dX] + eq[2]*P->u[dY] + eq[3]*P->u[dX]*P->u[dX] + eq[4]*P->u[dX]*P->u[dY] + eq[5]*P->u[dY]*P->u[dY];
			*rms += (z-P->z)*(z-P->z);
		}

		if (count)
		{
			*rms = sqrt(*rms / count);
			quadric->setMetaData(QString("RMS"),QVariant(*rms));
		}
	}
	
	return quadric;
}

6.相关代码

[1] PCL 最小二乘拟合二次曲面
[2] matlab 最小二乘拟合二次曲面
[3] Open3D 点云最小二乘拟合二次曲面

  • 5
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点云侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值