• 点云拟合平面原理和实现(Halcon)


    最近学习了一下拟合平面的原理,看了这篇文章最小二乘拟合平面(C++版) - 知乎

    讲到了以下几种方法,我这里在halcon中对其一一实现。

    一、算法原理

    1,直接求解法

    2.使用拉格朗日乘子法

    3 SVD分解法  

    二、Halcon实现

    1.各方法对比

    在halcon中其实有对应的算子直接实现拟合平面Ax+By+C=D

    如fit_primitives_object_model_3d 

    我这里取了一张点云图,对其中一小块点云进行平面拟合测试

    取红色圈内一部分数据测试

    直接使用halcon算子 fit_primitives_object_model_3d得到的结果

    [0.376856, -0.602116, -0.703873, -0.553981]

    使用拉格朗日乘子的那个方法得到的结果

    [0.376856, -0.602116, -0.703873, -0.553981]

    第一个直接求解法得到的结果

    [0.376656, -0.601768, -0.704277, -0.554283]

    用SVD方法求解的结果

    [-0.376856, 0.602116, 0.703873, 0.553981]

    结果都一样,除了那个直接求解法的,没有做去质心处理,可能有点细微的差别

    2.halcon代码

    1. read_image (XYZ, '3d_machine_vision/segmentation/3d_primitives_xyz_01.tif')
    2. access_channel (XYZ, X, 1)
    3. access_channel (XYZ, Y, 2)
    4. access_channel (XYZ, Z, 3)
    5. gen_ellipse (ROI_0, 84.5473, 95.7705, rad(-35.9506), 10.9232, 8.60448)
    6. reduce_domain (Z, ROI_0, ImageReduced)
    7. xyz_to_object_model_3d (X, Y, ImageReduced, ObjectModel3D)
    8. *直接使用halcon拟合平面算子处理
    9. fit_primitives_object_model_3d (ObjectModel3D, 'primitive_type', 'plane', ObjectModel3DOut)
    10. get_object_model_3d_params (ObjectModel3DOut, 'primitive_parameter', Result1)
    11. get_object_model_3d_params (ObjectModel3DOut, 'primitive_rms', GenParamValue1)
    12. *获取截取的3d模型x、y、z的坐标值
    13. get_object_model_3d_params (ObjectModel3D, 'point_coord_x', pX)
    14. get_object_model_3d_params (ObjectModel3D, 'point_coord_y', pY)
    15. get_object_model_3d_params (ObjectModel3D, 'point_coord_z', pZ)
    16. *测试用拉格朗日乘子法
    17. Num:=|pX|
    18. *求均值
    19. XM:=mean(pX)
    20. YM:=mean(pY)
    21. ZM:=mean(pZ)
    22. *去质心
    23. DX:=pX-XM
    24. DY:=pY-YM
    25. DZ:=pZ-ZM
    26. *求矩阵各个位置的值
    27. MA11 := sum(DX * DX)
    28. MA22 := sum(DY * DY)
    29. MA33 := sum(DZ * DZ)
    30. MA12 := sum(DX * DY)
    31. MA13 := sum(DX * DZ)
    32. MA23 := sum(DY * DZ)
    33. create_matrix (3, 3, [MA11,MA12,MA13,MA12,MA22,MA23,MA13,MA23,MA33], MatrixID)
    34. *实对称矩阵,求特征值和特征向量
    35. eigenvalues_symmetric_matrix (MatrixID, 'true', EigenvaluesID, EigenvectorsID)
    36. *特征值按小到大排列,所以平面法向量是第一列特征向量
    37. get_value_matrix (EigenvectorsID, 0, 0, NX)
    38. get_value_matrix (EigenvectorsID, 1, 0, NY)
    39. get_value_matrix (EigenvectorsID, 2, 0, NZ)
    40. *算C 平面方程NX*X+NY*Y+NZ*Z=C
    41. C := NX * XM + NY * YM + NZ * ZM
    42. Result2:=[NX,NY,NZ,C]
    43. *对应使用直接求解法
    44. *算矩阵各个位置的值
    45. MB11:=sum(pX*pX)
    46. MB12:=sum(pX*pY)
    47. MB13:=sum(pX)
    48. MB22:=sum(pY*pY)
    49. MB23:=sum(pY)
    50. MB33:=|pX|
    51. MC1:=sum(pX*pZ)
    52. MC2:=sum(pY*pZ)
    53. MC3:=sum(pZ)
    54. create_matrix (3, 3, [MB11,MB12,MB13,MB12,MB22,MB23,MB13,MB23,MB33], MB)
    55. create_matrix (3, 1, [MC1,MC2,MC3], MC)
    56. solve_matrix (MB, 'general', 0, MC, MatrixResultID)
    57. get_full_matrix (MatrixResultID, Values)
    58. *要求a^2+b^2+c^2=1 求解真正的a、c
    59. dd:=Values[0]*Values[0]+Values[1]*Values[1]+1
    60. a:=Values[0]/sqrt(dd)
    61. b:=Values[1]/sqrt(dd)
    62. c:=-1/sqrt(dd)
    63. *因为这里的平面方程为a*x+b*y+c*z=d 与文章中方程A*x+B*y+C*z+D=0中d相差个负号,所以
    64. d:=-Values[2]/sqrt(dd)
    65. Result3:=[a,b,c,d]
    66. *SVD分解法
    67. create_matrix (3, Num, [DX,DY,DZ], A)
    68. transpose_matrix_mod (A)
    69. svd_matrix (A, 'full', 'both', U, S, V)
    70. get_full_matrix (V, VValues)
    71. get_value_matrix (V, 0, 2, Value1)
    72. get_value_matrix (V, 1, 2, Value2)
    73. get_value_matrix (V, 2, 2, Value3)
    74. Value4:=Value1*XM+Value2*YM+Value3*ZM
    75. Result4:=[Value1,Value2,Value3,Value4]

    那个求各个位置的值,可以直接用矩阵相乘好了,简写成

    1. *求特征向量法
    2. create_matrix(3,Num,[DX,DY,DZ],B)
    3. mult_matrix (B, B, 'ABT', MatrixMultID)
    4. eigenvalues_symmetric_matrix (MatrixMultID, 'true', EigenvaluesID1, EigenvectorsID1)
    5. get_full_matrix (EigenvectorsID1, Values3)
    6. aa:=Values3[0]
    7. bb:=Values3[3]
    8. cc:=Values3[6]
    9. dd:=aa*XM+bb*YM+cc*ZM
    10. Result5:=[aa,bb,cc,dd]

  • 相关阅读:
    两个栈实现一个队列,两个队列实现一个栈(C++实现)
    JavaSE 第八章 Java常用类
    【正点原子STM32连载】 第三十一章 睡眠模式实验 摘自【正点原子】APM32F407最小系统板使用指南
    【数据结构】---哈希表
    探索云原生时代:技术驱动的业务架构革新
    java计算机毕业设计ssm求职与招聘网站的设计与实现
    即时通讯开发之Netty入门长文
    制作一个简单HTML静态网页(HTML+CSS)
    动态开点线段树(C++实现)
    基于改进萤火虫算法的图像分割的应用(Matlab代码实现)
  • 原文地址:https://blog.csdn.net/Isaac320/article/details/130886820