ICP算法实现(MATLAB)

ICP原理

ICP(Iterative closet point method)迭代最近点法,用于两组数据之间的配准,其实现的具体步骤如下

对于两组点云: P Q

step1:选择控制点 piP 、设置 T 的初始值T0=T0

step2:重复执行以下步骤,直至满足收敛条件

​ step2-1:对各控制点, pi Q 中求其最近点qj,并将其作为 pi 的假想对应点

​ step2-2:对于确定的对应的关系,求解 Tk ,对并且求解loss function

Ek=Tk|piqj|2>

​ step2-3:重新计算控制点 pi 在经过 Tk 变换之后的点,并将其重新赋值给 pi

算法的收敛条件是 δ=EkEk1M<ε

数据采集

把采集的数据集1:
这里写图片描述

数据2:
这里写图片描述

经过初始配准之后的数据集:

这里写图片描述

Registration

在初始时,通过手动选取3000个点作为配准点;平移通过质心之间的距离计算,旋转通过 svd 分解进行计算。具体实现方法为,假设两组去质心的数据点为 qi qi ,通过计算

Hi=1nqiqti

则变换 qi=Rqi ,对 H 进行SVD分解,即 H=USVt ,则旋转矩阵可表示为 R=VUt ,该方法已经集成在PCL库中用于registration,具体证明方法可以参照”Least-Squares Fitting of Two 3-D Points Sets”这篇文章。算法迭代的流程如下:

for iter=1:iteration
%寻找控制点的对应点
for i=1:controldatanum
    temp_data1=repmat(controldata1(i,:),m,1);
    diff=sqrt(sum((temp_data1-data2).^2,2));
    [minvalue,index(i,1)]=min(diff);
    controldata2(i,:)=data2(index(i,1),:);
end
%%
%对于确定的关系,求解RT
centroid1=mean(controldata1);
centroid2=mean(controldata2);
demeancontroldata1=controldata1-repmat(centroid1,controldatanum,1);
demeancontroldata2=controldata2-repmat(centroid2,controldatanum,1);
H=demeancontroldata1'*demeancontroldata2;
[U,S,V]=svd(H);
R=V*U';
T=(centroid2-centroid1)';
R_Intermediate(:,:,iter)=R;
T_Intermediate(:,:,iter)=T;
%%
%利用求解得到的RT计算变换之后的点
controldata1=R*controldata1'+repmat(T,1,controldatanum);
controldata1=controldata1';%新的控制点
E=norm(controldata1-controldata2,2);
e_Intermediate(iter,1)=E/controldatanum
delta=abs(E-last_E)/controldatanum%中间迭代的误差
delta_Intermediate(iter,1)=delta;
if(delta<0.001)
    break;
end
last_E=E;
end

由于控制点手工选取的较好,所以算法收敛的很快,基本上经过三次迭代即收敛,算法的loss函数定义为控制点与其match之间的平均差距,即为 Ek/M ,得到如下图像

这里写图片描述
配准的结果如下图:

这里写图片描述

配准结果好坏的衡量标准为观察点云是否融合在一起,仔细观察上述结果是彼此融合在一起。

不足之处

用matlab实现起来速度比较慢,尤其是在寻找控制点的match时,需要对另外一组数据进行遍历匹配,一种比较快速的方法是用C++并且通过K-d tree进行匹配点搜索,这样耗时应该比较少。

全部代码

%%
%寻找的变换关系data2=Rdata1+T

%%
%加载数据选取控制点
data1=load('3.asc');
data2=load('4.asc');
figure(1);
plot3(data1(:,1),data1(:,2),data1(:,3),'r.');
hold on;
plot3(data2(:,1),data2(:,2),data2(:,3),'b.');
title('原始数据');
axis tight equal;
hold off;


[m,n]=size(data2);
controldata1=load('controldata.asc');%选取控制点
[controldatanum,~]=size(controldata1);
controldata2=zeros(controldatanum,3);
%%
%初始化
R=[1,0,0;0,1,0;0,0,1];
T=[0,0,0];
last_E=0;
iteration=20;
R_Intermediate=zeros(3,3,iteration);
T_Intermediate=zeros(3,1,iteration);
delta_Intermediate=zeros(iteration,1);
index=zeros(controldatanum,1);
e_Intermediate=zeros(iteration,1);
%%
%迭代
for iter=1:iteration
%寻找控制点的对应点
for i=1:controldatanum
    temp_data1=repmat(controldata1(i,:),m,1);
    diff=sqrt(sum((temp_data1-data2).^2,2));
    [minvalue,index(i,1)]=min(diff);
    controldata2(i,:)=data2(index(i,1),:);
end
%%
%对于确定的关系,求解RT
centroid1=mean(controldata1);
centroid2=mean(controldata2);
demeancontroldata1=controldata1-repmat(centroid1,controldatanum,1);
demeancontroldata2=controldata2-repmat(centroid2,controldatanum,1);
H=demeancontroldata1'*demeancontroldata2;
[U,S,V]=svd(H);
R=V*U';
T=(centroid2-centroid1)';
R_Intermediate(:,:,iter)=R;
T_Intermediate(:,:,iter)=T;
%%
%利用求解得到的RT计算变换之后的点
controldata1=R*controldata1'+repmat(T,1,controldatanum);
controldata1=controldata1';%新的控制点
E=norm(controldata1-controldata2,2);
e_Intermediate(iter,1)=E/controldatanum
delta=abs(E-last_E)/controldatanum%中间迭代的误差
delta_Intermediate(iter,1)=delta;
if(delta<0.001)
    break;
end
last_E=E;
end

figure(2);
plot(1:iter,delta_Intermediate(1:iter,1)');
xlabel('迭代次数');ylabel('delta');
figure(3);
plot(1:iter,e_Intermediate(1:iter)');
xlabel('迭代次数');ylabel('loss');
%%
%计算最终的R与T
temp_R=eye(3);
temp_T=zeros(3,1);
for i=1:iter
   temp_R=R_Intermediate(:,:,i)*temp_R; 
   temp_T=R_Intermediate(:,:,i)*temp_T+T_Intermediate(:,:,i);
end
R_final=temp_R;
T_final=temp_T;

data1_transformed=R_final*data1'+repmat(T_final,1,size(data1,1));
data1_transformed=data1_transformed';
figure(4);
plot3(data1_transformed(:,1),data1_transformed(:,2),data1_transformed(:,3),'r.')
hold on;
plot3(data2(:,1),data2(:,2),data2(:,3),'b.')
title('ICP results')
axis equal tight;
hold off;
 save data3.asc -ascii data1_transformed;
  • 11
    点赞
  • 122
    收藏
    觉得还不错? 一键收藏
  • 30
    评论
ICP(Iterative Closest Point)算法是一种常用于点云配准的算法,它通过迭代的方式找到两个点云之间的最佳变换关系,使得它们尽可能地重叠在一起。在Matlab中,我们可以使用以下步骤来实现ICP算法的编程: 1. 导入点云数据:首先,我们需要导入两个点云数据集,分别称为源点云和目标点云。可以使用Matlab中的文件导入功能,将点云数据以矩阵的形式导入到Matlab中。 2. 初始化变换矩阵:接下来,我们需要初始化一个初始的变换矩阵,用于将源点云与目标点云进行配准。可以使用Matlab中的齐次变换矩阵来实现。 3. 迭代计算:在每一次迭代中,我们根据当前的变换矩阵,将源点云变换到目标点云的坐标系中。然后,通过对应点的匹配,计算源点云与目标点云之间的误差,得到最佳的配准结果。 4. 更新变换矩阵:根据误差的最小化准则,我们可以使用最小二乘法来更新当前的变换矩阵,以减小源点云与目标点云之间的误差。 5. 判断终止条件:我们可以设置一个预定的终止条件,例如误差的阈值或者迭代次数的上限。当达到终止条件时,ICP算法将停止迭代,并输出最终的变换矩阵。 6. 应用变换矩阵:最后,我们可以使用得到的最终变换矩阵来将源点云变换到目标点云的坐标系中,从而实现点云的配准。 以上就是在Matlab实现ICP算法的步骤。需要注意的是,ICP算法对于初始变换矩阵的选择和对应点的匹配都有一定的要求,对于不同的应用场景可能需要调整算法的参数。如果需要更高效的计算,也可以考虑使用Matlab中的并行计算工具箱来加速计算过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值