一 实现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角点抗旋转,抗仿射变换,但是不抗尺度
如下图所示