基于Matlab的多线激光中心坐标值提取

本文详细介绍了使用Matlab进行激光线中心线提取的方法,包括图像二值化、重心法、图像叠加等步骤,分别处理了简单和复杂情况的图像。针对复杂图像,采用了分区二值化、光斑处理和骨架提取等技术,以应对倾斜、亮度不均和光斑干扰的问题。
摘要由CSDN通过智能技术生成

        本文是基于给定的两张多线激光图片,如下图所示。需将图片中的激光线的中心线坐标提取出来并绘制激光中心线图形。因为是Matlab课程训练研究大作业,所以全文代码为Matlab,希望可以为相似作业的非专业同学提供一些帮助。

文章目录

1.问题分析

 2.研究思路及关键代码

2.1图片一部分

2.1.1二值化处理

 2.1.2 重心法提取中心线

2.1.3 图像叠加

 2.2 图像二部分

2.2.1 分区二值化处理

 2.2.2 光斑处理

 2.2.3 提取中心线

 3.总结及整体代码

3.1 总结

3.2 整体代码

3.2.1 图片一

3.2.2 图片二

3.3 参考链接


1.问题分析

        由于是给定图片,数量不是很多,因此可以对每个图像单独分析,这也是本篇文章的局限性。在拿到图像时,如果懂ps的,可以先调大整体图像的亮度,可以看到一些原本图像显示并不清楚的地方,例如在图二中,原图中右下部分是没有激光线的,但是在调亮后确有,这是在交大作业的前一天晚上发现的,因此大家都没有再改的了。

        第一张图中,其线条相对简单,激光线基本垂直于水平线,没有较大的噪点,因此可以先二值化处理图形,再利用重心法提取中心线,可以实现像素级提取激光中心线。

        第二张图中,可以发现激光线有较大的倾斜角,且亮度不一,并有较大的光斑对图像造成干扰,因此提取较第一张图更加复杂一些。可以先对图像进行区域二值化处理,再去除光斑的影响,最后提取激光条纹中心线。

 2.研究思路及关键代码

2.1图片一部分

2.1.1二值化处理

        遍历图一每个像素点,经过多次调试后设定二值化的阈值为60,当图片的灰度值小于60是置为0,否则置为255,得到处理后的图。

for i=1:a
    for j=1:b
        if I(i,j)<60
            I(i,j)=0;
        else
            I(i,j)=255;
        end
    end
end

 

 2.1.2 重心法提取中心线

        从图中任取出一条水平线,读取其处理后的灰度值如下图。

         可以发现,每个峰值区即为激光线,因此提取每段峰值区的中点即可提取其中心线,再遍历每条水平线即可。

    w=1; %字母含义为某排识别出的中心点横坐标的序号
    for i=1:a
        for j=1:b
            if I(i,j)==255 %识别出某条激光线的第一个位置坐标
                k=j;
                while I(i,k)==255 %判断该条激光线的最后一个位置坐标
                    k=k+1;
                    if k>=b;
                        break;
                    end
                end
                s(w)=ceil((k-1+j)/2); %通过首尾位置计算中心点坐标存入数组中
                w=w+1;
            end
            I(i,j)=0; %抹除图像所有亮点
        end
        I(i,s)=255; %赋给中心点255
        w=1;
        s=0;
    end

2.1.3 图像叠加

        再与原图叠加即可验证其提取效果。由于需要用彩色图来区分,因此需把灰度图转化成RGB图像,灰度图是一个0-255的数来显示的,而RGB图是(R,G,B)三个0-255的数来描述,因此涉及到图像的转化部分。代码和最终图像如下。

for i=1:a 
    for j=1:b
        q=I0(i,j); %读取原图
        II(i,j,1)=q;
        II(i,j,2)=q;
        II(i,j,3)=q;
        if I(i,j)==255 %读取提取中心线的图
            II(i,j-2,1)=255; %中心线显示为红色
            II(i,j-2,2)=0;
            II(i,j-2,3)=0;
        end
    end
end

 2.2 图像二部分

2.2.1 分区二值化处理

        可以明显观察到左上角的条纹的亮度较小,且有斜向右下的亮宽条纹对激光条纹有较大的影响。因此,对图像进行分区二值化以得到更好的预处理效果。

        利用四条直线将上图分成5个部分。

对于1号和3号部分,其激光条纹亮度差异不大,因此可以设置较大的阈值,设定像素的灰度值小于160时置为0,否则置为255。

对于2号和5号部分,其中激光条纹亮度差异较大,应设置较小的阈值。设定像素的灰度值小于45时置为0,否则置为255。

对于4号部分,由于其干扰线亮度大,激光条纹线亮度也大,因此设定阈值应更大以滤去干扰线部分。设定像素的灰度值小于230时置为0,否则置为255。

        处理后的图如下。

 2.2.2 光斑处理

        对图像进行膨胀腐蚀处理,可以提取图中的圆。

se=strel('disk',8); %设置圆半径
fc=imerode(I,se);   %图像腐蚀
fc=imdilate(fc,se);   %图像膨胀

 

 将上图反值后,与原图像叠加,得到去除圆的图像,再经过降噪处理,得到待提取中心线的图像

I=bwareaopen(I,10); %降噪处理

 

        将之前提取到的圆的图像与上图进行相交判断处理,识别圆是否与直线相交。首先使用canny算子提取圆的边缘,再判断每个边缘像素点周围5个点的位置是否于待提取直线相交。在找到相交边缘后,再把对应圆找到。以每个圆内点为圆心,50为半径,判断其是否与边缘点相交,得到相交边缘所在圆。最后再将其与待提取中心线的图像部分叠加,得到最后的待提取中心线部分

fc1=edge(fc,'canny'); %用Canny算子进行边缘检测

for i=1:a %检测边缘是否与直线相交
    for j=1:b-5
        if fc1(i,j)==1
            s=0;
            for m=1:5
                if I(i-m,j-m)==1||I(i+m,j-m)==1||I(i-m,j+m)==1||I(i+m,j+m)==1
                    s=1;
                end
            end
            if s==0
                fc1(i,j)=0;
            end
        end
    end
end

for i=1:a %找到相交边缘圆
    for j=1:b
        if fc(i,j)==255
            s=0;
            radius=50;
            for m=max(1,i-radius):min(a,i+radius)
                for n=max(1,j-radius):min(b,j+radius)
                    if ((m-i)^2+(n-j)^2<=radius^2)&&(fc1(m,n)==1)
                        s=1;
                        break;
                    end
                end
            end
            if s==0
                fc(i,j)=0;
            end
        end
    end
end

for i=1:a %合并相交圆与待提取中心线
    for j=1:b
        if fc(i,j)==255
            I(i,j)=255;
        end
    end
end

 2.2.3 提取中心线

采用bwmorph函数,提取激光条纹的骨架线作为其中心线。

I = bwmorph(I,'thin',100);

 

再将其与原图叠加,得到最终图。

 3.总结及整体代码

3.1 总结

        在对图片一进行处理时,二分阈值的选取可能不适用于部分区域,导致提取出来的中心线有部分偏移。当然也可以不预先进行二值化,从而采用基于灰度的重心法,对于噪声小的图像可能适用,但是噪声过大就会提取出噪声了。

        在对第二张图片处理时,和第一张图相比,最大的不同便是整个图像倾斜、激光线明暗变化较大,且有明显的噪点,给二值化处理带来困难,分区二值化相当于是一个妥协,也是不能通用的阻碍。在查找资料时,其实还有更专业的处理方法,opencv已提供有现成可用的api,但是本文要求为Matlab代码,因此仅仅为同为需求的同学提供一些帮助,也不失为应付作业的一种方法罢。

3.2 整体代码

3.2.1 图片一

clc ; clear all;
I = imread('图片一.bmp');
[a,b]=size(I);
figure(1);
imshow(I);
title('原图');
I0=I;%保存一份原图,用于后面叠加显示

%******二值化图像**********
for i=1:a
    for j=1:b
        if I(i,j)<60
            I(i,j)=0;
        else
            I(i,j)=255;
        end
    end
end
figure(2);
imshow(I);
title('二值化的图');
imwrite(I,'二值化的图.tif');

%******重心法提取中心线**********
q=100;
while q>0
    w=1;
    for i=1:a
        for j=1:b
            if I(i,j)==255
                k=j;
                while I(i,k)==255
                    k=k+1;
                    if k>=b;
                        break;
                    end
                end
                s(w)=ceil((k-1+j)/2);
                w=w+1;
            end
            I(i,j)=0;
        end
        I(i,s)=255;
        w=1;
        s=0;
    end
    q=q-1;
end

for i=1:a %中心线与原图叠加
    for j=1:b
        q=I0(i,j);
        II(i,j,1)=q;
        II(i,j,2)=q;
        II(i,j,3)=q;
        if I(i,j)==255
            II(i,j-2,1)=255;
            II(i,j-2,2)=0;
            II(i,j-2,3)=0;
        end
    end
end

figure(3);
imshow(II);
title('最终图1');
imwrite(II,'最终图1.tif');

3.2.2 图片二

clc ; clear all;
I = imread('图片二.bmp');
[a,b]=size(I);
figure(1);
imshow(I);
title('原图');
pif=I;

%******分区二值化图像**********
for i=1:a
    for j=1:b
        if(((i/320+j/128)>1)&&((i/800+j/400<1))||((i/1900+j/1100>1)))%四条直线分区
            
            if I(i,j)<45
                I(i,j)=0;
            else
                I(i,j)=255;
            end
        else if ((i/800+j/400>1))&&((i/1900+j/1100<1)&&(3*i-5*j>200))
                if I(i,j)<230
                    I(i,j)=0;
                else
                    I(i,j)=255;
                end
            else
                if I(i,j)<160 %设置不同的阈值过滤图像
                    I(i,j)=0;
                else
                    I(i,j)=255;
                end
            end
        end
    end
end

figure(2);
imshow(I);
title('二值化的图');
imwrite(I,'二值化的图.bmp');

%******处理图中的圆形噪点**********
se=strel('disk',8);
fc=imerode(I,se);   %图像腐蚀
fc=imdilate(fc,se);   %图像膨胀
figure(3);
imshow(fc);
title('原图处理后的圆点图');
imwrite(fc,'原图处理后的圆点图.bmp');

for i=1:a
    for j=1:b
        if fc(i,j)==255
            I(i,j)=0; %将白色圆形置为黑色
        end
    end
end

figure(4);
imshow(I);
title('去除圆形的图');
imwrite(I,'去除圆形的图.bmp');

%******去除图像中的剩余噪点**********
I=bwareaopen(I,10);
figure(5);
imshow(I);
title('去噪图');
imwrite(I,'去噪图.bmp');

%******检测与直线相交的圆边缘**********
fc1=edge(fc,'canny'); %用Canny算子进行边缘检测
figure(6);
imshow(fc1);
title('圆边缘图');
imwrite(fc1,'圆边缘图.bmp');

%检测边缘是否与直线相交
for i=1:a
    for j=1:b-5
        if fc1(i,j)==1
            s=0;
            for m=1:5
                if I(i-m,j-m)==1||I(i+m,j-m)==1||I(i-m,j+m)==1||I(i+m,j+m)==1
                    s=1;
                end
            end
            if s==0
                fc1(i,j)=0;
            end
        end
    end
end
figure(7);
imshow(fc1);
title('相交圆边缘');
imwrite(fc1,'相交圆边缘图.bmp');

%******找到相交边缘圆**********
for i=1:a
    for j=1:b
        if fc(i,j)==255
            s=0;
            radius=50;
            for m=max(1,i-radius):min(a,i+radius)
                for n=max(1,j-radius):min(b,j+radius)
                    if ((m-i)^2+(n-j)^2<=radius^2)&&(fc1(m,n)==1)
                        s=1;
                        break;
                    end
                end
            end
            if s==0
                fc(i,j)=0;
            end
        end
    end
end

figure(8);
imshow(fc);
title('相交圆');
imwrite(fc,'相交圆图.bmp');

%******合并相交圆与线**********
for i=1:a
    for j=1:b
        if fc(i,j)==255
            I(i,j)=255;
        end
    end
end
figure(9);
imshow(I);
title('需要找中心线的部分');
imwrite(I,'需要找中心线的部分.bmp');

%******提取中心线**********
I = bwmorph(I,'thin',100);%生成的I为逻辑数
figure(10);
imshow(I);
title('提取的中心线');
imwrite(I,'提取的中心线.bmp');

%******合并中心线与原图,中心线置红**********
for i=1:a
    for j=1:b
        q=pif(i,j);
        pifs(i,j,1)=q;
        pifs(i,j,2)=q;
        pifs(i,j,3)=q;
        if  I(i,j)==1
            pifs(i,j,1)=255;
            pifs(i,j,2)=0;
            pifs(i,j,3)=0;
        end
    end
end

figure(11);
imshow(pifs);
title('最终图');
imwrite(pifs,'最终图.bmp');

3.3 参考链接

激光光条中心的提取_九磅十五便士_的博客-CSDN博客_光条中心提取

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值