• 点云配准(四) Sparse Point Registration 算法浅析


            Sparse Point Registration (SPR)是一篇2017年的点云配准算法,该算法的主要目的是对稀疏点云进行配准,并且取得了不错的成果和突破。本文一方面是对SPR配准算法模型进行了简单的原理解析以及附加代码实现,另一方面是对之前工作的总结,也算水篇博文,接下来的工作主要就是分割和光流预测方面的学习了。

    一.算法模型概述

    1.算法背景

            所谓稀疏点云就是点数稀少的点云模型,有时我们需要用到一些物体上的关键点来和目标模型进行配准,计算一些关键指标。而传统的点云配准算法要求待配准的两片点云数量级相当,并且还包括粗配准和精配准两个阶段。经实验可得,传统点云配准算法在稀疏点云配准上表现较差,因此稀疏点云配准十分关键。

     2.算法模型 

            SPR算法不需要进行粗配准就可以实现效果较好的稀疏点云配准效果,该算法的核心思想主要包括扰动、迭代、细化三个部分。SPR算法模型包括以下步骤:

    • 初始化目标模型点云数据A,稀疏点云数据B,最大迭代次数MaxIterations,配准误差阈值Threshold、扰动次数P
    • 根据点云Size和高斯分布计算当前迭代的扰动量(扰动量随着迭代次数不断减小,最后减小到零)获取P个扰动扰动变换矩阵,然后对当前B点云进行扰动变换
    • 分别计算P个扰动变换后的稀疏点云B和目标模型点云A的 Cost (这里可以使用K-D Tree 计算最近点偏差和作为Cost),选择Cost最小的作为局部最优扰动
    • 基于当前的最优扰动变换后的稀疏点云B,进行 ICP or DQF 算法精配准细化(本文选择ICP),获得精配准矩阵Tk,并计算此时的误差
    • 若计算的误差小于最小误差e,则更新全局最优边换矩阵T和最小误差e为当前迭代结果。
    • 重复迭代以上过程,直到达到最大迭代次数MaxIterations或计算误差e<配准误差阈值Threshold

     3.算法流程图

             除此之外,论文中还阐释了一些比较细节的注意事项和参数设置,比如最大迭代次数MaxIterations、配准误差阈值Threshold、扰动次数P设置为多少,如何进行扰动计算,以及如何在试验中取点等等,当然稀疏点云中越具有特征性的关键点配准效果越好。

    二.算法实现(ICP版本)

            本文的SPR算法实现使用Matlab编程进行,采用ICP的精配准版本,在实现过程中对原算法进行了改进:在迭代过程中,对每一个出现的扰动变换都进行ICP精配准计算,然后基于这个误差进行比较,而不只是原算法所言的选出最优扰动后再计算ICP,这样可以最大程度的提高算法精确度,但是牺牲了时间复杂度。下面给出部分代码。

    (1)SPR.m

    1. % SPR Main logic function:transform A sparse point cloud into B model point cloud coordinate system for registration
    2. % - Params:
    3. % - A:sparse point cloud [n,3]
    4. % - B:model point cloud [m,3]
    5. % - Return:
    6. % - R:optimal rotation matrix [3,3]
    7. % - T:optimal translation matrix [1,3]
    8. % - trans_res:transform point cloud [n,3]
    9. function [ R,T,trans_res ] = SPR(A,B)
    10. %1.kdtree model for B(euclidean distance) and size of the model
    11. Mdl = KDTreeSearcher(B);
    12. Size = max(range(B));
    13. %2.Initialize R0,T0,e0
    14. R = eye(3);
    15. %Align the centroids of two point clouds A->B
    16. cen_A = sum(A)/length(A);
    17. cen_B = sum(B)/length(B);
    18. T = cen_B - cen_A;
    19. trans_res = transform(A,R,T);
    20. e = calculateCost(trans_res,B,Mdl);
    21. %3.Initialize the number of disturbed pose P, the maximum number of iterations I, and the minimum error threshold RMS
    22. P = 10;
    23. I = 30;
    24. RMS = 1e-6;
    25. %4.Initialize loop variable
    26. k = 1;
    27. %record data
    28. x_loop = 1:I;
    29. y_error = zeros(1,I);
    30. %5.SPR Loop
    31. while e > RMS && k <= I
    32. cost_best = inf;
    33. R_k = R;
    34. T_k = T;
    35. %(1). Perturbations for Sparse point cloud,and then the perturbation transformation matrix is obtained
    36. % - R_p: [3,3,P+1]
    37. % - T_p: [p+1,3]
    38. [R_p, T_p] = perturb(Size,P,k,I);
    39. %(2). Calculate the optimal pose
    40. for j = 1:P+1
    41. %Obtain the transformation matrix parameters rp_j(3,3), tp_j(1,3) of the current p-th disturbance pose
    42. rp_j = R_p(:,:,j)*R;
    43. tp_j = (R_p(:,:,j)*T')'+T_p(j,:);
    44. %Calculate current optimal cost(from ICP)
    45. [R_j,T_j,cost_j] = solveicp(A,B,Mdl,rp_j,tp_j);
    46. %judge optimal cost
    47. if cost_j < cost_best
    48. cost_best = cost_j;
    49. R_k = R_j;
    50. T_k = T_j;
    51. end
    52. end
    53. %(3). Error calculation and judge for update
    54. trans_k = transform(A,R_k,T_k);
    55. e_k = calculateCost(trans_k,B,Mdl);
    56. if e_k < e
    57. e = e_k;
    58. R = R_k;
    59. T = T_k;
    60. end
    61. y_error(k) = e;
    62. k = k+1;
    63. end
    64. trans_res = transform(A,R,T);
    65. figure
    66. plot(x_loop,y_error,marker='o', MarkerFaceColor='r');
    67. xlabel('loop');
    68. ylabel('ems error');
    69. end

    (2)Perturb.m

    1. %Disturbance function: Generates random perturbations based on iteration within loop and specified
    2. % - Params:
    3. % - size:Size of the model
    4. % - P:Number of disturbances
    5. % - k:Number of iterations
    6. % - I:Iteration upper bound
    7. % - Return:
    8. % - R_p:Perturbation rotation matrix [3,3,P+1]
    9. % - T_p:Perturbation translation matrix [P+1,3]
    10. function [ R_p, T_p ] = perturb( size,P,k,I )
    11. %1.Initial translation disturbance:10% of the model size
    12. T_p = normrnd(0,(0.1*size*((I+1-k)/I)),[P,3]); %[P,3]
    13. %2.Initial perturbation number of rotation:10 ° normal distribution(Right hand coordinate system)
    14. %Around x
    15. a = normrnd(0,(10*((I+1-k)/I)),[1,P]); %[1,P]
    16. %Around y
    17. b = normrnd(0,(10*((I+1-k)/I)),[1,P]);
    18. %Around z
    19. c = normrnd(0,(10*((I+1-k)/I)),[1,P]);
    20. %3.convert to radians
    21. a = a.*(pi()/180);
    22. b = b.*(pi()/180);
    23. c = c.*(pi()/180);
    24. %4.initialize R_p
    25. R_p = zeros(3,3,P);
    26. %5.Generate P disturbances respectively (matlab subscript starts from 1)
    27. for j = 1:P
    28. %rotation matrix about x
    29. r1 = [1,0,0; 0, cos(a(j)), -sin(a(j)); 0, sin(a(j)), cos(a(j))];
    30. %rotation matrix about y
    31. r2 = [cos(b(j)), 0, sin(b(j)); 0,1,0; -sin(b(j)), 0, cos(b(j))];
    32. %rotation matrix about z
    33. r3 = [cos(c(j)), -sin(c(j)), 0; sin(c(j)), cos(c(j)), 0; 0,0,1];
    34. %Perturbation Rotation
    35. R_p(:,:,j) = r1*r2*r3;
    36. end
    37. %P+1:Transformation without disturbance
    38. R_p(:,:,P+1) = eye(3);
    39. T_p(P+1,:) = [0,0,0];
    40. end

    (3)solveicp.m

    1. %Function takes in A and B clusters, registers A to B using ICP, returns resultant transformation matrix and error calculation
    2. % - Params:
    3. % - A:initial point cloud [n,3]
    4. % - B:target point cloud [m,3]
    5. % - Return:
    6. % - TR:solve rotation matrix [1,3]
    7. % - RO:solve translation matrix [3,3]
    8. % - e:registers error
    9. function [ R,T,e ] = solveicp( A,B,Mdl,R_0,T_0 )
    10. %1.initialize variable parameters
    11. k = 1;
    12. error = 0.0001;
    13. Iterator = 50;
    14. R = R_0;
    15. T = T_0;
    16. %2.initial:kdtree algorithm to find the nearest point pair of two point clouds
    17. trans = transform(A,R,T);
    18. e = calculateCost(trans,B,Mdl);
    19. %3.ICP loop
    20. while e > error && k <= Iterator
    21. %find the nearest point
    22. idx = knnsearch(Mdl,trans);
    23. NN = B(idx,:);
    24. %svd solve: optimal matching matrix of two point clouds in current state
    25. [T_k, R_k] = solvesvd(trans,NN);
    26. %Cumulative transformation T=[1,3] R=[3,3]
    27. T = (R_k*T')'+T_k;
    28. R = R_k*R;
    29. trans = transform(A,R,T);
    30. %Update error E
    31. e = sum(sqrt(sum((NN-trans).^2,2)))/length(trans);
    32. k = k+1;
    33. end
    34. end

    (4)solvesvd.m

    1. %function: svd solve yo find T and R between point set B and it nearest neighbour set
    2. % - Params:
    3. % - B:initial point clouds [n,3]
    4. % - NN: target nearest neighbour point clouds [n,3]
    5. % - Return:
    6. % - T:solve optimal translation matrix [1,3]
    7. % - R:solve optimal rotation matrix [3,3]
    8. function [ T, R ] = solvesvd( B, NN )
    9. num = length(B);
    10. %1.Seeking centroid
    11. cen_B = sum(B)/num;
    12. cen_NN = sum(NN)/num;
    13. %2.Decentralization:Set centroids as reference origin for both clusters
    14. B2 = B-repmat(cen_B,num,1);
    15. NN2 = NN-repmat(cen_NN,num,1);
    16. %3.svd decompose:[U,S,V] = svd(A) ==> A = U*S*V'
    17. H = B2'*NN2;
    18. [U,~,V] = svd(H);
    19. R = V*diag([1 1 sign(det(V*U'))])*U';
    20. T = cen_NN' - R*cen_B';
    21. T = T';
    22. end

    三.实现效果

     注意:上图中蓝色为初始稀疏点云,黑色为配准后的稀疏点云结果

  • 相关阅读:
    Java基础38 面向对象三大特征之多态
    StatefulSet 简单实践 Kubernetes
    S5PV210裸机(七):Nand和iNand
    【嵌入式项目应用】__do{...} while(0) 的四大使用场景
    2023 牛客国庆day4 【10.2训练补题】
    野火开发板使用FlyMcu一键ISP下载时
    移动端页面秒开优化总结
    Springboot项目多模块打包jar移动到指定目录,docker打jar包构建镜像部署并运行
    Shell揭秘——程序退出状态码
    Idea本地跑flink任务时,总是重复消费kafka的数据(kafka->mysql)
  • 原文地址:https://blog.csdn.net/qq_40772692/article/details/127954620