您的位置:首页 > 编程语言 > MATLAB

灰度图像形状的识别分类算法实现matlab

2016-07-22 20:58 706 查看

摘  要: 针对已经给出的图像,在分类之前,因为存在噪声和光照的不同,所以要先进行图像增强,并统一将图像转为二值图像。对图像进行边缘检测,可以很容易算出各个图像面积与周长二次方的比值关系,对图像进行直线检测, 可以获得图像中直线的特征,结合图像的以上两种特种对形状进行分类。

 

 

算法设计和推导:

    

  1. 图像预处理部分,通过
9X9 均值滤波器,先对图像进行去噪,然后二值化图像。
  2. 各个形状的面积和周长存在一定的特征关系,可据此对图像进行分类。
(令各形状的面积为S,周长为L,计算)
   (1)圆形(半径为r1):S/L2
=(π*r12) / (2*π*r1)2
                                              = 1 / 4*π= 0.0796
(2)正方形(边长为r2):S/L2  =  r22
/ (4*r2)2
                                         =  1/16 = 0.0652
(3) 矩形(不包含正方形)  S/L2  < 1/16 = 0.0652
(4) 椭圆(不包含原)   S/L2  <  1 / 4*π= 0.0796
   据此方法,可对圆和正方形进行分类,将圆和正方形与另外两种形状区分开来,但无法对椭圆和矩形进行恰当分类。
   3. 用霍夫变换对形状进行直线检测,获得直线特征(直线数量,直线长度),
若检测到直线数量不等于四条,可直接判断为圆或椭圆,计算直线长度,找出相等的直线对,若四条直线相等,可判断为正方形,若有两对相等的直线,可判断为矩形。
    结合以上两种判断方法,对形状进行识别并分类。
  

实验设计和结果

  1.预处理部分,对图像进行增强并二值化,实现代码如下:

function K2 = quzao(I)

 

K1=filter2(fspecial('average',[9,9]),I)/255;

 

thresh = graythresh(I);

K2 = im2bw(K1,thresh);

end

实现效果:

 




              原图像             处理过的图像  

 




             原图像              处理过的图像 

 

 




            原图像               处理过的图像 

 




        原图像                   处理过的图像 

 

 2.为了计算S/L2,需要获得图像中各形状对应的面积和周长,对二值化后的图像进行边缘提取,来获得形状的边界(以圆为例)

 

  


两张图像大小一样,分别计算每张图像值为1 的像素数量,计算比率,实现代码如下:

function r = Ratio(K,E)

    [r1,c1] = size(K);

  %  [r2,c2] = size(E);

    

    area = 0;

    perimeter = 0;

    

    for i = 1:r1

        for j = 1:c1

            if(K(i,j)==1)

                area = area+1;

            end

            if(E(i,j)==1)

                perimeter = perimeter+1;

            end

        end

    end

   

    r = area/(perimeter*perimeter);

    

end

 

每个形状各选择50张图像进行测试,查看各个不同形状所计算出的比率的分布情况,结果如下:

 

 


  

               圆                              正方形

  

 


             长方形                           椭圆
 
观察实验结果发现,圆和正方形的S/L2比值并未像预期那样为定值,但圆形的比值基本分布在0.085和
0.09之间,而其他形状算出的比值均未超过0.085,可据此将圆形与其他三个形状区分开来。

 
3.对图像进行直线检测

利用霍夫变换进行直线检测 ,可通过分析直线特征,根据获得的直线数量,计算出的直线长度来进行比较,具体实现如下
直线检测并进行正方形和长方形的判断并写入相应文件夹:
 
 
 
BW=edge(K,'canny');                                    %边缘检测

            [H,T,R]=hough(BW);                                     %霍夫变换进行直线检测

            P=houghpeaks(H,5,'threshold',ceil(0.3*max(H(:))));

            lines=houghlines(BW,T,R,P,'FillGap',30,'MinLength',60);  %获得检测到的直线

            [num1,num2] = size(lines);                               %获得直线的数量num2

            if(num2 == 4)                                           %若检测到为四条直线,逐一计算各条直线长度,存入l

                for count=1:4

                    lines(count).long = sqrt((lines(count).point1(1)-lines(count).point2(1))^2 + (lines(count).point1(2)-lines(count).point2(2))^2);

                    l(count) = lines(count).long;

                end

                num = lineCompare(l);                           %比较直线长度,判断是否为矩形或正方形形

            end

            if(num==4 && num2 == 4)                               %判断为正方形

                    path = strcat('square\',int2str(index1));

                    imwrite(K,strcat(path,'.jpg'));

                    index1 = index1+1;

            elseif(num==2 && num2 == 4)                           %判断为矩形

                    path = strcat('rectangle\',int2str(index2));

                    imwrite(K,strcat(path,'.jpg'));

                    index2 = index2+1;

 
通过直线的长度比较来进行判断,lineCompare函数代码如下
 
function num = lineCompare(l)

    num = 0;

    diff(12) = abs(l(1)-l(2));            %第一条直线与各直线进行比较,计算与其他直线的差值diff

    diff(13) = abs(l(1)-l(3));

    diff(14) = abs(l(1)-l(4));  

    

    if(diff(12)<5.5 || diff(13)<5.5 || diff(14)<5.5)

        if(diff(12)<5.5 && diff(13)<5.5 && diff(14)<5.5)         %若四条直线相等(即直线长度差值小于5.5),即判断为正方形

            num = 4;

        elseif(diff(12) < 5.5)                                   %四条直线不相等,但直线1,2相等,判断直线3,4是否相等,若相等,即为矩形

            diff(34) = abs(l(3) - l(4));

            if(diff(34) < 5.5)

                num = 2;

            end

        elseif(diff(13) < 5.5)

            diff(24) = abs(l(2) - l(4));

            if(diff(24) < 5.5)

                num = 2;

            end

        elseif(diff(14) < 5.5)

            diff(23) = abs(l(2)-l(3));

            if(diff(23) < 5.5)

                num = 2;

            end

        end

    end

    

end

 
 
最终确定的程序执行步骤为,先进行直线检测将图像分为正方形和长方形,圆形和椭圆两类,正方形和长方形通过直线长度比较进一步分类,圆形和椭圆通过计算S/L2进一步划分。将每一张图像进行形状分类后写入对应的文件夹
 
4. 将最终程序用于形状的划分,统计分到每个问价下的各形状数量性能统计如下

文件夹\形状

正方形
长方形
椭圆
circle
276
2
3
60
square
0
188
0
2
rectangle
 0
  14
156
  2
ellipse
 3
  75
120
215
合计
279
  279
279
  279
正确率
98.9%
 67.4%
56.0%
77.1%
完整实现代码:

图像预处理:

function K2 = quzao(I)

K1=filter2(fspecial('average',9),I)/255;

thresh = graythresh(I);

K2 = im2bw(K1,thresh);

end

周长面积比率:

function r = Ratio(K,E)

    [r1,c1] = size(K);

  %  [r2,c2] = size(E);

    

    area = 0;

    perimeter = 0;

    

    for i = 1:r1

        for j = 1:c1

            if(K(i,j)==1)

                area = area+1;

            end

            if(E(i,j)==1)

                perimeter = perimeter+1;

            end

        end

    end

   

    r = area/(perimeter*perimeter);

    

end

开始分类:

function split(file_path)

%file_path =  'test1\';% 图像文件夹路径

img_path_list = dir(strcat(file_path,'*.jpg'));%获取该文件夹中所有jpg格式的图像

img_num = length(img_path_list);%获取图像总数量

index1 = 1;

index2 = 1;

index3 = 1;

index4 = 1;

num = 0;

if img_num > 0 %有满足条件的图像

        for j = 1:img_num %逐一读取图像

            image_name = img_path_list(j).name;% 图像名

            image =  imread(strcat(file_path,image_name));

            fprintf('%d %d %s\n',i,j,strcat(file_path,image_name));% 显示正在处理的图像名

            K = quzao(image);                                      % 调用去噪函数进行去噪

            BW=edge(K,'canny');                                    %边缘检测

            [H,T,R]=hough(BW);                                     %霍夫变换进行直线检测

            P=houghpeaks(H,5,'threshold',ceil(0.3*max(H(:))));

            lines=houghlines(BW,T,R,P,'FillGap',30,'MinLength',60);  %获得检测到的直线

            [num1,num2] = size(lines);                               %获得直线的数量num2

            if(num2 == 4)                                           %若检测到为四条直线,逐一计算各条直线长度,存入l

                for count=1:4

                    lines(count).long = sqrt((lines(count).point1(1)-lines(count).point2(1))^2 + (lines(count).point1(2)-lines(count).point2(2))^2);

                    l(count) = lines(count).long;

                end

                num = lineCompare(l);                           %比较直线长度,判断是否为矩形或正方形形

            end

            if(num==4 && num2 == 4)                               %判断为正方形

                    path = strcat('square\',int2str(index1));

                    imwrite(K,strcat(path,'.jpg'));

                    index1 = index1+1;

            elseif(num==2 && num2 == 4)                           %判断为矩形

                    path = strcat('rectangle\',int2str(index2));

                    imwrite(K,strcat(path,'.jpg'));

                    index2 = index2+1;

                

            else                                                

                 E = edge(K);

                  r = Ratio(K,E);                                      

                 if(r>0.086)                                          %判断为圆

                     path = strcat('circle\',int2str(index3));

                     imwrite(K,strcat(path,'.jpg'));

                     index3 = index3+1;

                 else                                                %判断为椭圆

                     path = strcat('ellipse\',int2str(index4));

                     imwrite(K,strcat(path,'.jpg'));

                     index4 = index4+1;

                 end

             end

       

          

        end

       

            %图像处理过程 省略

       

else

    fprintf('文件夹不存在!');% 显示正在处理的图像名

end

end

function num = lineCompare(l)

    num = 0;

    diff(12) = abs(l(1)-l(2));            %第一条直线与各直线进行比较,计算与其他直线的差值diff

    diff(13) = abs(l(1)-l(3));

    diff(14) = abs(l(1)-l(4));

    

   

    

    if(diff(12)<5.5 || diff(13)<5.5 || diff(14)<5.5)

        if(diff(12)<5.5 && diff(13)<5.5 && diff(14)<5.5)         %若四条直线相等(即直线长度差值小于5.5),即判断为正方形

            num = 4;

        elseif(diff(12) < 5.5)                                   %四条直线不相等,但直线1,2相等,判断直线3,4是否相等,若相等,即为矩形

            diff(34) = abs(l(3) - l(4));

            if(diff(34) < 5.5)

                num = 2;

            end

        elseif(diff(13) < 5.5)

            diff(24) = abs(l(2) - l(4));

            if(diff(24) < 5.5)

                num = 2;

            end

        elseif(diff(14) < 5.5)

            diff(23) = abs(l(2)-l(3));

            if(diff(23) < 5.5)

                num = 2;

            end

        end

    end

    

end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: