1. 程式人生 > >灰度影象形狀的識別分類演算法實現matlab

灰度影象形狀的識別分類演算法實現matlab

摘  要: 針對已經給出的影象,在分類之前,因為存在噪聲和光照的不同,所以要先進行影象增強,並統一將影象轉為二值影象。對影象進行邊緣檢測,可以很容易算出各個影象面積與周長二次方的比值關係,對影象進行直線檢測, 可以獲得影象中直線的特徵,結合影象的以上兩種特種對形狀進行分類。

 

 

演算法設計和推導:

    

  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.0850.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