学习之角点检测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角点');

学习之角点检测Harris_第1张图片

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



你可能感兴趣的:(算法,性能,matlab,图像处理)