基于hough变换的平行线识别

基于hough变换的平行线识别

hough变换基本原理讲述

线段识别是识别图像中平行线的基础。但一张图像中所包含的线段几乎是无限的所以无法在图像中直接判断,因此引入Hough变换[32]。Hough变换的基础是建立极坐标空间用(ρ,θ)表示空间各点,并根据极坐标变换将图像中所有直线用空间各点(ρ,θ)表示。根据直线在极坐标系与直角坐标系间转换关系得式(1)。
ρ=xcos⁡θ+ysin⁡θ (1)
式中ρ为原点到该直线的垂直距离;θ为垂线与x轴的夹角。
Hough变换后得出极坐标空间与图像空间满足下述关系:(1) 极坐标空间中任意点(ρ, θ)都代表图像空间中的一条直线并将此直线记作l((ρ,θ));(2) 图像空间中任意点(x, y)对应于极坐标空间中一条三角函数线。
在这里插入图片描述

程序编写

- 程序实现步骤

在程序编写过程中将总体流程分为三部分:图像边缘线检测、线段检测与平行线检测。在图像边缘线检测中根据灰度梯度的变化情况,利用sobel算子完成边缘线检测;线段检测中利用Hough变换,识别边缘线中的线段,并输出所识别线段的角度和极径参数;在平行线检测过程中,根据平行线的几何特征制定线段组夹角、距离以及间距3种判定条件完成平行线判断,并识别程序流程图如下图所示。
在这里插入图片描述

程序代码

clc;
clear;
iceThickness=0;
%%   图片的读入与裁剪
f=imread('C:\Users\huawei\Desktop\海冰识别\前期过程\所识别图片\dachuang1.png');
%f=imcrop(f,[900,760,200,300]);  %裁剪图片
% f=imcrop(f,[670,0,689,817]);  %裁剪图片
% f=imcrop(f,[890,0,689,817]);  %裁剪图片
f=imcrop(f,[850,710,400,400]);
figure(10)
imshow(f);
%%   判断参数的定义
%角度----------------------------------- 2
theta_chazhi=3;
%两线间距离(极坐标下 )---------------- 70~15
distance_max=70;
distance_min=15;
%端点距离 ---------------------------- -10~25
boundray_point_distance_max=15;
boundray_point_distance_min=-15;
%中点距离----------------------------- -10~20
middle_point_distance_max=20;
middle_point_distance_min=-10;
%平行条件判断---------------------------- 13
parallel_judge=10;
%两线间距离(直角坐标系下)-------------- 10~100
xy_distance_max=100;
xy_distance_min=10;
%直线本身长度----------------------------- 25    
length_min=25;
%两线长度差值--------------------------- 0.25~2.5
length_ratio_max=2;
length_ratio_min=0.5;

%%   输出值预定义
iceThickness=0;
iceParameter.k_1=0;
iceParameter.k_2=0;
iceParameter.b_1=0;
iceParameter.b_2=0;
iceParameter.start_1=[0,0];
iceParameter.start_2=[0,0];
iceParameter.end_1=[0,0];
iceParameter.end_2=[0,0];

%%   从视频中读入图片
% video=VideoReader('C:\Users\86132\Desktop\大创\20171203(1).mp4');      %读取MP4文件
% nFrames=video.NumberOfFrames;     %从视频中读取视频的总帧数
% n=round((nFrames-10)/25);
% im=cell(1,n);
% for k=1:n
%     m1=read(video,25*k);%读取第k帧,存入im中
%     im{k}=im2double(m1);%将图片存入元胞im,
% end
% f=imcrop(im{14},[850,0,689,817]);

% figNames=struct2cell(dir('C:\Users\86132\Desktop\大创\截图\*.jpg'));
% [~,len]=size(figNames);
% for i=1:len
%     name=figNames{1,i};
% end
% f=imread(['C:\Users\86132\Desktop\大创\所识别图片\',name]);
% f=imcrop(f,[870,0,689,817]);  %裁剪图片

%%   图像的基本处理
I=rgb2gray(f);     %进行灰度化

% imshow(I),title('原图I');
% figure (1)
% imshow(I),title('裁剪图');

se=strel('disk',20);%disk指定构建一个圆形的结构体,第二个参数指定结构体的半径
%接下来,进行基于重建的开操作。使用imerode和imreconstruct函数实现
Ie=imerode(I, se);%先腐蚀‘erosion’
Iobr=imreconstruct(Ie, I);%再重建

% figure(10)
% imshow(Iobr);

Iobrd=imdilate(Iobr, se);%在基于重建的开操作的结果基础上,进行腐蚀
Iobrcbr=imreconstruct(imcomplement(Iobrd), imcomplement(Iobr));%重建,标记图像为腐蚀后图像取补,模板为腐蚀前原图取补。
Iobrcbr=imcomplement(Iobrcbr);%重建结果再取补,得到实际基于重建的闭操作的结果。

% figure(2)
% imshow(Iobrcbr),title('基本图像处理后所得图形');



%%   图像的边缘检测
BW=edge(Iobrcbr,'sobel');
% figure(3);
% imshow(BW),title('边缘图');

%%   图像中的直线检测
[x,y]=size(BW);
[H,T,R]=hough(BW,'RhoResolution',1,'Theta',-90:1:89.5);      %Hough变换
P=houghpeaks(H,10,'threshold',ceil(0.05*max(H(:))));   %查找Hough峰值
lines1=houghlines(BW,T,R,P,'FillGap',15,'MinLength',20);
L=0;
for k=1:length(lines1)
%     if lines1(k).theta<=45&&lines1(k).theta>=-45
        L=L+1;
        Lines(L).point1=lines1(k).point1;
        Lines(L).point2=lines1(k).point2;
        Lines(L).theta=lines1(k).theta;
        Lines(L).rho=lines1(k).rho;
%     end
end
figure(4),imshow(BW,[]),title('直线检测图');
hold on
n=length(Lines);
for i=1:n
    for j=1:3
        color(i,j)=rand(1);
    end
end
for k=1:length(Lines)
    xy=[Lines(k).point1;Lines(k).point2];
    plot(xy(:,1),xy(:,2),'LineWidth',2,'color',color(k,:));
end



if (L)==0
    return;
end
for i=1:length(Lines)
    A(i)=Lines(i).theta;       %A代表角度
    B(i)=Lines(i).rho;         %B代表极径长度
    x1y1(i,1:2)=Lines(i).point1;   %x1y1代表起始点的坐标
    x2y2(i,1:2)=Lines(i).point2;   %x2y2代表终止点的坐标
end
%合并相同的直线的不同线段
o=1;h(1:length(A))=0;
A1(1)=A(1);B1(1)=B(1);
X1Y1(1,1:2)=x1y1(1,1:2);
X2Y2(1,1:2)=x2y2(1,1:2);
for i=2:length(A)
    z=A(i)-A(i-1);l=B(i)-B(i-1);
    if (z~=0||l~=0)
        o=o+1;
    else
        h(o)=h(o)+1;  %记录相同直线的个数
    end
    A1(o)=A(i);   %A1代表角度
    B1(o)=B(i);   %B1代表极径长度
end
z(1:17)=0;
same_number(1:length(A1))=h(1:length(A1))+1;o=0; %用same_number来接收相同直线的个数
for i=1:length(same_number)
    xy1(1:same_number(i),1:2)=x1y1((1+o):(same_number(i)+o),1:2);
    xy1(same_number(i)+1:2*same_number(i),1:2)=x2y2((1+o):(same_number(i)+o),1:2); %记录同一下直线上的所有点
    if A1(i)~=0
        for k=1:2*same_number(i)
            z=0;
            for j=1:2*same_number(i)
                if xy1(k,1)>=xy1(j,1)
                    z=z+1;
                end
            end
            if z==2*same_number(i)
                X1Y1(i,1:2)=xy1(k,1:2);
            end
        end
        for k=1:2*same_number(i)
            z=0;
            for j=1:2*same_number(i)
                if xy1(k,1)<=xy1(j,1)
                    z=z+1;
                end
            end
            if z==2*same_number(i)
                X2Y2(i,1:2)=xy1(k,1:2);
            end
        end
    end
    if A1(i)==0
        for k=1:2*same_number(i)
            z=0;
            for j=1:2*same_number(i)
                if xy1(k,2)>=xy1(j,2)
                    z=z+1;
                end
            end
            if z==2*same_number(i)
                X1Y1(i,1:2)=xy1(k,1:2);
            end
        end
        for k=1:2*same_number(i)
            z=0;
            for j=1:2*same_number(i)
                if xy1(k,2)<=xy1(j,2)
                    z=z+1;
                end
            end
            if z==2*same_number(i)
                X2Y2(i,1:2)=xy1(k,1:2);
            end
        end
    end
    o=o+same_number(i);
end

%%   坐标转换

    for i=1:size(A1,2)
        if A1(i)>=0&&A1(i)<=90
            K(i)=tan((90-A1(i))*(pi/180));  %k_lines表示直线在直角坐标系中的斜率
        end
        if A1(i)>=-90&&A1(i)<0
            K(i)=tan((-90-A1(i))*(pi/180));
        end
    end
    
    
    %利用中点和上一个循环得到的斜率计算两直线之间的平均距离
    for i=1:size(A1,2)
        Middle(i,1)=0.5*(X1Y1(i,1)+X2Y2(i,1));
        Middle(i,2)=0.5*(X1Y1(i,2)+X2Y2(i,2));
        B(i)=Middle(i,2)-K(i)*Middle(i,1);  %b_lines代表直线的截距
    end





for u=1
    %% 判断条件1:利用角度差值初步判断两线是否平行
    %查找并记录近似平行的直线
    o=0;
    for i=1:length(A1)
        for j=i+1:length(A1)
            if abs(A1(i)-A1(j))<=theta_chazhi&&A1(i)>=-5&&A1(i)<=60    %根据角度的差异大小,以及角度本身的大小进行判断  
                o=o+1;
                paralleltheta_number(o,1:2)=[i,j];
            end
        end
    end
    if o==0
        break;
    end
    f=0;
    for i=1:size(paralleltheta_number,1)
        distance(i)=abs(B1(paralleltheta_number(i,1))-B1(paralleltheta_number(i,2)));   %计算线段之间的距离
        if distance(i)<=distance_max&&distance(i)>=distance_min
            f=f+1;
            Paralleltheta_number(f,1:2)=paralleltheta_number(i,1:2);
        end
    end

    if f==0
        break;
    end
    
    
    
    
    
    
    
    %%   判断条件2:用两条线段间的距离判断
    for i=1:size(Paralleltheta_number,1)
        a(1:2)=X1Y1(Paralleltheta_number(i,1),1:2);
        b(1:2)=X2Y2(Paralleltheta_number(i,1),1:2);
        c(1:2)=X1Y1(Paralleltheta_number(i,2),1:2);
        d(1:2)=X2Y2(Paralleltheta_number(i,2),1:2);
        middle(i,1)=0.5*(a(1)+b(1));
        middle(i,2)=0.5*(a(2)+b(2));
        middle_2(i,1)=0.5*(c(1)+d(1));
        middle_2(i,2)=0.5*(c(2)+d(2));
        point_distance(1,i)=sqrt((middle(i,1)-middle_2(i,1))^2+(middle(i,2)-middle_2(i,2))^2);  %每一对平行线的中点距离
        point_distance(2,i)=sqrt((a(1)-c(1))^2+(a(2)-c(2))^2);
        point_distance(3,i)=sqrt((b(1)-d(1))^2+(b(2)-d(2))^2);
    end
    p=0;            
    for i=1:size(Paralleltheta_number,1)
        e(i)=abs(B1(Paralleltheta_number(i,1))-B1(Paralleltheta_number(i,2)));
        panduan(1:3,i)=point_distance(1:3,i)-e(i);    %线段距离和中点以及端点的距离差值大小
        if (panduan(1,i)<=middle_point_distance_max&&panduan(1,i)>=middle_point_distance_min)||(panduan(2,i)<=boundray_point_distance_max&&panduan(2,i)>=boundray_point_distance_min)||(panduan(3,i)<=boundray_point_distance_max&&panduan(3,i)>=boundray_point_distance_min)
            p=p+1;
            Paralleltheta_number2(p,1:2)=Paralleltheta_number(i,1:2);
        end
    end
    if p==0
        break;
    end
    
    
    %% 判断条件3:判断两条直线是否有相交的情况
    %将线段参数中的角度theta转化为斜率k_lines
    for i=1:size(Paralleltheta_number2,1)
        theta(i,1)=A1(Paralleltheta_number2(i,1));
        theta(i,2)=A1(Paralleltheta_number2(i,2));
        for j=1:2
            if theta(i,j)>=0&&theta(i,j)<=90
                k_lines(i,j)=tan((90-theta(i,j))*(pi/180));  %k_lines表示直线在直角坐标系中的斜率
            end
            if theta(i,j)>=-90&&theta(i,j)<0
                k_lines(i,j)=tan((-90-theta(i,j))*(pi/180));
            end
        end
    end
    
    
    %利用中点和上一个循环得到的斜率计算两直线之间的平均距离
    for i=1:size(k_lines,1)
        k_merge(i,1)=0.5*(k_lines(i,1)+k_lines(i,2));
        a(1:2)=X1Y1(Paralleltheta_number2(i,1),1:2);
        b(1:2)=X2Y2(Paralleltheta_number2(i,1),1:2);
        c(1:2)=X1Y1(Paralleltheta_number2(i,2),1:2);
        d(1:2)=X2Y2(Paralleltheta_number2(i,2),1:2);
        middle(i,1)=0.5*(a(1)+b(1));
        middle(i,2)=0.5*(a(2)+b(2));
        middle_2(i,1)=0.5*(c(1)+d(1));
        middle_2(i,2)=0.5*(c(2)+d(2));
        b_lines(i,1)=middle(i,2)-k_merge(i,1)*middle(i,1);  %b_lines代表直线的截距
        b_lines(i,2)=middle_2(i,2)-k_merge(i,1)*middle_2(i,1);
        b_distance(i,1)=(abs(b_lines(i,1)-b_lines(i,2))/sqrt(1+k_merge(i,1)^2));  %b_distance表示由虚设斜率所得两直线之间的平均距离
    end
    o=0;
    for i=1:size(Paralleltheta_number2,1)
        judge(i,1)=abs(b_distance(i,1)-abs(B1(Paralleltheta_number2(i,1))-B1(Paralleltheta_number2(i,2))));
        if (judge(i,1)<=parallel_judge)&&(b_distance(i,1)>=xy_distance_min)&&(b_distance(i,1)<=xy_distance_max)  %平行线判断标准
            o=o+1;
            Paralleltheta_number3(o,1:2)=Paralleltheta_number2(i,1:2);
            ice_thickness1(o)=b_distance(i);
        end
    end
    if o==1     %如果经过判断的直线组只剩下一个那么就直接输出此时的直线结果
    end
    
    
    
    %% 判断条件4:判断直线自身长度,以及两直线差值是否满足要求
    Q=0;
    for i=1:size(Paralleltheta_number3,1)
        a(1:2)=X1Y1(Paralleltheta_number3(i,1),1:2);%线段1起始点
        b(1:2)=X2Y2(Paralleltheta_number3(i,1),1:2);%线段1终止点
        c(1:2)=X1Y1(Paralleltheta_number3(i,2),1:2);%线段2起始点
        d(1:2)=X2Y2(Paralleltheta_number3(i,2),1:2);%线段2终止点
        self_distance(i,1)=sqrt((a(1)-b(1))^2+(a(2)-b(2))^2)+1;
        self_distance(i,2)=sqrt((c(1)-d(1))^2+(c(2)-d(2))^2)+1;
        self_distance_panduan(i)=abs(self_distance(i,1)/self_distance(i,2));
        if (self_distance(i,1)>length_min&&self_distance(i,2)>length_min)&&(self_distance_panduan(i)<length_ratio_max&&self_distance_panduan(i)>length_ratio_min)
            Q=Q+1;
            Paralleltheta_number4(Q,1:2)=Paralleltheta_number3(i,1:2);
            ice_thickness2(Q)=ice_thickness1(i);
        end
    end
    %如果经过判断的直线组只剩下一个那么就直接输出此时的直线结果
    if Q~=0
    end   
end

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值