直线提取——合并分裂算法 MATLAB代码

       一、代码原理

        题目来自CUMT自主移动机器人,直线检测大作业

        在自主移动机器人中,直线的提取多用于检测障碍物和检测两侧的道路,在图像处理中,直线的提取一般采用hough变换的方式进行提取,算法比较成熟,效果也较为理想,这里介绍另一种比较常用的直线提取算法,合并分裂算法。

        分裂——合并算法是比较流行的直线提取的算法。该算法源于计算机视觉,并已经在许多的著作中被研究使用。顾名思义,合并分裂算法就是对一串点集中,在一条直线上的点进行合并,而不在一条直线上的两个点集进行分裂。

        具体实现的流程如下:

 在输入点集之后,对整个点集进行拟合,并计算各个点到点集的距离后进行排序,选择距离拟合曲线最远的点,作为点集的分裂点,将点集分离开,再对分离后的两个点集分别进行拟合,重复以上操作,最后得到拟合的直线。

        分裂合并算法中,点集的变化示例图如下:

项目通过MATLAB实现,实验的数据通过激光雷达采集得到。

二、数据采集

根据作业的要求,我们采用极其有限的部分工具搭建了一个五边形,并使用激光雷达采集点云:

采集的软件使用SLAMTEC思岚科技官方提供的软件

 激光雷达采集到的数据是一个没有后缀的文件,使用文本格式打开后可以发现,除文件头外,文件的数据包括了角度、距离以及数据的质量,即采集到的数据是以角坐标的形式存储的。

 为了便于MATLAB直接读取,我们去掉了文件头以及数据的质量一列,并将数据保存为txt文件,

通过MATLAB,使用极坐标画图命令,将数据进行可视化后,

clear,clc;
data=dlmread('888.txt');
polarplot(data(:,1)/180*pi,data(:,2));
grid on;

 三、MATLAB代码实现

(1)实现数据的读取,预处理和坐标轴的设定

clc,clear;
data=dlmread('888.txt');
[xdata,ydata]=pol2cart(data(:,1)/180*pi,data(:,2));
X=round(xdata+1000);
Y=round(ydata+1000);
plot(X,Y);
hold on;
plot(X(1,1),Y(1,1),'*');
T=[];
s=[X Y];
L={s};
axis([500 1500 0 1600])

(2)点集及其拟合数据的判断、存取

for i=1:length(L{1,:})
    pause(0.02);
    [m,n,t,k]=det_length(L{1,i});
    a=500:0.1:1500;
    b=t(1)*a+t(2);
    plot(a,b);
    if k==0
        if ~isempty(m)&&length(m(:,1))~=1
            L{end+1} = m;
        end
        if ~isempty(n)&&length(n(:,1))~=1
            L{end+1} = n;
        end
    else
        T(1:2,length(T)+1)=[t(1);t(2)];
    end
    if i==length(L)
        break;
    end
end

(3)自定义函数,实现点集的拟合,距离的计算和以及根据最远距离判断和分割点集

function [m,n,t,k]=det_length(s)
 t = polyfit(s(:,1),s(:,2),1);
 distance=abs(t(1)*s(:,1)-  s(:,2)+t(2))/sqrt(t(1)^2+1);
 [mdis,i]=max(distance);
 if mdis>12
     k=0;
	  m(:,1)=s(1:i-1,1);
         m(:,2)=s(1:i-1,2);
         n(:,1)=s(i+1:length(s(:,2)),1);
         n(:,2)=s(i+1:length(s(:,2)),2);
         plot(s(i,1),s(i,2),'o');
 else
     k=1;
     m=[];
     n=[];
 end

到这里基本实现了绝大部分的内容,但是在代码实现的时候会大仙一个问题,即最后只检测到了两条直线,代码在运行的时候陷入了局部最优解中,每一次在迭代的时候,只排除了最边上的一个点,代码运行过程如下:

直线检测局部最优

其中直线为每一次迭代拟合的直线,圆圈为最远的点。

        因此我们需要对现有的分割函数进行改进,即在检测到离拟合的直线最远的点为端点时,默认选择中点作为分割点,以此来保证能检测到所有的直线。

(4)改进后的分割函数

当检测到离拟合曲线最远距离的点是端点时,便连接点集的第一个点和最后一个点,形成一条直线

以该直线作为该点集拟合得到的直线,再进行判断和分割

function [m,n,t,k]=det_length(s)
 t = polyfit(s(:,1),s(:,2),1);
 distance=abs(t(1)*s(:,1)-s(:,2)+t(2))/sqrt(t(1)^2+1);
 [mdis,i]=max(distance);
 if mdis>12
     k=0;
     if i==1||i==length(distance)
          t = polyfit([s(1,1);s(length(distance),1)],[s(1,2);s(length(distance),2)],1);
          distance=abs(t(1)*s(:,1)-s(:,2)+t(2))/sqrt(t(1)^2+1);
          [mdis,i]=max(distance);
     end
         m(:,1)=s(1:i-1,1);
         m(:,2)=s(1:i-1,2);
         n(:,1)=s(i+1:length(s(:,2)),1);
         n(:,2)=s(i+1:length(s(:,2)),2);
         plot(s(i,1),s(i,2),'o');
 else
     k=1;
     m=[];
     n=[];
 end

 改进后的分割效果:

直线检测

 最后成功检测到所有的直线:

目前已经对算法进行了进一步的改进,能实现相似直线的合并以及端点的检测,后续看心情更新,完整的代码资源以及PPT后续会上传

完整资源以及代码:合并分裂算法MATLAB代码

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值