1. 程式人生 > >計算機視覺之(一)利用Harris檢測子進行角點特徵檢測(含matlab原始碼)

計算機視覺之(一)利用Harris檢測子進行角點特徵檢測(含matlab原始碼)

    本文為原創文章,轉載請註明本文來自http://blog.csdn.net/anymake_ren/article/details/21298807     計算機視覺中常用的影象特徵包括:點、邊緣、直線、曲線等,其中,點特徵屬於區域性特徵,對遮擋有一定魯棒性。影象中點特徵數量多,提取速度快,並且容易辨識區分,因此在影象處理中佔有重要地位。

    好的點特徵如圖1所示,在角點處,影象上的一個小視窗沿任何方向移動,視窗內的影象都有明顯的灰度變化,因此角點是好的點特徵。

                                               圖1


那麼,我們要怎樣識別角點呢?由圖2可以看出,角點具有類似圖2中的第一列所展示的性質:

                                              圖2


    假設視窗W發生位置偏移(u,v);比較偏移前後視窗中每一個畫素點的灰度變化值;使用灰度誤差平方和來構造一個誤差函式E(u,v),其中的視窗函式是用來濾波的。

    H稱為自相關矩陣, λmax和λmin是自相關矩陣的特徵值。其中E(u,v)是一個二次型函式,二次型函式的本質就是一個橢圓,橢圓的扁率和尺寸是由H的特徵λmax和λmin值λmax和λmin決定的,橢圓的方向由H的特徵向量決定。圖3-3表示的是點線面與橢圓的關係,其中(d)圖中的橢圓跑哪去了,我也不知道。因為圖是從掃描版的PDF中擷取的,有點模糊。

   下面這幅圖是王永明等在《影象區域性不變性特徵與描述》一書中闡述橢圓與點線面的關係用的。第一行是不同典型影象的灰度梯度分佈圖,第二行是對梯度分別的橢圓擬合。不過有一點沒有明白,如果按照哈里斯的理論線性邊緣時,R不應該為負值的嗎?那王永明的這幅圖中的R代表什麼含義啊到底?為什麼線性邊緣時,R=0.3328?搞不懂啊搞不懂!!!大哭


    正如圖3所示,只有當兩者都比較大,並且大小相當時對應點才為角點,兩者都非常小時為平坦區域;一大一小時為邊界。

                                         圖3


    在1988年,哈里斯在其論文《A combined corner and edge detector》裡給出了更有效的角點響應函式

R為正值時,檢測到的是角點;R為負時檢測到的是邊;R很小時檢測到的是平坦區域,由此也就有了更便於計算的數學公式。哈老先生對此做的圖如下:

下面是對Harris演算法的Matlab實現,原始碼參考自http://blog.csdn.net/aflyeagle/article/details/5116799

個人對一些地方做了修改說明。


執行環境windows8.1+Matlab R2013b

%%%Prewitt Operator Corner Detection.m
%%%時間優化--相鄰畫素用取差的方法求Harris角點
 %% 
 clear;
 Image = imread('884.jpg');                 % 讀取影象
 Image = im2uint8(rgb2gray(Image));   
  

dx = [-1 0 1;-1 0 1;-1 0 1];  %dx:橫向Prewitt差分模版
Ix2 = filter2(dx,Image).^2;   
Iy2 = filter2(dx',Image).^2;                                        
Ixy = filter2(dx,Image).*filter2(dx',Image);
 
%生成 9*9高斯視窗。視窗越大,探測到的角點越少。
h= fspecial('gaussian',9,2);
A = filter2(h,Ix2);       % 用高斯視窗差分Ix2得到A 
B = filter2(h,Iy2);                                 
C = filter2(h,Ixy);                                  
nrow = size(Image,1);                            
ncol = size(Image,2);                             
Corner = zeros(nrow,ncol); %zeros用來產生一個全零矩陣,故矩陣Corner用來儲存候選角點位置,初值全零,值為1的點是角點

 %引數t:點(i,j)八鄰域的“相似度”引數,只有中心點與鄰域其他八個點的畫素值之差在
 %(-t,+t)之間,才確認它們為相似點,相似點不在候選角點之列
 t=20;
 
 %我並沒有全部檢測影象每個點,而是除去了邊界上boundary個畫素,也就是從第8行第8列開始遍歷。
 %因為我們感興趣的角點並不出現在邊界上
 %個人覺得這一部分是的主要目的是找出可能是角點的點,縮小範圍,加快運算速度。
 %具體思想是如果中心點(i,j)周圍8個點中有7、8個點灰度值與之相似,那麼該中心點應該處於平坦區域,不可能為角點,
 %如果中心點(i,j)周圍只有1個點或者沒有點與之相似,那麼該中心點也不可能為角點。
 boundary=8;
 for i=boundary:nrow-boundary+1 
    for j=boundary:ncol-boundary+1
         nlike=0; %相似點個數
         if Image(i-1,j-1)>Image(i,j)-t && Image(i-1,j-1)<Image(i,j)+t 
            nlike=nlike+1;
         end
         if Image(i-1,j)>Image(i,j)-t && Image(i-1,j)<Image(i,j)+t  
            nlike=nlike+1;
         end
         if Image(i-1,j+1)>Image(i,j)-t && Image(i-1,j+1)<Image(i,j)+t  
            nlike=nlike+1;
         end  
        if Image(i,j-1)>Image(i,j)-t && Image(i,j-1)<Image(i,j)+t  
            nlike=nlike+1;
         end
         if Image(i,j+1)>Image(i,j)-t && Image(i,j+1)<Image(i,j)+t  
            nlike=nlike+1;
         end
         if Image(i+1,j-1)>Image(i,j)-t && Image(i+1,j-1)<Image(i,j)+t  
            nlike=nlike+1;
         end
         if Image(i+1,j)>Image(i,j)-t && Image(i+1,j)<Image(i,j)+t  
            nlike=nlike+1;
         end
         if Image(i+1,j+1)>Image(i,j)-t && Image(i+1,j+1)<Image(i,j)+t  
            nlike=nlike+1;
         end
         if nlike>=2 && nlike<=6
             Corner(i,j)=1;%如果周圍有2~6個相似點,那(i,j)就是角點
         end;
     end;
 end;
CRF = zeros(nrow,ncol);    % CRF用來儲存角點響應函式值,初值全零
 CRFmax = 0;                % 影象中角點響應函式的最大值,作閾值之用 
k=0.05;   
% 計算CRF
 %工程上常用CRF(i,j) =det(M)/trace(M)計算CRF,那麼此時應該將下面第105行的
 %比例係數k設定大一些,k=0.1對採集的這幾幅影象來說是一個比較合理的經驗值
 for i = boundary:nrow-boundary+1
     for j = boundary:ncol-boundary+1
     if Corner(i,j)==1  %只關注候選點
         M = [A(i,j) C(i,j);
              C(i,j) B(i,j)];      
         CRF(i,j) = det(M)-k*(trace(M))^2;
         if CRF(i,j) > CRFmax 
            CRFmax = CRF(i,j);    
        end;            
    end
 end;             
end;  
%CRFmax
 count = 0;       % 用來記錄角點的個數
 t=0.01;        
% 下面通過一個3*3的視窗來判斷當前位置是否為角點
 for i = boundary:nrow-boundary+1 
for j = boundary:ncol-boundary+1
         if Corner(i,j)==1  %只關注候選點的八鄰域
             if CRF(i,j) > t*CRFmax && CRF(i,j) >CRF(i-1,j-1) ......%?????為什麼要CRF(i,j) > t*CRFmax啊?求大神告知
                && CRF(i,j) > CRF(i-1,j) && CRF(i,j) > CRF(i-1,j+1) ......
                && CRF(i,j) > CRF(i,j-1) && CRF(i,j) > CRF(i,j+1) ......
                && CRF(i,j) > CRF(i+1,j-1) && CRF(i,j) > CRF(i+1,j)......
                && CRF(i,j) > CRF(i+1,j+1) 
            count=count+1;%這個是角點,count加1
             else % 如果當前位置(i,j)不是角點,則在Corner(i,j)中刪除對該候選角點的記錄
                 Corner(i,j) = 0;     
            end;
         end; 
end; 
end; 
% disp('角點個數');
 % disp(count)
 figure,imshow(Image);      % display Intensity Image
 hold on; 
% toc(t1)
 for i=boundary:nrow-boundary+1 
for j=boundary:ncol-boundary+1
         column_ave=0;
         row_ave=0;
         k=0;
        if Corner(i,j)==1
             for x=i-3:i+3  %7*7鄰域
                 for y=j-3:j+3
                     if Corner(x,y)==1
 % 用算數平均數作為角點座標,如果改用幾何平均數求點的平均座標,對角點的提取意義不大
                         row_ave=row_ave+x;
                         column_ave=column_ave+y;
                         k=k+1;
                     end
                 end
             end
         end
         if k>0 %周圍不止一個角點           
             plot( column_ave/k,row_ave/k ,'g.');
         end
 end; 
end; 




採用國際會議中心的圖片進行實驗,效果如下:

原圖:

標記效果圖:

為了驗證Harris的旋轉不變性,將原圖旋轉後實驗效果如下: