基于hough霍夫变换的铁栏栅断裂处的检测算法matlab仿真

目录

一、理论基础

二、MATLAB程序

三、仿真结果


一、理论基础

       Hough变换:Hough变换是1962年由Hough提出来的,用于检测图像中直线、圆、抛物线、椭圆等形状能够用一定函数关系描述的曲线,它在影像分析,模式识别等很多领域中得到了成功的应用。Hough变换的基本原理是将影像空间中的曲线(包括直线)变换到参数空间中,通过检测参数空间中的极值点,确定出该曲线的描述参数,从而提取影像中的规则曲线。

       Hough变换是图像处理中从图像中识别几何形状的基本方法之一。Hough直线检测的基本原理在于利用点与线的对偶性,在我们的直线检测任务中,即图像空间中的直线与参数空间中的点是一一对应的,参数空间中的直线与图像空间中的点也是一一对应的。这意味着我们可以得出两个非常有用的结论:

1)图像空间中的每条直线在参数空间中都对应着单独一个点来表示;

2)图像空间中的直线上任何一部分线段在参数空间对应的是同一个点。

       因此Hough直线检测算法就是把在图像空间中的直线检测问题转换到参数空间中对点的检测问题,通过在参数空间里寻找峰值来完成直线检测任务,也即把检测整体特性转化为检测局部特性。

       霍夫变换是一个特征提取技术。其可用于隔离图像中特定形状的特征的技术,应用在图像分析、计算机视觉和数字图像处理领域。目的是通过投票程序在特定类型的形状内找到对象的不完美实例。这个投票程序是在一个参数空间中进行的,在这个参数空间中,候选对象被当作所谓的累加器空间中的局部最大值来获得,所述累加器空间由用于计算霍夫变换的算法明确地构建。最基本的霍夫变换是从黑白图像中检测直线(线段)。Hough变换主要优点是能容忍特征边界描述中的间隙,并且相对不受图像噪声的影响。

       霍夫变换最简单的是检测直线。我们知道,直线的方程表示可以由斜率和截距表示(这种表示方法,称为斜截式),如下所示:

        如果用参数空间表示则为,即用斜率和截距就能表示一条直线。

       但是这样会参数问题,垂直线的斜率不存在(或无限大),这使得斜率参数的值接近于无限。为此,为了更好的计算,Richard O. Duda和Peter E. Hart在1971年4月,提出了Hesse normal form(Hesse法线式)

       其中是原点到直线上最近点的距离(其他人可能把这记录为,下面也可以把r看成参数),是轴与连接原点和最近点直线之间的夹角。如图1所示。

因此,可以将图像的每一条直线与一对参数相关联。这个参数平面有时被称为霍夫空间,用于二维直线的集合。

在概念上,霍夫变换很接近Radon变换有人将之看成同一变换的不同形式

经过Hough变换,将图像空间中的一个点映射到Hough空间,如图2所示。

 

二、MATLAB程序

clc;
clear;
close all;
warning off;

%调用图片
I0      = imread('1.jpg');
[R,C,K] = size(I0);
if K==1
   I1 = I0; 
else
   I1 = rgb2gray(I0);  
end

%明暗度调整
I1    = imadjust(I1,[0.1 0.7],[]);
%初步的形态学处理
BW0   = im2bw(I1,0.5*graythresh(I1));
%去除小区域面积 
BW0   = bwareaopen(BW0,400);
BW1   = imerode(BW0,ones(5));
BW2   = imdilate(BW1,ones(5)); 
figure;
subplot(131);
imshow(BW0) 
subplot(132);
imshow(BW2) 

%Hough
[H,T,R] = hough(BW2);
P       = houghpeaks(H,15,'threshold',ceil(0.2*max(H(:))));
x       = T(P(:,2)); 
y       = R(P(:,1));
lines   = houghlines(BW2,T,R,P,'FillGap',5,'MinLength',7);
subplot(133);
imshow(BW2) 
hold on
max_len = 0;
for k = 1:length(lines)
   xy = [lines(k).point1; lines(k).point2];
   plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');
   plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
   plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
   len = norm(lines(k).point1 - lines(k).point2);
   if ( len > max_len)
      max_len = len;
      xy_long = xy;
   end
end

%垂直向直线检测和倾斜线段检测,即线条归类
Xv_s =[];
Xv_e =[];
Yv_s =[];
Yv_e =[];
Xh_s =[];
Xh_e =[];
Yh_s =[];
Yh_e =[];
for k = 1:length(lines)
    xy = [lines(k).point1; lines(k).point2];
    xs = xy(1,1);
    xe = xy(2,1);
    ys = xy(1,2);
    ye = xy(2,2); 
    %计算角度
    theta = 180*abs(atan((ye-ys)/(xe-xs)))/pi;
    if abs(theta - 90) <= 5;%垂直
       Xv_s =[Xv_s,xs];
       Xv_e =[Xv_e,xe];
       Yv_s =[Yv_s,ys];
       Yv_e =[Yv_e,ye];
    end
    if abs(theta - 30) <= 5;%倾斜
       Xh_s =[Xh_s,xs];
       Xh_e =[Xh_e,xe];
       Yh_s =[Yh_s,ys];
       Yh_e =[Yh_e,ye]; 
    end  
end


%对垂直区域进行检测
Xverr_s = [];
Xverr_e = [];
Yverr_s = [];
Yverr_e = [];
for k = 1:length(Xv_s)
    %计算长度
    dist1(k) = sqrt((Xv_s(k) - Xv_e(k))^2 + (Yv_s(k) - Yv_e(k))^2);
    if dist1(k) <= 2000%这个参数和实际图像大小有关,这里为2000
       Xverr_s = [Xverr_s,Xv_s(k)];
       Xverr_e = [Xverr_e,Xv_e(k)];
       Yverr_s = [Yverr_s,Yv_s(k)];
       Yverr_e = [Yverr_e,Yv_e(k)];
    end
end
%计算断裂的大概编号
for i = 1:length(Xverr_s)/2;
    X(i) = Xverr_s(2*i-1);
end
BH = [];
for j = 1:length(X)
    for i = 1:length(Xv_s)
        if X(j) < Xv_s(i)
           BH = [BH,i+j-1];  
           break;
        end
    end
end
BH



Xherr_s = [];
Xherr_e = [];
Yherr_s = [];
Yherr_e = [];
%对倾斜区域进行检测
for k = 1:length(Xh_s)
    %计算长度
    dist2(k) = sqrt((Xh_s(k) - Xh_e(k))^2 + (Yh_s(k) - Yh_e(k))^2);
    if dist2(k) <= 2000%这个参数和实际图像大小有关,这里为2000
       Xherr_s = [Xherr_s,Xh_s(k)];
       Xherr_e = [Xherr_e,Xh_e(k)];
       Yherr_s = [Yherr_s,Yh_s(k)];
       Yherr_e = [Yherr_e,Yh_e(k)];
    end
end





%将异常点合并
Xerr_s =[Xverr_s,Xherr_s];
Xerr_e =[Xverr_e,Xherr_e];
Yerr_s =[Yverr_s,Yherr_s];
Yerr_e =[Yverr_e,Yherr_e];

%根据坐标进行定位
if isempty(Xerr_s) == 1;
   figure;
   imshow(I0);title('无裂痕');
else
   %获得裂痕坐标区域
   figure;
   imshow(I0);
   hold on
   %分析裂痕坐标点
   XC=[];
   YC=[];
   for k = 1:length(Xerr_s)-1
       %计算长度
       dist0(k) = sqrt((Xerr_e(k) - Xerr_s(k+1))^2 + (Yerr_e(k) - Yerr_s(k+1))^2);
       if dist0(k) <= 200%这个参数和实际图像大小有关,裂痕,如果值过大,则不属于裂痕
          XC=[XC,(Xerr_e(k) + Xerr_s(k+1))/2];
          YC=[YC,(Yerr_e(k) + Yerr_s(k+1))/2];
       end
   end
   %给出定位区域
   for k = 1:length(YC)
       plot(XC(k),YC(k),'go','LineWidth',3,'MarkerEdgeColor','g','MarkerSize',20);
       hold on
       text(XC(k),YC(k)-100,['第',num2str(BH(k)),'根'],'fontsize',15);
   end
   XC
   YC
   
   
   NAME = [];
   for i = 1:length(BH)
       NAME = [NAME,'第',num2str(BH(i)),'根  '];
   end
   title(['有裂痕:',NAME]);
   
   figure;
   imshow(BW0);
   hold on
   for k = 1:length(YC)
       plot(XC(k),YC(k),'go','LineWidth',3,'MarkerEdgeColor','g','MarkerSize',20);
       
   end
   
   
end

 

三、仿真结果

仿真的结果如下:

 

 

 

 

 

 

 

 A23-29

猜你喜欢

转载自blog.csdn.net/ccsss22/article/details/126806394