ubuntu下安装OpenCV的过程可以参考这篇博客。其他的版本可能会有一些问题,但是应该可以按照代码的思路简单解决。
#include
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/legacy/legacy.hpp"
#include
using namespace std;
using namespace cv;
void MySusan(Mat imageGray, vector<Point2f>& corners);
int main(int argc, char **argv)
{
Mat image1 = imread("../image/1.jpg", 1);//读取图像
Mat image2 = imread("../image/2.jpg", 1);//读取图像
Mat imageGray1,imageGray2;
cvtColor(image1,imageGray1,CV_RGB2GRAY);//将彩色图转化为灰度图
cvtColor(image2,imageGray2,CV_RGB2GRAY);//将彩色图转化为灰度图
IplImage pBinary1 = image1,pBinary2 = image2;
IplImage *input1 = cvCloneImage(&pBinary1);//转化为iplpmage类型指针
IplImage *input2 = cvCloneImage(&pBinary2);//转化为iplpmage类型指针
vector<Point2f> corners1,corners2; //角点
vector<KeyPoint> keypoints1,keypoints2; //关键点
MySusan(imageGray1, corners1);
MySusan(imageGray2, corners2);
CvScalar color1 =CV_RGB(255,0,0);
CvScalar color2 =CV_RGB(0,255,0);
for(int i=0;i<corners1.size();i++)
{
cvCircle(input1, cvPoint((int)(corners1[i].x), (int)(corners1[i].y)), 2, color1, 1, CV_AA, 0);//圈出角点
}
for(int i=0;i<corners2.size();i++)
{
cvCircle(input2, cvPoint((int)(corners2[i].x), (int)(corners2[i].y)), 2, color2, 1, CV_AA, 0);//圈出角点
}
KeyPoint::convert(corners1,keypoints1);
KeyPoint::convert(corners2,keypoints2);
//特征点描述,为下边的特征点匹配做准备
// SiftDescriptorExtractor SiftDescriptor;
BriefDescriptorExtractor Descriptor;
Mat imageDesc1, imageDesc2;
Descriptor.compute(imageGray1,keypoints1 , imageDesc1);
Descriptor.compute(imageGray2, keypoints2, imageDesc2);
BruteForceMatcher< L2<float> > matcher;
// FlannBasedMatcher< L2 > matcher;
vector<vector<DMatch> > matchePoints;
vector<DMatch> GoodMatchePoints;
matcher.knnMatch(imageDesc2, imageDesc1, matchePoints,2);//获取两个最优匹配点,在imageDesc2中找imageDesc1的2个最佳匹配点
cout << "total match points: " << matchePoints.size() << endl;
// Lowe's algorithm,获取优秀匹配点
for (int i = 0; i < matchePoints.size(); i++)
{
if (matchePoints[i][0].distance < 0.4 * matchePoints[i][1].distance)
{
GoodMatchePoints.push_back(matchePoints[i][0]);
}
}
cout << "GoodMatchePoints: " << GoodMatchePoints.size() << endl;
Mat first_match;
drawMatches(image2, keypoints2, image1, keypoints1, GoodMatchePoints, first_match);
imshow("first_match ", first_match);
imwrite("first_match.jpg", first_match);
// cout<<"corners1.size="<
// cout<<"corners2.size="<
// imshow("imageBefore1",image1);
// cvShowImage("imageAfter1",input1);
// cvSaveImage( "ImageAfter1.jpg", input1);
// imshow("imageBefore2",image2);
// cvShowImage("imageAfter2",input2);
// cvSaveImage( "ImageAfter2.jpg", input2);
waitKey();
return 0;
}
//susan角点检测
//输入灰度图,输出角点
void MySusan(Mat imageGray, vector<Point2f>& corners)
{
long int Imagewidth=imageGray.cols;
long int Imageheight=imageGray.rows;//得到图像高宽
cout<<"Imagewidth="<<Imagewidth<<" Imageheight=" <<Imageheight<<endl;
int threshold = 50; //判断灰度相近的阈值(可调)
long int i,j,c=0,u=0,g=0,max=0;
int usan[(Imagewidth-6)*(Imageheight-6)]; // 当前像素和窗体内像素差别在t以下的个数,即相似的个数(一维)
int imgn[Imageheight-6][Imagewidth-6]; // 当前像素和窗体内像素差别在t以下的个数,即相似的个数(二维)
uchar *p1,*p2,*p3;
// 计算以像素为中心的窗体内包含的
// 包含37个像素的圆窗口,面积为12*pi=37,因此是以sqrt(12)为半径的原
// 没有在外围扩展图像,最终图像会缩小
for(i=3;i<Imageheight-3;i++)
{
p1=imageGray.ptr<uchar>(i);
for(j=3;j<Imagewidth-3;j++)
{
//从原图中截取7*7的区域再在其中挑选圆窗
Rect rect(j-3, i-3, 7,7);
Mat image_tmp = imageGray(rect);
//c表示灰度值相近的程度,越大越相近
c=0;
for(int p=0;p<7;p++)
{
p2=image_tmp.ptr<uchar>(p);
for(int q=0;q<7;q++)
{
//在7*7的区域中选取圆窗包含的像素
if((pow(p-3,2)+pow(q-3,2))<=12)
{
// 判断灰度是否相近,t是自己设置的
if(abs(p1[j]-p2[q])<=threshold)
{
c++;
}
}
}
}
usan[u++]=c;
}
}
cout<<"usansize="<<(Imagewidth-6)*(Imageheight-6)<<endl;
for(i=0;i<(Imagewidth-6)*(Imageheight-6);i++)
{
if(usan[i]>g) g=usan[i]; //找最大值
}
// 相当于进一步调整阈值,在threshold的基础上进一步减少角点个数
g=0.5*g; //g通常取max/2
for(i=0;i<(Imagewidth-6)*(Imageheight-6);i++)
{
if(usan[i]<g)
usan[i]=g-usan[i];
else
usan[i]=0;
}
for(i=0;i<Imageheight-6;i++)
{
for(j=0;j<Imagewidth-6;j++)
{
imgn[i][j]=usan[i*(Imagewidth-6)+j];
}
}
// 非极大抑制
//3*3
for(i=1;i<Imageheight-7;i++)
{
for(j=1;j<Imagewidth-7;j++)
{
if(imgn[i][j]>imgn[i-1][j-1]&&imgn[i][j]>imgn[i-1][j]&&imgn[i][j]>imgn[i-1][j+1]&&imgn[i][j]>imgn[i][j-1]
&&imgn[i][j]>imgn[i][j+1]&&imgn[i][j]>imgn[i+1][j-1]&&imgn[i][j]>imgn[i+1][j]&&imgn[i][j]>imgn[i+1][j+1])
{
corners.push_back(cvPoint(j+3,i+3));//之前是从第3行3列开始检测的,这里加上3
}
}
}
}
Paper: SUSAN — A New Approach to Low Level Image Processing