Matlab/OpenCV自己实现Harris特征点提取和匹配

一 实现Harris特征点提取

使用Matlab自己实现Harris特征点提取


function [ result,cnt] = Harris( img )
%R=det(M)-k.*tr(M).^2  k=0.04~0.06  we set k=0.04
[m,n]=size(img);
ori_img=img;
img=double(img);
h=[-2 -1 0 1 2];
Ix=filter2(h,img);  %  gradient on x
Iy=filter2(h',img); %  gradient on y
Ixx=Ix.^2;
Iyy=Ix.^2;
Ixy=Ix.*Iy;
Gauss=fspecial('gaussian',[7 7],2);  %window 7*7 ;sigma=2
Ixx=filter2(Gauss,Ixx);
Iyy=filter2(Gauss,Iyy);
Ixy=filter2(Gauss,Ixy);

% matrix instead of loop to compute matrix R
k=0.06;               
Mdet=Ixx.*Iyy-Ixy.^2; 
Mtr=Ixx+Iyy;        
R=Mdet-k.*Mtr.^2;

% k=0.06;
% R=zeros(m,n);
% for i=1:m
%     for j=1:n
%         M=[Ixx(i,j) Ixy(i,j);Ixy(i,j) Iyy(i,j)];
%         R(i,j)=det(M)-k*(trace(M))^2;
%     end;
% end;

Rmax=max(R(:));
T=0.01*Rmax;
result=zeros(m,n);

%searh the matrix R, if R(i,j)>T as well as the surrounding points,R(i,j) is
%a corner point
cnt=0;
for i=2:m-1
    for j=2:n-1
       if (R(i, j) > T && 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)=255;
            cnt=cnt+1;
        end;
    end;
end;

%plot the corner points
[r,c]=find(result==255);
figure;
imshow(ori_img);
hold on;
plot(c,r,'r+');
end



将以上代码改写成OpenCV+C++

#include<opencv2/opencv.hpp>  
#include <math.h>

using namespace cv;
using namespace std;

int main()
{
	Mat img=imread("E:/corner.jpg",0);  // read as uchar 1 channel  the directory name /
	//cout<<img1.at<uchar>(1,1)<<endl;
	namedWindow("image",WINDOW_AUTOSIZE); 
	imshow("Original1",img);
	img.convertTo(img,CV_32F);
	Mat kernel=(Mat_<float>(1,5)<<-2,-1,0,1,2);
	cout<<kernel<<endl;
	cout<<kernel.t()<<endl;
	
	Mat Ix;
	cv::filter2D(img,Ix,img.depth(),kernel);
	Mat Iy;
	cv::filter2D(img,Iy,img.depth(),kernel.t());
	cout<<"Ix"<<Ix.size()<<endl;
	cout<<"Iy"<<Iy.size()<<endl;

	Mat Ixx=Ix.mul(Ix);
	Mat Iyy=Iy.mul(Iy);
	Mat Ixy=Ix.mul(Iy); //mul=.*
	
	Mat Gauss;
	Size size(7,7);
	cv::GaussianBlur(Ixx,Ixx,size,2);
	cv::GaussianBlur(Iyy,Iyy,size,2);
	cv::GaussianBlur(Ixy,Ixy,size,2);
	
	int k=0.06;
	Mat Mdet=Ixx.mul(Iyy)-Ixy.mul(Ixy);
	Mat Mtr=Ixx+Iyy;
	Mat R=(Mdet-Mtr.mul(Mtr,k));
	double Rmin,Rmax;
	cv::minMaxIdx(R,&Rmin,&Rmax);
	float T=(float)0.01*Rmax;
	cout<<"Rmax="<<Rmax;
	Mat result=Mat::zeros(img.rows,img.cols,CV_8UC1);

	//R.at<double>(1,1)=1;
	int cnt=0;
	R.at<float>(1,1)=1;

	for(int i=2;i<img.rows-1;i++)  //不知道为什么 2 和rows-1才行,对没错,0-rows-1 ,再加上-1,+1上下界
		for(int j=2;j<img.cols-1;j++)
		{
			if (R.at<float>(i,j) > T && R.at<float>(i,j) > R.at<float>(i-1,j-1) && R.at<float>(i,j) > R.at<float>(i-1,j) && R.at<float>(i,j) > R.at<float>(i-1,j+1) && R.at<float>(i,j) > R.at<float>(i,j-1) &&R.at<float>(i,j) > R.at<float>(i,j+1) && R.at<float>(i,j) > R.at<float>(i+1,j-1) && R.at<float>(i,j) > R.at<float>(i+1,j) && R.at<float>(i,j) > R.at<float>(i+1,j+1))
				{
					result.at<uchar>(i,j)=255;		
					cv::circle(img,Point(j,i),2,Scalar(0),2,8,0);
			     }
		}

    //如果不归一化,那么会因为float太大,而导致画面一片白,均超过255,所以必须要归一化,基本都要有这一
	cv::normalize(img, img, 0, 255, NORM_MINMAX, CV_8U,Mat());
    imshow("output",img);
	waitKey(0);
	return 0;

}


二 特征点匹配 
        matlab实现特征点匹配,匹配度量为特征点11X11大小邻域之间的归一化互相关
main函数
 I1=imread('pic1\SAR_airport.tif'); 
 I2=imread('pic1\optical_airport.tif');
 
[ result1,cnt1] = Harris( I1 );
[ result2,cnt2] = Harris( I2 );
[ match_pt1,match_pt2 ] = cornerMatch( I1,I2,result1,result2,cnt1,cnt2); %img1<=img2

DrawMatch( I1, match_pt1', I2, match_pt2' );

匹配函数CornerMatch
function [ match_pt1,match_pt2 ] = cornerMatch( img1,img2,result1,result2,cnt1,cnt2)
[r1,c1]=find(result1==255);
[r2,c2]=find(result2==255);
pt1=[r1 c1]; % N*2 matrix
pt2=[r2 c2];
temp_pt2=zeros(size(pt1));
NCC=zeros(cnt1,cnt2);
% since the windows is too big , it is unwise to ignore the edge of img 
% however, it can be complicated to consider edge,so we extend the img
% instead of consider edge 
k=5;

EXimg1=extendimg(img1,k);
EXimg2=extendimg(img2,k);

%calculate the NCC of each point's 11*11 neighbourhood
for i=1:cnt1
    p=pt1(i,1)+k;q=pt1(i,2)+k;     
    Win1=EXimg1(p-5:p+5,q-5:q+5); % a window 11*11 around the corner in img1
    for j=1:cnt2
        m=pt2(j,1)+k;n=pt2(j,2)+k;                   
        Win2=EXimg2(m-5:m+5,n-5:n+5);% a window 11*11 around the corner in img2
        NCC(i,j)= NCC_cal(Win1,Win2);
    end   
%     NNR=0.8    
    MAX=max(NCC(i,:)); %max value of each col
    [r,c]=find(NCC(i,:)==MAX);    
    NCC(NCC==MAX)=0;
    SEC=max(NCC(i,:));
    NNR=double(SEC/MAX);   
    if NNR<0.8
      temp_pt2(i,:)=pt2(c,:);  
    else
      temp_pt2(i,:)=0;
    end;       
end;

cnt=numel(temp_pt2,temp_pt2~=0)/2;
match_pt1=zeros(cnt,2);
match_pt2=zeros(cnt,2);
j=1;
for i=1:cnt1
    if((temp_pt2(i,1)~=0)&&(pt1(i,1)~=0))
        match_pt2(j,:)=temp_pt2(i,:);        
        match_pt1(j,:)=pt1(i,:);
        j=j+1;    
    end;
end;



end
%.................Extend the img ............................
  function [ Eximg1 ] = extendimg( img1,k)
[L1,W1]=size(img1);
Eximg1=zeros(L1+2*k+1,W1+2*k+1);
Eximg1(k+1:k+L1,k+1:k+W1)=img1;

Eximg1(1:k,k+1:W1+k)=Eximg1(1:k,1:W1);                 %extend up
Eximg1(1:L1+k,W1+k+1:W1+2*k+1)=Eximg1(1:L1+k,W1:W1+k);    %extend right
Eximg1(L1+k+1:L1+2*k+1,k+1:W1+2*k+1)=Eximg1(L1:L1+k,k+1:W1+2*k+1);    %extend down
Eximg1(1:L1+2*k+1,1:k)=Eximg1(1:L1+2*k+1,k+1:2*k);       %extend left
end
计算归一化互相关函数NCC_CAL
function [ NCC ] = NCC_cal(I1,I2 )
%UNTITLED2 Summary of this function goes here
%   Detailed explanation goes here
N1=I1-mean(I1(:));

N2=I2-mean(I2(:));
        
M1=sum(sum(N1.*N2));
        
M2=sqrt(sum(sum(N1.^2))*sum(sum(N1.^2)));
        
NCC=abs(M1/M2);  

end

画图函数Draw
function DrawMatch( Img1, m1, Img2, m2 )
%DRAWMATCH 
    [x1, y1]=size(Img1);
    [x2, y2]=size(Img2);
    x = max(x1,x2);
    Img = zeros(x,y1+y2);
    Img(1:x1,1:y1)=Img1;
    Img(1:x2,y1+1:y2+y1)=Img2;
    figure;imshow(uint8(Img));
    for n=1:length(m1)
        hold on;
        plot(m1(2,n),m1(1,n),'r+');
        plot(y1+m2(2,n),m2(1,n),'r+');
        S=[m1(2,n),y1+m2(2,n)];
        T=[m1(1,n),m2(1,n)];
        line(S,T);
    end
    hold off;
            
end

匹配结果
图1



当然Matlab本身也有Harris特征点提取函数,实现函数如下
%function HarrisMatch(image1, image2)
tic;
 %  I1 = rgb2gray(imread('PentagonLight.jpg'));

%I2 = imresize(imrotate(I1,0), 1.4);


I1 = imread('H1H1_20140705_113340_003_CUT2.tif');
I2 = imread('H1V1_20140705_113340_003_CUT1.tif');
%I2 = imresize(imrotate(I1,30), 1);

if (ndims(I1)==3) 
   I1 = rgb2gray(I1);
end
 if (ndims(I2)==3) 
   I2 = rgb2gray(I2);
 end


points1 = detectHarrisFeatures(I1);
points2 = detectHarrisFeatures(I2);

[f1, vpts1] = extractFeatures(I1, points1);
[f2, vpts2] = extractFeatures(I2, points2);

index_pairs = matchFeatures(f1, f2) ;
matched_pts1 = vpts1(index_pairs(:, 1),:);
matched_pts2 = vpts2(index_pairs(:, 2),:);

figure; showMatchedFeatures(I1,I2,matched_pts1,matched_pts2,'montage');
legend('matched points 1','matched points 2');
toc;
效果如下


可以看到在数量和准确性上都被系统自带的Harris算法完爆一条街,毕竟是按照原理性编写,许多方面没有考虑到,也没有双向匹配


Harris角点配准方法分析

性能分析:

Harris角点抗旋转,抗仿射变换,但是不抗尺度

如下图所示



猜你喜欢

转载自blog.csdn.net/Z5337209/article/details/44202365