學習之角點檢測Harris

      角點是圖像亮度發生劇烈變化或者圖像邊緣曲線上曲率極大值的點。角點檢測方法主要分兩類:基於圖像邊緣的方法和基於圖像灰度的方法。前者往往需要對圖像邊緣進行編碼,這在很大程度上依賴於圖像的分割和邊緣提取,具有相當大的難度和計算量,且一旦待檢測目標局部發生變化,很有可能導致操作的失敗。基於圖像灰度的方法通過計算點的曲率及梯度來檢測角點,避免了第一類方法存在的缺點,是目前研究的重點。評價角點檢測算法性能優劣主要從以下5個方面:

     (1)準確性:即使很細小的角點,也能檢測到;

     (2)定位性:檢測到的角點應儘可能地接近它們在圖像中的真實位置;

     (3)穩定性:對相同場景拍攝的多幅圖片,每一個角點的位置都不應該移動;

     (4)實時性:角點檢測算法的計算量越小,運行速度越快越好;

     (5)魯棒性:對噪聲具有抗干擾性。

      基於圖像邊緣:Rosenfeld和Freeman等人的方法,後期有CCS等方法。基於圖像灰度:Moravec算子、Forstener算子、Harris算子、SUSAN算子等。本文先介紹Harris算子,Harris算子具有平移和旋轉不變性,對光照條件的變化不敏感:

      1、先調用MATLAB函數檢測圖像Harris角點特徵,其中I是輸入的圖像矩陣,C爲角點量度矩陣,用來檢測圖像I中的角點信息,並與I同尺寸,C的值越大表示圖像I中的像素越有可能是一個角點。

clear all;close all;clc;
I=imread('5.jpg');
I=rgb2gray(I);
subplot(1,3,1);imshow(I);title('yuan');

%生成角點度量矩陣
C=cornermetric(I,'harris');
C_adjusted=imadjust(C);%imadjust在數字圖像處理中用於進行圖像的灰度變換
subplot(1,3,2);imshow(C_adjusted);title('角點矩陣');

%尋找並顯示Harris角點
corner_peaks=imregionalmax(C);
corner_idx=find(corner_peaks==true);
[r b g]=deal(I);
r(corner_idx)=255;
g(corner_idx)=255;
b(corner_idx)=0;
RGB=cat(3,r,g,b);
subplot(1,3,3);imshow(RGB);title('檢測出的Harris角點');


2、(1)計算圖像I(x,y)在X和Y方向的梯度Ix、Iy.

       (2)計算圖像兩個方向梯度的乘積

       (3)使用高斯函數對Ix^2、Iy.^2和Ixy進行高斯加權,生成矩陣M的元素A,B和C

       (4)計算每個像元的Harris相應值R,並對於小於某一閾值t的R置爲零

       (5)在3*3,或5*5的領域內進行非最大值抑制,局部最大值點即爲圖像中的點。(函數式子特殊符號還不太會用,因此沒寫上去,一下三段Harris代碼,網速不穩定,結果圖不傳了)

clear;  
 Image = imread('01.jpg');                 % 讀取圖像  
 Image = im2uint8(rgb2gray(Image));     
    
  
dx = [-1 0 1;-1 0 1;-1 0 1];  %dx:橫向Prewitt差分模版  
 Ix2 = filter2(dx,Image).^2;     %filter2 只能對二維圖像(灰度圖)進行空間濾波
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); %矩陣Corner用來保存候選角點位置,初值全零,值爲1的點是角點  
                            %真正的角點在137和138行由(row_ave,column_ave)得到  
 %參數t:點(i,j)八鄰域的“相似度”參數,只有中心點與鄰域其他八個點的像素值之差在  
 %(-t,+t)之間,才確認它們爲相似點,相似點不在候選角點之列  
 t=20;  
 %我並沒有全部檢測圖像每個點,而是除去了邊界上boundary個像素,  
 %因爲我們感興趣的角點並不出現在邊界上  
 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;%如果周圍有0,1,7,8個相似與中心的(i,j)  
                           %那(i,j)就不是角點,所以,直接忽略  
         end;  
     end;  
 end;  
CRF = zeros(nrow,ncol);    % CRF用來保存角點響應函數值,初值全零  
 CRFmax = 0;                % 圖像中角點響應函數的最大值,作閾值之用   
t=0.05;     
% 計算CRF  
 %工程上常用CRF(i,j) =det(M)/trace(M)計算CRF,那麼此時應該將下面第105行的  
 %比例係數t設置大一些,t=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)-t*(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) > 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 ,'r.');  
         end  
 end;   
end; 
clear all; close all; clc;
ori_im2=rgb2gray(imread('5.bmp'));
fx=[5 0 -5;8 0 -8;5 0 -5];
Ix=filter2(fx,ori_im2);
fy = [5 8 5;0 0 0;-5 -8 -5];          % la gaucienne,ver axe y  
Iy = filter2(fy,ori_im2);              % la convolution vers axe y  
Ix2 = Ix.^2;  
Iy2 = Iy.^2;  
Ixy = Ix.*Iy;  
clear Ix;  
clear Iy;  
h= fspecial('gaussian',[3 3],2);      % générer une fonction gaussienne,sigma=2  
  
Ix2 = filter2(h,Ix2);  
Iy2 = filter2(h,Iy2);  
Ixy = filter2(h,Ixy);  
  
height = size(ori_im2,1);  
width = size(ori_im2,2);  
result = zeros(height,width);         % enregistrer la position du coin  
  
R = zeros(height,width);  
  
K=0.04;  
Rmax = 0;                              % chercher la valeur maximale de R  
for i = 1:height  
    for j = 1:width  
        M = [Ix2(i,j) Ixy(i,j);Ixy(i,j) Iy2(i,j)];           
        R(i,j) = det(M)-K*(trace(M))^2;                     % % calcule R  
        if R(i,j) > Rmax  
           Rmax = R(i,j);  
        end;  
    end;  
end;  
  
cnt = 0;  
for i = 2:height-1  
    for j = 2:width-1  
        % réduire des valuers minimales ,la taille de fenetre 3*3  
        if R(i,j) > 0.01*Rmax && R(i,j) > R(i-1,j-1) && R(i,j) > R(i-1,j) && R(i,j) > R(i-1,j+1) && R(i,j) > R(i,j-1) && R(i,j) > R(i,j+1) && R(i,j) > R(i+1,j-1) && R(i,j) > R(i+1,j) && R(i,j) > R(i+1,j+1)  
            result(i,j) = 1;  
            cnt = cnt+1;  
        end;  
    end;  
end;  
  
[posr2, posc2] = find(result == 1);  
cnt                                      % compter des coins  
figure  
imshow(ori_im2);  
hold on;  
plot(posc2,posr2,'w*');  

clear all;close all;clc;
image=imread('2.jpg');
in_image=rgb2gray(image);
ori_im=double(in_image); %8進制轉換爲雙精度double類型
%計算圖像在x,y兩個方向的梯度
fx=[-1 0 1];
Ix=filter2(fx,ori_im);%x方向濾波
fy=[-1;0;1];
Iy=filter2(fy,ori_im);
%計算兩個方向的梯度乘積
Ix2=Ix.^2;
Iy2=Iy.^2;
Ixy=Ix.*Iy;
%使用高斯函數對梯度乘積進行加權
%產生7*7的高斯模板。sigma=2
h=fspecial('gaussian',[7 7],2);
Ix2=filter2(h,Ix2);
Iy2=filter2(h,Iy2);
Ixy=filter2(h,Ixy);
%計算每個像元的Harris響應值
[height,width]=size(ori_im);
R=zeros(height,width);
%像素(i,j)處的Harris響應值
a=0.05;
for i=1:height
    for j=1:width
        M=[Ix2(i,j) Ixy(i,j);Ixy(i,j) Iy2(i,j)];
        R(i,j) = det(M)-a*(trace(M))^2;      
    end
end
%去掉小於閾值的Harris響應值
Rmax=max(max(R));
t=0.01*Rmax;
for i=1:height
    for j=1:width
        if R(i,j)<t
            R(i,j)=0;
        end
    end
end
%進行非極大值抑制
corner_peaks=imregionalmax(R);
countnum=sum(sum(corner_peaks));
[posr,posc]=find(corner_peaks==1);
%posc是用於存放列座標的向量
figure;imshow(in_image);hold on;
for i=1:length(posr)
    plot(posc(i),posr(i),'r+');
end



發佈了30 篇原創文章 · 獲贊 4 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章