两个点集间的变换矩阵(或相似矩阵)计算(应用于点云配准、图像匹配)

@(笔记)两个点集间的变换矩阵(或相似矩阵)计算(应用于点云配准、图像匹配)

同尺度点云

问题描述:两个相同尺度的点云,仅发生旋转平移(R、T)变换,已知相互匹配点集的情况下,计算R、T。

void pose_estimation_3d3d(
	const vector<Point3f>& pts1,
	const vector<Point3f>& pts2,
	Eigen::Matrix4f & TransMatrix
)
{
	Point3f p1, p2;     // center of mass
	int N = pts1.size();
	for (int i = 0; i < N; i++)
	{
		p1 += pts1[i];
		p2 += pts2[i];
	}
	p1 = Point3f(Vec3f(p1) / N);
	p2 = Point3f(Vec3f(p2) / N);
	vector<Point3f>     q1(N), q2(N); // remove the center
	for (int i = 0; i < N; i++)
	{
		q1[i] = pts1[i] - p1;
		q2[i] = pts2[i] - p2;
	}

	// compute q1*q2^T
	Eigen::Matrix3d W = Eigen::Matrix3d::Zero();
	for (int i = 0; i < N; i++)
	{
		W += Eigen::Vector3d(q1[i].x, q1[i].y, q1[i].z) * Eigen::Vector3d(q2[i].x, q2[i].y, q2[i].z).transpose();
	}
	cout << "W=" << W << endl;

	// SVD on W
	Eigen::JacobiSVD<Eigen::Matrix3d> svd(W, Eigen::ComputeFullU | Eigen::ComputeFullV);
	Eigen::Matrix3d U = svd.matrixU();
	Eigen::Matrix3d V = svd.matrixV();
	cout << "U=" << U << endl;
	cout << "V=" << V << endl;

	Eigen::Matrix3d R_ = U* (V.transpose());
	Eigen::Vector3d t_ = Eigen::Vector3d(p1.x, p1.y, p1.z) - R_ * Eigen::Vector3d(p2.x, p2.y, p2.z);

	// convert to cv::Mat
	
	/*R = (Mat_<double>(3, 3) <<
		R_(0, 0), R_(0, 1), R_(0, 2),
		R_(1, 0), R_(1, 1), R_(1, 2),
		R_(2, 0), R_(2, 1), R_(2, 2)
		);
	t = (Mat_<double>(3, 1) << t_(0, 0), t_(1, 0), t_(2, 0));*/
	TransMatrix << R_(0, 0), R_(0, 1), R_(0, 2), t_(0, 0),
		R_(1, 0), R_(1, 1), R_(1, 2), t_(1, 0),
		R_(2, 0), R_(2, 1), R_(2, 2), t_(2, 0),
		0, 0, 0, 1;
}

reference :

高翔视觉SLAM十四讲第一版,7.9 3D-3D:ICP;

不同尺度点云(同样支持其他维度点集)

问题描述:两个不同尺度的点云,发生相似(cR、T)变换,已知相互匹配点集的情况下,计算相似矩阵。

void matrix_estimation_3d3d(
	const vector<Point3f>& pts1,
	const vector<Point3f>& pts2,
	Eigen::Matrix4f & TransMatrix
)
{
	Eigen::Matrix<float, 3, Eigen::Dynamic> cloud_tgt(3, pts1.size());
	Eigen::Matrix<float, 3, Eigen::Dynamic> cloud_src(3, pts1.size());
	for (int i = 0; i < pointcapture.pts1.size(); i++) {
		cloud_src(0, i) = pts1[i].x;
		cloud_src(1, i) = pts1[i].y;
		cloud_src(2, i) = pts1[i].z;
		cloud_tgt(0, i) = pts2[i].x;
		cloud_tgt(1, i) = pts2[i].y;
		cloud_tgt(2, i) = pts2[i].z;
	}
	TransMatrix = Eigen::umeyama(cloud_src, cloud_tgt, true);//置为true,则可估计不同尺度点集的配准,包含cR、T,c为尺度因子;
}

关于Eigen::umeyama ( const MatrixBase< Derived > & src, const
MatrixBase< OtherDerived > & dst, bool with_scaling = true ) 函数的说明

 Eigen::umeyama	(	const MatrixBase< Derived > & 	src,const MatrixBase< OtherDerived > & 	dst,bool 	with_scaling = true)

reference :

https://eigen.tuxfamily.org/dox-3.2/group__Geometry__Module.html#gab3f5a82a24490b936f8694cf8fef8e60(Eigen官方文档)

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PCL(Point Cloud Library)是一个非常流行的用于点云处理的C++库,其中包含了计算两个点集之间变换矩阵的函数。以下是使用PCL库计算两个点云之间变换矩阵的示例代码: ```cpp #include <iostream> #include <pcl/point_types.h> #include <pcl/registration/icp.h> int main(int argc, char** argv) { // 定义源点云和目标点云 pcl::PointCloud<pcl::PointXYZ>::Ptr src_cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr dst_cloud(new pcl::PointCloud<pcl::PointXYZ>); src_cloud->width = 3; src_cloud->height = 1; src_cloud->points.resize(src_cloud->width * src_cloud->height); dst_cloud->width = 3; dst_cloud->height = 1; dst_cloud->points.resize(dst_cloud->width * dst_cloud->height); src_cloud->points[0].x = 0; src_cloud->points[0].y = 0; src_cloud->points[0].z = 0; src_cloud->points[1].x = 0; src_cloud->points[1].y = 1; src_cloud->points[1].z = 0; src_cloud->points[2].x = 1; src_cloud->points[2].y = 0; src_cloud->points[2].z = 0; dst_cloud->points[0].x = 1; dst_cloud->points[0].y = 1; dst_cloud->points[0].z = 0; dst_cloud->points[1].x = 1; dst_cloud->points[1].y = 2; dst_cloud->points[1].z = 0; dst_cloud->points[2].x = 2; dst_cloud->points[2].y = 1; dst_cloud->points[2].z = 0; // 定义ICP算法 pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp; icp.setInputSource(src_cloud); icp.setInputTarget(dst_cloud); // 进行配准 pcl::PointCloud<pcl::PointXYZ> aligned_cloud; icp.align(aligned_cloud); // 输出变换矩阵 std::cout << icp.getFinalTransformation() << std::endl; return 0; } ``` 上述代码中,首先定义了源点云和目标点云,接着定义了ICP算法并将源点云和目标点云设置为输入,然后进行配准操作并输出变换矩阵。需要注意的是,上述示例代码中的变换矩阵并不与前面Python和C++代码中的变换矩阵完全一致,但它们都是表示了相同的变换关系。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值