当前位置:   article > 正文

Halcon 用点来拟合平面_halcon 拟合平面

halcon 拟合平面

一、简介

项目要求用多个点来拟合一个平面,然后再用其他平面上的点来计算这个点到平面的距离,halcon 有现成的拟合函数。

MatLab 版本:Matlab 最小二乘法 拟合平面_Σίσυφος1900的博客-CSDN博客

二、算子解释

  1. *输入点云数据然后生成3D模型
  2. gen_object_model_3d_from_points(X, Y, Z, ObjectModel3D)
  3. * X, Y, Z 分别是点x、y、z方向上的集合
  4. * ObjectModel3D 是输出的3D模型
  1. *拟合成想要的平面
  2. fit_primitives_object_model_3d (ObjectModel3D, ['primitive_type','fitting_algorithm'], ['plane','least_squares_tukey'], ObjectModel3DOut)
  3. *fit_primitives_object_model_3d( : : ObjectModel3D, ParamName, ParamValue : ObjectModel3DOut)
  4. *ObjectModel3D:输入模型
  5. *ParamName:拟合的参数 :fitting_algorithm, max_radius, min_radius, output_point_coord, output_xyz_mapping, primitive_type
  6. *ParamValue:对应'primitive_type'------'cylinder'(圆柱体), 'sphere'(球体), 'plane'(平面)。对应'primitive_type'------'least_squares', 'least_squares_huber', 'least_squares_tukey'几种最小二乘法,这里选择plane和least_squares
  7. *ObjectModel3DOut:输出的平面

三、代码演示

  1. X:=[-0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04, -0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04, -0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04, -0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04, -0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04, -0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04, -0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04, -0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04, -0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04]
  2. Y:=[-0.04, -0.04, -0.04, -0.04, -0.04, -0.04, -0.04, -0.04, -0.04, -0.03, -0.03, -0.03, -0.03, -0.03, -0.03, -0.03, -0.03, -0.03, -0.02, -0.02, -0.02, -0.02, -0.02, -0.02, -0.02, -0.02, -0.02, -0.01, -0.01, -0.01, -0.01, -0.01, -0.01, -0.01, -0.01, -0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04]
  3. Z:=[-0.0, -0.0, -0.0, -0.0, -0.1, -0.0, -0.0, -0.1, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, 0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0]
  4. *输入点云数据然后生成3D模型
  5. gen_object_model_3d_from_points(X, Y, Z, ObjectModel3D)
  6. dev_open_window(0, 0, 512, 512, 'black', WindowHandle)
  7. *拟合成想要的平面
  8. fit_primitives_object_model_3d (ObjectModel3D, ['primitive_type','fitting_algorithm'], ['plane','least_squares_tukey'], ObjectModel3DOut)
  9. *fit_primitives_object_model_3d( : : ObjectModel3D, ParamName, ParamValue : ObjectModel3DOut)
  10. *ObjectModel3D:输入模型
  11. *ParamName:拟合的参数 :fitting_algorithm, max_radius, min_radius, output_point_coord, output_xyz_mapping, primitive_type
  12. *ParamValue:对应'primitive_type'------'cylinder'(圆柱体), 'sphere'(球体), 'plane'(平面)。对应'primitive_type'------'least_squares', 'least_squares_huber', 'least_squares_tukey'几种最小二乘法,这里选择plane和least_squares
  13. *ObjectModel3DOut:输出的平面
  14. visualize_object_model_3d (WindowHandle,[ObjectModel3D,ObjectModel3DOut], [],[], \
  15. ['color_0','color_1','alpha_1','disp_pose'], ['green','gray',0.5,'true'],'RectBOX', [], [], Pose)
  16. *获取法向量,Normal的前三个数值就是单位法向量
  17. get_object_model_3d_params (ObjectModel3DOut, 'primitive_parameter', Normals)

 平面方程:ax+by+cz+d=0;

  1. gen_object_model_3d_from_points(X, Y, Z, ObjectModel3D)
  2. paraName:=['primitive_type', 'fitting_algorithm']
  3. paraVal:=['plane', 'least_squares_tukey']
  4. fit_primitives_object_model_3d(ObjectModel3D, ['primitive_type', 'fitting_algorithm'], ['plane', 'least_squares_tukey'], ObjectModel3DOut)
  5. get_object_model_3d_params(ObjectModel3DOut, 'primitive_parameter', plane)
  6. * 计算平面方程(a,b,c,d)
  7. A:= plane[0]
  8. B:= plane[1]
  9. C:= plane[2]
  10. D:= plane[3]

那么计算点到平面的距离就是:

Distance:=a*X + b*Y + c*Z - d
  1. X:=[-0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04, -0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04, -0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04, -0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04, -0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04, -0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04, -0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04, -0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04, -0.04, -0.03, -0.02, -0.01, 0.0, 0.01, 0.02, 0.03, 0.04]
  2. Y:=[-0.04, -0.04, -0.04, -0.04, -0.04, -0.04, -0.04, -0.04, -0.04, -0.03, -0.03, -0.03, -0.03, -0.03, -0.03, -0.03, -0.03, -0.03, -0.02, -0.02, -0.02, -0.02, -0.02, -0.02, -0.02, -0.02, -0.02, -0.01, -0.01, -0.01, -0.01, -0.01, -0.01, -0.01, -0.01, -0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04]
  3. Z:=[-0.0, -0.0, -0.0, -0.0, -0.1, -0.0, -0.0, -0.1, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, 0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0, -0.0]
  4. gen_object_model_3d_from_points(X, Y, Z, ObjectModel3D)
  5. paraName:=['primitive_type', 'fitting_algorithm']
  6. paraVal:=['plane', 'least_squares_tukey']
  7. fit_primitives_object_model_3d(ObjectModel3D, ['primitive_type', 'fitting_algorithm'], ['plane', 'least_squares_tukey'], ObjectModel3DOut)
  8. get_object_model_3d_params(ObjectModel3DOut, 'primitive_parameter', plane)
  9. * 计算平面方程(a,b,c,d)
  10. A:= plane[0]
  11. B:= plane[1]
  12. C:= plane[2]
  13. D:= plane[3]
  14. x:=[-0.04, -0.03, -0.02, -0.01]
  15. y:=[-0.04, -0.04, -0.04, -0.04]
  16. z:=[-0.0, -1.0, 10.0, 30.0]
  17. Distance:=A*x +B*y + C*z - D

四、用最小二乘法来拟合的平面

【MQ笔记】超简单的最小二乘法拟合平面(Python)_M&Q的博客-CSDN博客_最小二乘法拟合平面

 上述方程可以用A\cdot X=b来表示。由于A是一个m\times n的矩阵,因此我们先在等号两边分别乘以 转置矩阵A^{T},使系数矩阵变为n\times n的方阵,之后,通过乘以系数矩阵的逆矩阵求解,也就是说,X=(AA^{T})^{-1}A^{T}b

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from mpl_toolkits.mplot3d import Axes3D
  4. # 创建函数,用于生成不同属于一个平面的100个离散点
  5. def not_all_in_plane(a, b, c):
  6. x = np.random.uniform(-10, 10, size=100)
  7. y = np.random.uniform(-10, 10, size=100)
  8. z = (a * x + b * y + c) + np.random.normal(-1, 1, size=100)
  9. return x, y, z
  10. # 调用函数,生成离散点
  11. x, y, z = not_all_in_plane(2, 5, 6)
  12. # 创建系数矩阵A
  13. a = 0
  14. A = np.ones((100, 3))
  15. for i in range(0, 100):
  16. A[i, 0] = x[a]
  17. A[i, 1] = y[a]
  18. a = a + 1
  19. # print(A)
  20. # 创建矩阵b
  21. b = np.zeros((100, 1))
  22. a = 0
  23. for i in range(0, 100):
  24. b[i, 0] = z[a]
  25. a = a + 1
  26. # print(b)
  27. # 通过X=(AT*A)-1*AT*b直接求解
  28. A_T = A.T
  29. A1 = np.dot(A_T, A)
  30. A2 = np.linalg.inv(A1)
  31. A3 = np.dot(A2, A_T)
  32. X = np.dot(A3, b)
  33. print('平面拟合结果为:z = %.3f * x + %.3f * y + %.3f' % (X[0, 0], X[1, 0], X[2, 0]))
  34. # 计算方差
  35. R = 0
  36. for i in range(0, 100):
  37. R = R + (X[0, 0] * x[i] + X[1, 0] * y[i] + X[2, 0] - z[i]) ** 2
  38. print('方差为:%.*f' % (3, R))
  39. # 展示图像
  40. fig1 = plt.figure()
  41. ax1 = fig1.add_subplot(111, projection='3d')
  42. ax1.set_xlabel("x")
  43. ax1.set_ylabel("y")
  44. ax1.set_zlabel("z")
  45. ax1.scatter(x, y, z, c='r', marker='o')
  46. x_p = np.linspace(-10, 10, 100)
  47. y_p = np.linspace(-10, 10, 100)
  48. x_p, y_p = np.meshgrid(x_p, y_p)
  49. z_p = X[0, 0] * x_p + X[1, 0] * y_p + X[2, 0]
  50. ax1.plot_wireframe(x_p, y_p, z_p, rstride=10, cstride=10)
  51. plt.show()

 

利用最小二乘法公式求导
通过离散点拟合平面,也就是说,要找到一个平面(),使这平面到各个点的“距离”最近,根据最小二乘法,,也就是说我们要求得一组a,b,c,使得对于已有的离散点来说,S的值最小。

求解该恰定方程即可得到a,b,c。上述方程也可以用表示,该方程可以通过两边同时乘以系数矩阵的逆矩阵求得,即X=A^{-1}Ab

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from mpl_toolkits.mplot3d import Axes3D
  4. # 创建函数,用于生成不同属于一个平面的100个离散点
  5. def not_all_in_plane(a, b, c):
  6. x = np.random.uniform(-10, 10, size=100)
  7. y = np.random.uniform(-10, 10, size=100)
  8. z = (a * x + b * y + c) + np.random.normal(-1,1,size=100)
  9. return x, y, z
  10. # 调用函数,生成离散点
  11. x2, y2, z2 = not_all_in_plane(2, 5, 6)
  12. #创建系数矩阵A
  13. A=np.zeros((3,3))
  14. for i in range(0,100):
  15. A[0,0]=A[0,0]+x2[i]**2
  16. A[0,1]=A[0,1]+x2[i]*y2[i]
  17. A[0,2]=A[0,2]+x2[i]
  18. A[1,0]=A[0,1]
  19. A[1,1]=A[1,1]+y2[i]**2
  20. A[1,2]=A[1,2]+y2[i]
  21. A[2, 0] = A[0,2]
  22. A[2, 1] = A[1, 2]
  23. A[2, 2] = 100
  24. #print(A)
  25. #创建b
  26. b = np.zeros((3,1))
  27. for i in range(0,100):
  28. b[0,0]=b[0,0]+x2[i]*z2[i]
  29. b[1,0]=b[1,0]+y2[i]*z2[i]
  30. b[2,0]=b[2,0]+z2[i]
  31. #print(b)
  32. #求解X
  33. A_inv=np.linalg.inv(A)
  34. X = np.dot(A_inv, b)
  35. print('平面拟合结果为:z = %.3f * x + %.3f * y + %.3f'%(X[0,0],X[1,0],X[2,0]))
  36. #计算方差
  37. R=0
  38. for i in range(0,100):
  39. R=R+(X[0, 0] * x2[i] + X[1, 0] * y2[i] + X[2, 0] - z2[i])**2
  40. print ('方差为:%.*f'%(3,R))
  41. # 展示图像
  42. fig1 = plt.figure()
  43. ax1 = fig1.add_subplot(111, projection='3d')
  44. ax1.set_xlabel("x")
  45. ax1.set_ylabel("y")
  46. ax1.set_zlabel("z")
  47. ax1.scatter(x2,y2,z2,c='r',marker='o')
  48. x_p = np.linspace(-10, 10, 100)
  49. y_p = np.linspace(-10, 10, 100)
  50. x_p, y_p = np.meshgrid(x_p, y_p)
  51. z_p = X[0, 0] * x_p + X[1, 0] * y_p + X[2, 0]
  52. ax1.plot_wireframe(x_p, y_p, z_p, rstride=10, cstride=10)
  53. plt.show()

 

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

闽ICP备14008679号