PCL计算PFH源码computePairFeatures

本文详细解析了使用PCL库计算PFH点特征直方图过程中遇到的问题,并针对官网资料和文献中存在的误导进行了修正说明,重点阐述了如何正确选择坐标原点及坐标轴计算的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在用pcl库计算PFH点特征直方图时,求解点对的四元组需要用到这个函数:

computePairFeatures (const Eigen::Vector4f &p1, const Eigen::Vector4f &n1,
                     const Eigen::Vector4f &p2, const Eigen::Vector4f &n2,
                     float &f1, float &f2, float &f3, float &f4);

根据官网的定义,求解四元组的基本思想是这样:
在这里插入图片描述
根据这个思想我自己实现了一个求解四元组的过程,在判断坐标原点方面还参考了熊风光的博士论文里的这个部分:

但是很坑的是,如果以PCL库里的computePairFeatures函数作为标准的话,官网提供的计算思路和这篇博士论文里都有一些问题。。首先在选择Darboux坐标系的坐标原点时,判断依据是选择法向量和两点连线夹角较小的那个点作为原点,但是论文里提供的这个式子写反了,夹角小意味着sin值小,cos值大,而式子里是把cos值小的点作为坐标原点,所以这里需要注意。
官网里在计算坐标轴uvw的公式也有一处错误,这个错误这篇博文也提到了,但是我刚看到的时候没懂,自己遇到了这个错误才发现。问题在于官网给的公式里,求坐标轴v的时候是用u叉乘两点连线向量Pt-Ps,但是在PCL源码里是用两点连线向量Pt-Ps去叉乘u,所以这里会导致正负号的反向。。注意到这两个地方就可以理解源码computePairFeatures和官网里提供的思路了。
computePairFeatures这个函数我在本地没找到,在网上一篇博客这里找到了,贴下来:

bool computePairFeatures11(const Eigen::Vector4f &p1, const Eigen::Vector4f &n1,
	const Eigen::Vector4f &p2, const Eigen::Vector4f &n2,
	float &f1, float &f2, float &f3, float &f4)
{ 
	Eigen::Vector4f dp2p1 = p2 - p1;
	dp2p1[3] = 0.0f;
	// f4是两相邻点的距离
	f4 = dp2p1.norm();

	// 在进行数学运算前后,需要检查输出错误信息
	if (f4 == 0.0f)
	{
		PCL_DEBUG("[pcl::computePairFeatures] Euclidean distance between points is 0!\n");
		f1 = f2 = f3 = f4 = 0.0f;
		return (false);
	}

	// 计算f3,首先先确定谁是source,谁是target
	Eigen::Vector4f n1_copy = n1,
		n2_copy = n2;
	n1_copy[3] = n2_copy[3] = 0.0f;
	float angle1 = n1_copy.dot(dp2p1) / f4;

	// Make sure the same point is selected as 1 and 2 for each pair
	float angle2 = n2_copy.dot(dp2p1) / f4;
	if (std::acos(std::fabs(angle1)) > std::acos(std::fabs(angle2)))
	{
		// switch p1 and p2
		n1_copy = n2;
		n2_copy = n1;
		n1_copy[3] = n2_copy[3] = 0.0f;
		dp2p1 *= (-1);
		f3 = -angle2;
	}
	else
		f3 = angle1;

	// Create a Darboux frame coordinate system u-v-w
	// u = n1; v = (p_idx - q_idx) x u / || (p_idx - q_idx) x u ||; w = u x v
	// 齐次坐标相乘,第四维不需要管,只需要计算完叉乘后赋值0即可,因为叉乘是计算与现有向量都垂直的向量,因此前三项肯定满足
	Eigen::Vector4f v = dp2p1.cross3(n1_copy);
	v[3] = 0.0f;
	float v_norm = v.norm();
	// 计算完叉乘后,检查结果模长
	if (v_norm == 0.0f)
	{
		PCL_DEBUG("[pcl::computePairFeatures] Norm of Delta x U is 0!\n");
		f1 = f2 = f3 = f4 = 0.0f;
		return (false);
	}
	// Normalize v
	v /= v_norm;

	Eigen::Vector4f w = n1_copy.cross3(v);
	// Do not have to normalize w - it is a unit vector by construction

	v[3] = 0.0f;
	f2 = v.dot(n2_copy);
	w[3] = 0.0f;
	// Compute f1 = arctan (w * n2, u * n2) i.e. angle of n2 in the x=u, y=w coordinate system
	f1 = std::atan2(w.dot(n2_copy), n1_copy.dot(n2_copy)); // @todo optimize this

	return (true);
}
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值