三维变换矩阵实战——三维点云的旋转、缩放、镜像、错切、平移、正交投影

ops/2024/10/21 5:32:56/

一、旋转矩阵(右手坐标系)

绕x轴旋转

旋转矩阵:右边矩阵是点云的原始坐标,左边的是旋转矩阵

\begin{bmatrix} 1&0 &0 \\ 0&cos\beta &-sin\beta \\ 0&sin\beta & cos\beta \end{bmatrix}  \begin{bmatrix} x\\ y \\z \end{bmatrix} 

可视化:绕x轴旋转90度

代码:

python">import vtk
import numpy as np
import mathdef pointPolydataCreate(pointCloud):points = vtk.vtkPoints()cells = vtk.vtkCellArray()i = 0for point in pointCloud:points.InsertPoint(i, point[0], point[1], point[2])cells.InsertNextCell(1)cells.InsertCellPoint(i)i += 1PolyData = vtk.vtkPolyData()PolyData.SetPoints(points)PolyData.SetVerts(cells)mapper = vtk.vtkPolyDataMapper()mapper.SetInputData(PolyData)actor = vtk.vtkActor()actor.SetMapper(mapper)actor.GetProperty().SetColor(0.0, 0.1, 1.0)return actordef visiualize(pointCloud, pointCloud2):colors = vtk.vtkNamedColors()actor1 = pointPolydataCreate(pointCloud)actor2 = pointPolydataCreate(pointCloud2)Axes = vtk.vtkAxesActor()# 可视化renderer1 = vtk.vtkRenderer()renderer1.SetViewport(0.0, 0.0, 0.5, 1)renderer1.AddActor(actor1)renderer1.AddActor(Axes)renderer1.SetBackground(colors.GetColor3d('skyblue'))renderer2 = vtk.vtkRenderer()renderer2.SetViewport(0.5, 0.0, 1.0, 1)renderer2.AddActor(actor2)renderer2.AddActor(Axes)renderer2.SetBackground(colors.GetColor3d('skyblue'))renderWindow = vtk.vtkRenderWindow()renderWindow.AddRenderer(renderer1)renderWindow.AddRenderer(renderer2)renderWindow.SetSize(1040, 880)renderWindow.Render()renderWindow.SetWindowName('PointCloud')renderWindowInteractor = vtk.vtkRenderWindowInteractor()renderWindowInteractor.SetRenderWindow(renderWindow)renderWindowInteractor.Initialize()renderWindowInteractor.Start()pointCloud = np.loadtxt("C:/Users/A/Desktop/pointCloudData/model.txt") #读取点云数据angel_x = 90  # 旋转角度
radian = angel_x * np.pi / 180  # 旋转弧度
Rotation_Matrix_1 = [  # 绕x轴三维旋转矩阵 [1, 0, 0],[0, math.cos(radian), -math.sin(radian)],[0, math.sin(radian), math.cos(radian)]]Rotation_Matrix_1 = np.array(Rotation_Matrix_1)p = np.dot(Rotation_Matrix_1, pointCloud.T) # 计算
p = p.T
visiualize(pointCloud, p)

绕y轴旋转

旋转矩阵

\begin{bmatrix} cos\beta &0 &sin\beta \\ 0&1 &0 \\ -sin\beta &0 &cos\beta \end{bmatrix}  \begin{bmatrix} x\\ y \\z \end{bmatrix}

可视化:绕y轴旋转180度

代码:

python">angel_y = 180  # 旋转角度
radian = angel_y * np.pi / 180  # 旋转弧度
Rotation_Matrix_2 = [  # 绕y轴三维旋转矩阵[math.cos(radian), 0, math.sin(radian)],[0, 1, 0],[-math.sin(radian), 0, math.cos(radian)]]Rotation_Matrix_1 = np.array(Rotation_Matrix_1)p = np.dot(Rotation_Matrix_1, pointCloud.T) # 计算
p = p.T
visiualize(pointCloud, p)

绕z轴旋转

旋转矩阵

\begin{bmatrix} cos\beta &-sin\beta &0 \\ sin\beta &cos\beta & 0\\ 0&0 & 1 \end{bmatrix}  \begin{bmatrix} x\\ y \\z \end{bmatrix}

可视化:绕z轴旋转90度

代码:

python">angel_z = 90  # 旋转角度
radian = angel_z * np.pi / 180  # 旋转弧度
Rotation_Matrix_1 = [  # 绕z轴三维旋转矩阵[math.cos(radian), -math.sin(radian), 0],[math.sin(radian), math.cos(radian), 0],[0, 0, 1]]Rotation_Matrix_1 = np.array(Rotation_Matrix_1)p = np.dot(Rotation_Matrix_1, pointCloud.T) # 计算
p = p.T
visiualize(pointCloud, p)

线绕z轴旋转,再绕x轴旋转:

旋转矩阵:  线绕哪个轴转,xyz矩阵就和哪和轴的旋转矩阵先计算

\begin{bmatrix} 1&0 &0 \\ 0&cos\beta &-sin\beta \\ 0&sin\beta & cos\beta \end{bmatrix}  \begin{bmatrix} cos\beta &-sin\beta &0 \\ sin\beta &cos\beta & 0\\ 0&0 & 1 \end{bmatrix}  \begin{bmatrix} x\\ y \\z \end{bmatrix}

可视化:先绕z轴旋转90度,再绕x轴旋转90度

代码:

python">angel_z = 90  # 旋转角度
radian = angel_z * np.pi / 180  # 旋转弧度
Rotation_Matrix_z = [  # 绕z轴三维旋转矩阵[math.cos(radian), -math.sin(radian), 0],[math.sin(radian), math.cos(radian), 0],[0, 0, 1]]angel_x = 90  # 旋转角度
radian = angel_x * np.pi / 180  # 旋转弧度
Rotation_Matrix_x = [  # 绕x轴三维旋转矩阵[1, 0, 0],[0, math.cos(radian), -math.sin(radian)],[0, math.sin(radian), math.cos(radian)]]Rotation_Matrix_z = np.array(Rotation_Matrix_z)
Rotation_Matrix_x = np.array(Rotation_Matrix_x)p = np.dot(Rotation_Matrix_z, pointCloud.T) # 计算
p = np.dot(Rotation_Matrix_x, p) # 计算
p = p.T
visiualize(pointCloud, p)

二、缩放矩阵

缩放矩阵

\begin{bmatrix} k_{x}&0 &0 \\ 0& k_{y} &0 \\ 0&0 &k_{z} \end{bmatrix}

计算过程:三个k是xyz对应的缩放系数

\begin{bmatrix} k_{x}&0 &0 \\ 0& k_{y} &0 \\ 0&0 &k_{z} \end{bmatrix}   \begin{bmatrix} x\\ y \\z \end{bmatrix}= \begin{bmatrix} k_{x}x\\k_{y} y \\k_{z}z \end{bmatrix}

x坐标变为原来的1.5倍,y变为0.7倍,z不变

\begin{bmatrix} 1.5&0 &0 \\ 0& 0.7 &0 \\ 0&0 &1 \end{bmatrix}   \begin{bmatrix} x\\ y \\z \end{bmatrix}= \begin{bmatrix} 1.5x\\0.7 y \\1z \end{bmatrix}

可视化:

三、镜像矩阵

3D镜像矩阵

\begin{bmatrix} 1-2n_x{}^{2} & -2n_x{}n_{y} &-2n_x{}n_{z} \\ -2n_x{}n_{y} &1-2n_y{}^{2} &-2n_y{}n_{z} \\ -2n_x{}n_{z} &-2n_y{}n_{z} & 1-2n_z{}^{2} \end{bmatrix}

 n=\begin{bmatrix} n_{x} &n_{y} & n_{z} \end{bmatrix}

向量n是垂直于镜像平面的单位向量

三维点云对xz平面的镜像:

①首先,确定一个垂直于xz平面的单位向量 n=[0, 1, 0]

②将该单位向量带入上述3D镜像矩阵

可视化:

代码:

python">import vtk
import numpy as np
import mathdef pointPolydataCreate(pointCloud):points = vtk.vtkPoints()cells = vtk.vtkCellArray()i = 0for point in pointCloud:points.InsertPoint(i, point[0], point[1], point[2])cells.InsertNextCell(1)cells.InsertCellPoint(i)i += 1PolyData = vtk.vtkPolyData()PolyData.SetPoints(points)PolyData.SetVerts(cells)mapper = vtk.vtkPolyDataMapper()mapper.SetInputData(PolyData)actor = vtk.vtkActor()actor.SetMapper(mapper)actor.GetProperty().SetColor(0.0, 0.1, 1.0)return actordef visiualize(pointCloud, pointCloud2):colors = vtk.vtkNamedColors()actor1 = pointPolydataCreate(pointCloud)actor2 = pointPolydataCreate(pointCloud2)Axes = vtk.vtkAxesActor()# 可视化renderer1 = vtk.vtkRenderer()renderer1.SetViewport(0.0, 0.0, 0.5, 1)renderer1.AddActor(actor1)renderer1.AddActor(Axes)renderer1.SetBackground(colors.GetColor3d('skyblue'))renderer2 = vtk.vtkRenderer()renderer2.SetViewport(0.5, 0.0, 1.0, 1)renderer2.AddActor(actor1)renderer2.AddActor(actor2)renderer2.AddActor(Axes)renderer2.SetBackground(colors.GetColor3d('skyblue'))renderWindow = vtk.vtkRenderWindow()renderWindow.AddRenderer(renderer1)renderWindow.AddRenderer(renderer2)renderWindow.SetSize(1040, 880)renderWindow.Render()renderWindow.SetWindowName('PointCloud')renderWindowInteractor = vtk.vtkRenderWindowInteractor()renderWindowInteractor.SetRenderWindow(renderWindow)renderWindowInteractor.Initialize()renderWindowInteractor.Start()pointCloud = np.loadtxt("C:/Users/A/Desktop/pointCloudData/model.txt") #读取点云数据nx = 0
ny = 0
nz = 1
n = [nx, ny, nz] # 垂直xy平面的单位向量
# 镜像矩阵
Mirror_Matrix = [[1-2*nx**2, -2*nx*ny, -2*nx*nz],[-2*nx*ny, 1-2*ny**2, -2*ny*nz],[-2*nx*nz, -2*ny*nz, 1-2*nz**2]]Mirror_Matrix = np.array(Mirror_Matrix)p = np.dot(Mirror_Matrix, pointCloud.T)  # 计算
p = p.T
visiualize(pointCloud, p)

四、错切矩阵     

沿xy平面错切(z不变)                

                             矩阵                                                计算过程

H_{xy}(s, t)=\begin{bmatrix} 1 &0 &s \\ 0&1 &t \\ 0&0 &1 \end{bmatrix}                      \begin{bmatrix} 1 &0 &s \\ 0&1 &t \\ 0&0 &1 \end{bmatrix} \begin{bmatrix} x\\ y \\ z \end{bmatrix}=\begin{bmatrix} x+sz\\y+tz \\ z \end{bmatrix}

沿xz平面错切(y不变) 

                             矩阵                                                计算过程

H_{xz}(s, t)=\begin{bmatrix} 1 &0 &s \\ 0&1 &0 \\ 0&t &1 \end{bmatrix}                      \begin{bmatrix} 1 &0 &s \\ 0&1 &0 \\ 0&t &1 \end{bmatrix} \begin{bmatrix} x\\ y \\ z \end{bmatrix}=\begin{bmatrix} x+sz\\y \\ z+ty \end{bmatrix}

沿yz平面错切(x不变)

                             矩阵                                                计算过程

H_{yz}(s, t)=\begin{bmatrix} 1 &0 &0 \\ s&1 &0 \\ t&0 &1 \end{bmatrix}                      \begin{bmatrix} 1 &0 &0 \\ s&1 &0 \\ t&0 &1 \end{bmatrix} \begin{bmatrix} x\\ y \\ z \end{bmatrix}=\begin{bmatrix} x\\y+sx \\ z+tx \end{bmatrix}

可视化:沿yz平面错切

代码:

python">pointCloud = np.loadtxt("C:/Users/A/Desktop/pointCloudData/model.txt") #读取点云数据s = 0.3
t = 0.3
# 沿yz平面错切矩阵
Shear_Matrix = [[1, 0, 0],[s, 1, 0],[t, 0, 1]]Shear_Matrix = np.array(Shear_Matrix)p = np.dot(Shear_Matrix, pointCloud.T)  # 计算
p = p.T
visiualize(pointCloud, p)

五、正交投影

正交投影矩阵(投影到三维空间任意平面):

\begin{bmatrix} 1-n_{x}^{2} &-n_{x}n_{y} &-n_{x}n_{z} \\ -n_{x}n_{y}&1-n_{y}^{2} &-n_{y}n_{z} \\ -n_{x}n_{z}&-n_{y}n_{z} & 1-n_{z}^{2} \end{bmatrix}

n=\begin{bmatrix} n_{x} &n_{y} & n_{z} \end{bmatrix}

向量n是垂直于投影平面的单位向量

可视化:点云在xy平面上的正交投影

           

六、平移矩阵

平移矩阵需要利用齐次矩阵(4*4矩阵),下面是一个平移矩阵

最右边一列是xyz的位移量

\begin{bmatrix} 1 &0 &0 & \Delta x \\ 0&1 &0 &\Delta y \\ 0&0 &1 & \Delta z\\ 0&0 & 0 & 1 \end{bmatrix}

计算过程:

\begin{bmatrix} 1 &0 &0 & \Delta x \\ 0&1 &0 &\Delta y \\ 0&0 &1 & \Delta z\\ 0&0 & 0 & 1 \end{bmatrix}   \begin{bmatrix} x\\y \\z \\ 1 \end{bmatrix}=\begin{bmatrix} x+\Delta x\\ y+\Delta y \\ z+\Delta z \\ 1 \end{bmatrix}

线性变换+平移:

增加的平移对原来的线性变换没影响,可以将前面介绍的变换矩阵和平移结合

例如:沿xy平面错切+平移

\begin{bmatrix} 1&0 &s &\Delta x \\ 0&1 &t &\Delta y \\ 0&0 &1 &\Delta z \\ 0& 0& 0 & 1 \end{bmatrix}


http://www.ppmy.cn/ops/34341.html

相关文章

Midjourney之语义分割及权重符号的使用

hello 小伙伴们,我是你们的老朋友——树下,今天分享Midjourney提示词的语义分割及权重的使用,话不多说,直接开始~ 分割语义: 用 | 来表示,用来分割关键词的语义,能更精确表达意思 增加权重&am…

死锁

文章目录 死锁 死锁 public class MyThread extends Thread {//创建锁对象static Object objA new Object();static Object objB new Object();Overridepublic void run() {while (true) {if (getName().equals("线程1")) {synchronized (objA) {System.out.print…

解决git合并冲突

解决Git请求合并冲突通常涉及以下步骤: 了解冲突: 当Git在合并过程中无法自动解决文件差异时,它会产生冲突。 你可以通过查看Git的输出或检查冲突文件的特殊标记来识别冲突。 查看冲突文件: 打开Git告诉你存在冲突的文件。 你…

基于 Dockerfile 部署nginx服务(实现HTTPS功能)

目录 前言 1、任务要求 2、建立工作目录并上传nginx安装包 3、创建自签名证书 4、创建 nginx Dockerfile 文件 5、准备并编写 nginx.conf 配置文件 6、准备nginx页面文件 7、工作目录文件结构 8、生成镜像 8、启动容器并开启宿主机端口映射 9、浏览器测试 前言 Ngi…

Docker 入门与实践:从零开始构建容器化应用环境

Docker 一、docker常用命令docker ps 格式化输出Linux设置命令别名 二、数据卷相关命令挂载到默认目录(/var/lib/docker)挂载到本地目录 三、自定义镜像Dockerfile构建镜像的命令 四、网络自定义网络 五、DockerCompose相关命令 一、docker常用命令 dock…

K8s: Helm包管理工具的应用以及项目分环境部署

Helm 概述与安装 1 ) 概述 k8s中官方包管理工具, 官网: https://helm.sh/用 Yaml 管理多个应用同时部署 不需要在不同的yaml中写两遍,执行两遍解决一键部署的问题,联合部署 实现了部署的版本管理 可以实现版本回滚 应用和配置分离 2 )安装 …

建材物料小程序商城的作用是什么

建材物料如门窗、马桶、涂料、瓷砖等有着大量需求者,传统模式中客户主要是同城进店咨询查看,但随时电商深入生活和商家模式更新,如今线上店铺消费也同样火热。 尤其是厂商或品牌经销商,无论线下还是线上都不影响生意开展&#xf…

如何从大量单号中,一键批量筛选出物流延误的单号

先来给大家看下例子,下面这个表格里面有3000多个单号 总有些单号物流信息不能及时更新,比如物流走到某中转站就停留在哪里超过24小时甚至更长时间,我们要如何慧眼识珠讯速找出来,及时查明原因并解决问题呢如下图:这个单…