PCL入门(三):矩阵变换实现平移和旋转

news2024/11/17 5:24:28

目录

        • 1. pcl中的矩阵变换是什么
        • 2. 举例:如何做矩阵变换

1. pcl中的矩阵变换是什么

通过激光传感器等设备获得的3d点云在拼接成更大场景时,需要对点云数据进行旋转和平移操作。而旋转和平移操作,就可以通过矩阵变换来实现。

  • 点的表示

对于点云中的一个点 p p p,其表示为
p = [ x y z 1 ] p=\begin{bmatrix} x \\ y \\ z \\ 1 \\ \end{bmatrix} p= xyz1
这里, ( x , y , z ) (x, y, z) (x,y,z)为点的空间坐标,第4维的1是什么?其实第4维是人为设置的,方便后面用矩阵乘法表示平移操作。

  • 点的平移

如将上面的 p p p点沿着x轴远离原点平移8个单位,直观上就可以得到平移后的结果 p ′ p^{\prime} p
p ′ = [ x + 8 y z 1 ] p^{\prime}=\begin{bmatrix} x+8 \\ y \\ z \\ 1 \\ \end{bmatrix} p= x+8yz1

其实等价于下面的矩阵乘法
p ′ = A ⋅ p = [ 1 0 0 a 0 1 0 b 0 0 1 c 0 0 0 1 ] ⋅ [ x y z 1 ] = [ x + a y + b z + c 1 ] p^{\prime}=A\cdot p= \begin{bmatrix} 1 & 0& 0& a \\ 0 & 1& 0& b\\ 0& 0& 1& c \\ 0& 0& 0& 1 \\ \end{bmatrix}\cdot \begin{bmatrix} x \\ y \\ z \\ 1 \\ \end{bmatrix}= \begin{bmatrix} x+a \\ y+b \\ z+c \\ 1 \\ \end{bmatrix} p=Ap= 100001000010abc1 xyz1 = x+ay+bz+c1

可以看到,通过给三维点坐标增加一维,可以非常方便的通过矩阵乘法实现点的平移操作。注意到,这里的矩阵 A A A总是 4 × 4 4\times4 4×4方阵。

  • 点的旋转

这里指的是点按照某个方向围绕原点旋转 θ \theta θ角度。比如,三维坐标系里绕着x轴逆时针旋转,如下所示(可参考博客《PCL点云库——旋转平移矩阵》)
在这里插入图片描述
任意方向旋转任意角度,可通过绕着x轴旋转、绕着y轴旋转、绕着z轴旋转等三个基本旋转操作组合而成。而绕着x轴旋转、绕着y轴旋转、绕着z轴旋转可分别通过矩阵表示。

记绕着x轴逆时针旋转 θ \theta θ角度的操作为 R x ( θ ) R_x(\theta) Rx(θ),则该操作对应的矩阵为
p ′ = R x ( θ ) ⋅ p = [ 1 0 0 0 0 c o s θ − s i n θ 0 0 s i n θ c o s θ 0 0 0 0 1 ] ⋅ [ x y z 1 ] = [ x y ⋅ c o s θ − z ⋅ s i n θ y ⋅ s i n θ + z ⋅ c o s θ 1 ] p^{\prime}=R_x(\theta)\cdot p= \begin{bmatrix} 1 & 0& 0& 0 \\ 0 & cos\theta& -sin\theta& 0\\ 0& sin\theta& cos\theta& 0 \\ 0& 0& 0& 1 \\ \end{bmatrix}\cdot \begin{bmatrix} x \\ y \\ z \\ 1 \\ \end{bmatrix}= \begin{bmatrix} x \\ y \cdot cos\theta-z\cdot sin\theta \\ y \cdot sin\theta+z\cdot cos\theta \\ 1 \\ \end{bmatrix} p=Rx(θ)p= 10000cosθsinθ00sinθcosθ00001 xyz1 = xycosθzsinθysinθ+zcosθ1

记绕着y轴逆时针旋转 θ \theta θ角度的操作为 R y ( θ ) R_y(\theta) Ry(θ),则该操作对应的矩阵为
p ′ = R y ( θ ) ⋅ p = [ c o s θ 0 s i n θ 0 0 1 0 0 − s i n θ 0 c o s θ 0 0 0 0 1 ] ⋅ [ x y z 1 ] = [ x ⋅ c o s θ + z ⋅ s i n θ y − x ⋅ s i n θ + z ⋅ c o s θ 1 ] p^{\prime}=R_y(\theta)\cdot p= \begin{bmatrix} cos\theta & 0& sin\theta& 0 \\ 0 & 1&0 & 0\\ -sin\theta&0 & cos\theta& 0 \\ 0& 0& 0& 1 \\ \end{bmatrix}\cdot \begin{bmatrix} x \\ y \\ z \\ 1 \\ \end{bmatrix}= \begin{bmatrix} x \cdot cos\theta+z\cdot sin\theta \\ y \\ -x \cdot sin\theta+z\cdot cos\theta \\ 1 \\ \end{bmatrix} p=Ry(θ)p= cosθ0sinθ00100sinθ0cosθ00001 xyz1 = xcosθ+zsinθyxsinθ+zcosθ1

记绕着z轴逆时针旋转 θ \theta θ角度的操作为 R z ( θ ) R_z(\theta) Rz(θ),则该操作对应的矩阵为
p ′ = R z ( θ ) ⋅ p = [ c o s θ − s i n θ 0 0 s i n θ c o s θ 0 0 0 0 1 0 0 0 0 1 ] ⋅ [ x y z 1 ] = [ x ⋅ c o s θ − y ⋅ s i n θ x ⋅ s i n θ + y ⋅ c o s θ z 1 ] p^{\prime}=R_z(\theta)\cdot p= \begin{bmatrix} cos\theta & -sin\theta& 0& 0 \\ sin\theta & cos\theta&0& 0\\ 0& 0& 1& 0 \\ 0& 0& 0& 1 \\ \end{bmatrix}\cdot \begin{bmatrix} x \\ y \\ z \\ 1 \\ \end{bmatrix}= \begin{bmatrix} x \cdot cos\theta-y\cdot sin\theta \\ x \cdot sin\theta+y\cdot cos\theta \\ z \\ 1 \\ \end{bmatrix} p=Rz(θ)p= cosθsinθ00sinθcosθ0000100001 xyz1 = xcosθysinθxsinθ+ycosθz1

2. 举例:如何做矩阵变换

只要实现矩阵变换,就可以做点云的旋转和平移。PCL库中做矩阵变换有两种方法,分别为Eigen::Matrix4fEigen::Affine3fEigen::Matrix4f需要手动构建旋转和平移矩阵,较易出错;Eigen::Affine3f则接近于人类操作步骤,将平移操作和旋转操作做成函数,调用即可。

举例:将点云数据先沿着x轴平移2.5,然后绕着z轴逆时针旋转 π 4 \frac{\pi}{4} 4π的角度。

实现主要参考双愚的代码;兔子pcd数据从博客《PCL读取PCD文件的数据》中获取
链接:https://pan.baidu.com/s/1v6mjPjwd7fIqUSjlIGTIGQ
提取码:zspx

  • matrix_transform.cpp
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/point_cloud.h>
#include <pcl/console/parse.h>
#include <pcl/common/transforms.h>
#include <pcl/visualization/pcl_visualizer.h>

int main(int argc, char** argv)
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr source_cloud(new pcl::PointCloud<pcl::PointXYZ>());

	if (pcl::io::loadPCDFile(argv[1], *source_cloud) < 0)
	{
		std::cout << "Error loading point cloud " << argv[1] << std::endl;
		return -1;
	}

	float theta = M_PI / 4; // 旋转角度

	//方法一: Matrix4f
	Eigen::Matrix4f transform_1 = Eigen::Matrix4f::Identity();

	transform_1(0, 0) = std::cos(theta);
	transform_1(0, 1) = -std::sin(theta);
	transform_1(1, 0) = std::sin(theta);
	transform_1(1, 1) = std::cos(theta);

	transform_1(0, 3) = 2.5;

	printf("method 1: using a matrix4f\n");
	std::cout << transform_1 << std::endl;

	//方法二: Affine3f
	Eigen::Affine3f transform_2 = Eigen::Affine3f::Identity();

	transform_2.translation() << 2.5, 0.0, 0.0;
	transform_2.rotate(Eigen::AngleAxisf(theta, Eigen::Vector3f::UnitZ()));

	printf("method 2: using an affine3f\n");
	std::cout << transform_2.matrix() << std::endl;

	
	// excuting the transformation(执行平移和旋转操作)
	pcl::PointCloud<pcl::PointXYZ>::Ptr transformed_cloud(new pcl::PointCloud<pcl::PointXYZ>());
	pcl::transformPointCloud(*source_cloud, *transformed_cloud, transform_2);

	// visualization(可视化)
	pcl::visualization::PCLVisualizer viewer("Matrix transformation example");

	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> source_cloud_color_handler(source_cloud, 255, 255, 255);
	viewer.addPointCloud(source_cloud, source_cloud_color_handler, "original_cloud");
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> transformed_cloud_color_handler(transformed_cloud, 230, 20, 220);
        viewer.addPointCloud(transformed_cloud, transformed_cloud_color_handler, "transformed_cloud");

	viewer.addCoordinateSystem(1.0, "cloud", 0);
	viewer.setBackgroundColor(0.05, 0.05, 0.05, 0);
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "original_cloud");
        viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "transformed_cloud");

	while (!viewer.wasStopped())
	{
		viewer.spinOnce();
	}

	return 0;

}
  • CMakeLists.txt
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)

project(pcl-matrix_transform)

find_package(PCL 1.7 REQUIRED)

add_executable (matrix_transform matrix_transform.cpp)
target_link_libraries (matrix_transform ${PCL_LIBRARIES})
  • 运行
./matrix_transform rabbit.pcd

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/984469.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【每日一题】1523. 在区间范围内统计奇数数目,860. 柠檬水找零

1523. 在区间范围内统计奇数数目 - 力扣&#xff08;LeetCode&#xff09; 给你两个非负整数 low 和 high 。请你返回 low 和 high 之间&#xff08;包括二者&#xff09;奇数的数目。 示例 1&#xff1a; 输入&#xff1a;low 3, high 7 输出&#xff1a;3 解释&#xff1a;…

Excel文件损坏打不开怎么办?可用这三招解决!

当你的excel文件不可读&#xff0c;或者出现提示“文件已经被损坏&#xff0c;无法打开”&#xff0c;这种情况让人措手不及。而且还会给我们正常的工作带来很多麻烦&#xff0c;文件损坏打不开怎么办&#xff1f;来看看这3招&#xff0c;详细的图文教程&#xff0c;小白也能轻…

Notepad++ 的安装及配置

由于电脑重装了Win11系统&#xff0c;干脆重头开始&#xff0c;重新安装每一个软件~~~ 很多博客或者博主都会推荐notepad的官网&#xff1a;https://notepad-plus-plus.org/ 但大家亲自点开就会发现是无响应&#xff0c;如下图 同时&#xff0c;也会有很多博主直接给网盘地址…

【Flutter】Flutter 使用 table_calendar 实现自定义日历

【Flutter】Flutter 使用 table_calendar 实现自定义日历 文章目录 一、前言二、安装和基本使用三、日历的交互性四、日历事件五、自定义 UI 和 CalendarBuilders六、本地化和语言设置七、完整实际业务代码示例 一、前言 你好&#xff01;今天我要为你介绍一个非常实用的 Flut…

2023高教社杯数学建模国赛的工具箱准备

2023高教社杯数学建模国赛的工具箱准备 数学建模国赛工具箱&#xff08;私信领取&#xff09;&#xff01;&#xff01;&#xff01;小编仔细阅读了比赛官方网站上的规则和要求&#xff0c;以及比赛的题型和时间安排&#xff0c;现总结分享给大家。欢迎私信和评论&#xff0c;…

运维监控系统PIGOSS BSM 业务监控 大屏展现解析

“业务大屏”是 PIGOSS BSM&#xff08;IT运维监控工具&#xff09;的特色功能之一&#xff0c;旨在提供综合而直观的业务监控视图。该功能主要由三个组成部分构成&#xff1a;业务健康度雷达图、业务状态矩阵和多趋势对比图。 下面将对每个部分进行详细介绍&#xff1a; 业务健…

IDEA Java1.8通过sqljdbc4连接sqlserver插入语句

1. 下载sqljdbc4:https://mvnrepository.com/artifact/com.microsoft.sqlserver.jdbc/sqljdbc4/4.0 下载后在IDEA放入仓库内&#xff0c;可以放在resources下&#xff0c;右键“add as library”。 2. 在控制面板中开启Telnet客户端&#xff0c;默认是不开启的。 若报错“ ja…

VMware虚拟机安装运行MacOS系统

VMware虚拟机安装运行MacOS系统 1. VMware虚拟机安装运行MacOS系统1.1. 前期准备 2. 解锁虚拟机MacOS2.1. 解锁后效果 3. 开始安装MacOS系统3.1. 选择系统3.2. 虚拟机磁盘3.3. 镜像 4. 开机配置4.1. MacOS图标4.2. 磁盘4.2.1. 磁盘配置4.2.2. 抹掉数据 4.3. 安装系统4.3.1. 安装…

论文阅读——Co-Salient Object Detection with Co-Representation Purification

目录 基本信息标题摘要引言方法PCSRPP 实验 基本信息 期刊IEEE TPAMI年份2023论文地址https://arxiv.org/pdf/2303.07670.pdf代码地址https://github.com/ZZY816/CoRP 标题 具有共同表示净化的共同显著目标检测 摘要 共同显著目标检测&#xff08;Co-SOD&#xff09;旨在发…

Java使用GraalVM Native Image打包可执行程序

GraalVM Native Image 技术可提前将 Java 代码编译为自包含的可执行文件。只有应用程序运行时所需的代码才会添加到可执行文件中。 也就是说打包体积会很小&#xff0c;不需要考虑设备有没有java环境&#xff0c;也不需要带着笨重的 jre 了 安装过程有很多的坑&#xff0c;愿你…

《Web安全基础》04. 文件操作安全

web 1&#xff1a;文件操作安全2&#xff1a;文件上传漏洞2.1&#xff1a;简介2.2&#xff1a;防护与绕过2.3&#xff1a;WAF 绕过2.3.1&#xff1a;数据溢出2.3.2&#xff1a;符号变异2.3.3&#xff1a;数据截断2.3.4&#xff1a;重复数据 3&#xff1a;文件包含漏洞4&#xf…

Java EE企业级开发学习 -- day1

什么是Java EE? 它是基于Java语言的一种软件设计体系结构&#xff0c;它是一种标准中间件体系结构。它的作用在于能标准化企业级多层结构应用系统的部署&#xff0c;并且简化开发环境。 具体环境的搭建 1.下载压缩包于安装包 jdk-8u261-windows-x64 eclipse-jee-2018-12-…

Navicat15工具连接PostgreSQL15失败

1.错误现象及原因 错误现象&#xff1a; 错误原因&#xff1a; postgresql 15版本中 pg_database 系统表把 datlastsysoid 列删除了&#xff0c;所以造成了此错误。 2.解决方法 &#xff08;1&#xff09;将Navicat工具更新到官网最新版本。 &#xff08;2&#xff09;更换…

如何使用CSS画一个三角形

原理&#xff1a;其实就是规定元素的四个边框颜色及边框宽度&#xff0c;将元素宽高设置为0。如果要哪个方向的三角形&#xff0c;将对应其他三个方向的边框宽和颜色设置为0和透明transparent即可 1.元素设置边框&#xff0c;宽高&#xff0c;背景色 <style>.border {w…

STL vector

文章目录 一、vector 类的模拟实现 vector 是一个动态增长的数组&#xff0c;可以存储任意类型 模板参数 T 表示存储元素的类型&#xff0c;Alloc 是空间配置器&#xff0c;一般不用传 vector 的接口使用和 string 类似&#xff0c;参考 string 一、vector 类的模拟实现 vec…

Facebook 已删除 276.7 亿虚假账户,大量真实用户被“误伤”

据Cyber News消息&#xff0c;正有数以千计的用户在X&#xff08;Twitter&#xff09;及其他平台上表达对Facebook的不满&#xff0c;因为该平台在打击虚假账户时对他们的正常账户进行了“误伤”。 自 2017 年 10 月以来&#xff0c;Facebook 已删除了 276.7 亿个虚假账户&…

函数相关概念

4.函数 1.函数的概念 1.什么是函数? 把特点的代码片段,抽取成为独立运行的实体 2.使用函数的好处1.重复使用,提供效率2.提高代码的可读性3.有利用程序的维护 3.函数的分类1.内置函数(系统函数)已经提高的alert(); prompt();confirm();print()document.write(),console.log()…

实训三:多表查询 - 大学数据库创建与查询实战

大学数据库创建与查询实战 第1关&#xff1a;数据库表设计任务描述相关知识大学数据库的整体设计教师信息表&#xff08;instructor&#xff09;开课信息表&#xff08;section&#xff09; 编程要求测试说明参考代码 第2关&#xff1a;查询&#xff08;一&#xff09;任务描述…

【javaweb】学习日记Day10 - tlias智能管理系统 - 部门、员工管理功能开发

目录 一、建立项目的基本操作步骤 二、前期搭建环境 1、创建springboot工程 ​2、引入对应依赖 3、对建立好的框架进行调试 &#xff08;1&#xff09;pom.xml没有显示蓝色怎么解决&#xff1f; &#xff08;2&#xff09; 启动类为橙红色java文件怎么办&#xff1f; 4…

OSS专栏------文件上传(一)

目录 1、简单上传1.1、流式上传1.1.1、上传字符串1.1.1.1、代码示例1.1.1.2、执行结果 1.1.2、上传Byte数组1.1.2.1、代码示例1.1.2.2、执行结果 1.1.3、上传网络流1.1.3.1、代码示例1.1.3.2、执行结果 1.1.4、上传文件流1.1.4.1、代码示例1.1.4.2、执行结果 1.2、文件上传1.2.…