当前位置:   article > 正文

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

点云旋转平移

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

绕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度

代码:

  1. import vtk
  2. import numpy as np
  3. import math
  4. def pointPolydataCreate(pointCloud):
  5. points = vtk.vtkPoints()
  6. cells = vtk.vtkCellArray()
  7. i = 0
  8. for point in pointCloud:
  9. points.InsertPoint(i, point[0], point[1], point[2])
  10. cells.InsertNextCell(1)
  11. cells.InsertCellPoint(i)
  12. i += 1
  13. PolyData = vtk.vtkPolyData()
  14. PolyData.SetPoints(points)
  15. PolyData.SetVerts(cells)
  16. mapper = vtk.vtkPolyDataMapper()
  17. mapper.SetInputData(PolyData)
  18. actor = vtk.vtkActor()
  19. actor.SetMapper(mapper)
  20. actor.GetProperty().SetColor(0.0, 0.1, 1.0)
  21. return actor
  22. def visiualize(pointCloud, pointCloud2):
  23. colors = vtk.vtkNamedColors()
  24. actor1 = pointPolydataCreate(pointCloud)
  25. actor2 = pointPolydataCreate(pointCloud2)
  26. Axes = vtk.vtkAxesActor()
  27. # 可视化
  28. renderer1 = vtk.vtkRenderer()
  29. renderer1.SetViewport(0.0, 0.0, 0.5, 1)
  30. renderer1.AddActor(actor1)
  31. renderer1.AddActor(Axes)
  32. renderer1.SetBackground(colors.GetColor3d('skyblue'))
  33. renderer2 = vtk.vtkRenderer()
  34. renderer2.SetViewport(0.5, 0.0, 1.0, 1)
  35. renderer2.AddActor(actor2)
  36. renderer2.AddActor(Axes)
  37. renderer2.SetBackground(colors.GetColor3d('skyblue'))
  38. renderWindow = vtk.vtkRenderWindow()
  39. renderWindow.AddRenderer(renderer1)
  40. renderWindow.AddRenderer(renderer2)
  41. renderWindow.SetSize(1040, 880)
  42. renderWindow.Render()
  43. renderWindow.SetWindowName('PointCloud')
  44. renderWindowInteractor = vtk.vtkRenderWindowInteractor()
  45. renderWindowInteractor.SetRenderWindow(renderWindow)
  46. renderWindowInteractor.Initialize()
  47. renderWindowInteractor.Start()
  48. pointCloud = np.loadtxt("C:/Users/A/Desktop/pointCloudData/model.txt") #读取点云数据
  49. angel_x = 90 # 旋转角度
  50. radian = angel_x * np.pi / 180 # 旋转弧度
  51. Rotation_Matrix_1 = [ # 绕x轴三维旋转矩阵
  52. [1, 0, 0],
  53. [0, math.cos(radian), -math.sin(radian)],
  54. [0, math.sin(radian), math.cos(radian)]]
  55. Rotation_Matrix_1 = np.array(Rotation_Matrix_1)
  56. p = np.dot(Rotation_Matrix_1, pointCloud.T) # 计算
  57. p = p.T
  58. 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度

代码:

  1. angel_y = 180 # 旋转角度
  2. radian = angel_y * np.pi / 180 # 旋转弧度
  3. Rotation_Matrix_2 = [ # 绕y轴三维旋转矩阵
  4. [math.cos(radian), 0, math.sin(radian)],
  5. [0, 1, 0],
  6. [-math.sin(radian), 0, math.cos(radian)]]
  7. Rotation_Matrix_1 = np.array(Rotation_Matrix_1)
  8. p = np.dot(Rotation_Matrix_1, pointCloud.T) # 计算
  9. p = p.T
  10. 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度

代码:

  1. angel_z = 90 # 旋转角度
  2. radian = angel_z * np.pi / 180 # 旋转弧度
  3. Rotation_Matrix_1 = [ # 绕z轴三维旋转矩阵
  4. [math.cos(radian), -math.sin(radian), 0],
  5. [math.sin(radian), math.cos(radian), 0],
  6. [0, 0, 1]]
  7. Rotation_Matrix_1 = np.array(Rotation_Matrix_1)
  8. p = np.dot(Rotation_Matrix_1, pointCloud.T) # 计算
  9. p = p.T
  10. 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度

代码:

  1. angel_z = 90 # 旋转角度
  2. radian = angel_z * np.pi / 180 # 旋转弧度
  3. Rotation_Matrix_z = [ # 绕z轴三维旋转矩阵
  4. [math.cos(radian), -math.sin(radian), 0],
  5. [math.sin(radian), math.cos(radian), 0],
  6. [0, 0, 1]]
  7. angel_x = 90 # 旋转角度
  8. radian = angel_x * np.pi / 180 # 旋转弧度
  9. Rotation_Matrix_x = [ # 绕x轴三维旋转矩阵
  10. [1, 0, 0],
  11. [0, math.cos(radian), -math.sin(radian)],
  12. [0, math.sin(radian), math.cos(radian)]]
  13. Rotation_Matrix_z = np.array(Rotation_Matrix_z)
  14. Rotation_Matrix_x = np.array(Rotation_Matrix_x)
  15. p = np.dot(Rotation_Matrix_z, pointCloud.T) # 计算
  16. p = np.dot(Rotation_Matrix_x, p) # 计算
  17. p = p.T
  18. 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镜像矩阵

可视化:

代码:

  1. import vtk
  2. import numpy as np
  3. import math
  4. def pointPolydataCreate(pointCloud):
  5. points = vtk.vtkPoints()
  6. cells = vtk.vtkCellArray()
  7. i = 0
  8. for point in pointCloud:
  9. points.InsertPoint(i, point[0], point[1], point[2])
  10. cells.InsertNextCell(1)
  11. cells.InsertCellPoint(i)
  12. i += 1
  13. PolyData = vtk.vtkPolyData()
  14. PolyData.SetPoints(points)
  15. PolyData.SetVerts(cells)
  16. mapper = vtk.vtkPolyDataMapper()
  17. mapper.SetInputData(PolyData)
  18. actor = vtk.vtkActor()
  19. actor.SetMapper(mapper)
  20. actor.GetProperty().SetColor(0.0, 0.1, 1.0)
  21. return actor
  22. def visiualize(pointCloud, pointCloud2):
  23. colors = vtk.vtkNamedColors()
  24. actor1 = pointPolydataCreate(pointCloud)
  25. actor2 = pointPolydataCreate(pointCloud2)
  26. Axes = vtk.vtkAxesActor()
  27. # 可视化
  28. renderer1 = vtk.vtkRenderer()
  29. renderer1.SetViewport(0.0, 0.0, 0.5, 1)
  30. renderer1.AddActor(actor1)
  31. renderer1.AddActor(Axes)
  32. renderer1.SetBackground(colors.GetColor3d('skyblue'))
  33. renderer2 = vtk.vtkRenderer()
  34. renderer2.SetViewport(0.5, 0.0, 1.0, 1)
  35. renderer2.AddActor(actor1)
  36. renderer2.AddActor(actor2)
  37. renderer2.AddActor(Axes)
  38. renderer2.SetBackground(colors.GetColor3d('skyblue'))
  39. renderWindow = vtk.vtkRenderWindow()
  40. renderWindow.AddRenderer(renderer1)
  41. renderWindow.AddRenderer(renderer2)
  42. renderWindow.SetSize(1040, 880)
  43. renderWindow.Render()
  44. renderWindow.SetWindowName('PointCloud')
  45. renderWindowInteractor = vtk.vtkRenderWindowInteractor()
  46. renderWindowInteractor.SetRenderWindow(renderWindow)
  47. renderWindowInteractor.Initialize()
  48. renderWindowInteractor.Start()
  49. pointCloud = np.loadtxt("C:/Users/A/Desktop/pointCloudData/model.txt") #读取点云数据
  50. nx = 0
  51. ny = 0
  52. nz = 1
  53. n = [nx, ny, nz] # 垂直xy平面的单位向量
  54. # 镜像矩阵
  55. Mirror_Matrix = [
  56. [1-2*nx**2, -2*nx*ny, -2*nx*nz],
  57. [-2*nx*ny, 1-2*ny**2, -2*ny*nz],
  58. [-2*nx*nz, -2*ny*nz, 1-2*nz**2]]
  59. Mirror_Matrix = np.array(Mirror_Matrix)
  60. p = np.dot(Mirror_Matrix, pointCloud.T) # 计算
  61. p = p.T
  62. 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平面错切

代码:

  1. pointCloud = np.loadtxt("C:/Users/A/Desktop/pointCloudData/model.txt") #读取点云数据
  2. s = 0.3
  3. t = 0.3
  4. # 沿yz平面错切矩阵
  5. Shear_Matrix = [
  6. [1, 0, 0],
  7. [s, 1, 0],
  8. [t, 0, 1]]
  9. Shear_Matrix = np.array(Shear_Matrix)
  10. p = np.dot(Shear_Matrix, pointCloud.T) # 计算
  11. p = p.T
  12. 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}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/242590?site
推荐阅读