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

目录

        • 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; // 旋转角度//方法一: Matrix4fEigen::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;//方法二: Affine3fEigen::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.hqwc.cn/news/102254.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php 获取今日、昨日、上周、本月的起始时间戳和结束时间戳的方法非常简单

php 获取今日、昨日、上周、本月的起始时间戳和结束时间戳的方法&#xff0c;主要使用到了 php 的时间函数 mktime。下面首先还是以示例说明如何使用 mktime 获取今日、昨日、上周、本月的起始时间戳和结束时间戳&#xff0c;然后在介绍一下 mktime 函数作用和用法。非常简单哦…

使用ChatGLMTokenizer处理json格式数据

我下载了一些中文wikipedia数据&#xff0c;准备采用ChatGLMTokenizer对齐进行清洗&#xff0c;整理为预训练语料。 import numpy as np import json from tqdm import tqdm from chatglm_tokenizer.tokenization_chatglm import ChatGLMTokenizertokenizer ChatGLMTokenizer…

Python超入门(1)__迅速上手操作掌握Python

# 1.第一个代码&#xff1a;输出语句 # 1.第一个代码&#xff1a;输出语句 print("My dogs name is Huppy!") print(o----) print( ||| ) print("*" * 10) """ 输出结果&#xff1a; My dogs name is Huppy! o----||| ********** "&…

如何让自己的精力集中 Maven自学笔记 马云演讲观看

目录 如何让自己的精力集中 Avoid having multiple tasks and objects in your line of sight 人的脑袋是给自己思考用的 晚上床上想千条路&#xff0c;早上起床还是走原路 参与才会变得更好 共度灾难&#xff0c;是需要互相鼓励的 CFO Capital 上海各区都有哪些大学?…

奥菲斯办公

下载 运行 移除旧组件&#xff0c;移除之后重启电脑 部署&#xff0c;如图设置 下载&#xff0c;1.5GB&#xff0c;点击上方的开始部署。部署完成后。 安装许可证&#xff0c;安装成功后才能安装许可证 找一个 KMS 主机输入 主机列表 点击上方激活&#xff0c;有效…

2023数学建模国赛选题建议及BC题思路

大家好呀&#xff0c;全国大学生数学建模竞赛今天下午开赛啦&#xff0c;在这里先带来初步的选题建议及思路。 目前团队正在写B题和C题完整论文&#xff0c;后续还会持续更新哈&#xff0c;以下只是比较简略的图文版讲解&#xff0c;团队目前正在写B、C题完整论文&#xff0c;…

LeetCode 1113.报告的记录

数据准备 Create table If Not Exists Actions (user_id int, post_id int, action_date date, action ENUM(view, like, reaction, comment, report, share), extra varchar(10)); Truncate table Actions; insert into Actions (user_id, post_id, action_date, action, ext…

差异化竞争阵地的所在【周技术进阶】-从BS 项目C#最基础截取字符串方法开始

效果 代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace ConsoleAppNumberOneHelloWorld {class Program{static void Main(string[] args){Console.WriteLine("hello world&#xf…

MonoDETR: Depth-guided Transformer for Monocular 3D Object Detection 论文解读

文章目录 1.Abstract2. Introduction3. Related workDETR base methods 4. Method4.1Feature ExtractionVisual Featuresdepth featuresforeground depth map 4. 2 Depth guided transformerVisual and depth encodersDepth-guided-decoderDepth positional encoding 4. 3 Dete…

Golang专题精进

Golang专题精进 Golang单元测试Golang错误处理Golang正则表达式Golang反射Golang验证码Golang日期时间处理库CarbonGolang发送邮件库emailGolang log日志Golang log日志框架logrusGolang加密和解密应用Golang访问权限控制框架casbinGolang使用swagger生成api接口文档Golang jwt…

css强制显示一行

要强制将文本内容显示在一行中&#xff0c;可以使用CSS的white-space属性和overflow属性来实现。 首先&#xff0c;将white-space属性设置为nowrap&#xff0c;这样文本内容就不会换行。然后&#xff0c;将overflow属性设置为hidden&#xff0c;这样超出一行的内容就会被隐藏起…

Apache Tomcat 漏洞复现

文章目录 Apache Tomcat 漏洞复现1. Tomcat7 弱密码和后端 Getshell 漏洞1.1 漏洞描述1.2 漏洞复现1.3 漏洞利用1.3.1 jsp小马1.3.2 jsp大马 2. Aapache Tomcat AJP任意文件读取/包含漏洞2.1 漏洞描述2.1 漏洞复现2.2 漏洞利用工具 3. 通过 PUT 方法的 Tomcat 任意写入文件漏洞…