说是surf,其实原算法是基于Notes on the OpenSURF Library这篇文档。
下载地址:http://opensurf1.googlecode.com/files/OpenSURFcpp.zip
首先定义 #define PROCEDURE 1
紧接着进入main()主函数:
main.cpp
int main(void)
{
if (PROCEDURE == 1) return mainImage();//静态图像的特征点监测
if (PROCEDURE == 2) return mainVideo();//通过摄像头实时监测,提取特征点
if (PROCEDURE == 3) return mainMatch();//图像匹配算法,在视频序列里寻找一个已知物体图像
if (PROCEDURE == 4) return mainMotionPoints();//视频中行为监测
if (PROCEDURE == 5) return mainStaticMatch();//静态图像间的特征点匹配
if (PROCEDURE == 6) return mainKmeans();//静态图像的k-means聚类
}
我们以监测静态图像特征点(即1)为例了解surf算法如何提取特征点。
int mainImage(void)
{
//声明Ipoints的向量 Declare Ipoints and other stuff
IpVec ipts;
IplImage *img=cvLoadImage("imgs/sf.jpg");
//检测与描述图像中的兴趣点 Detect and describe interest points in the image
clock_t start = clock();
surfDetDes(img, ipts, false, 5, 4, 2, 0.0004f);//SURF描述子特征提取实现函数
clock_t end = clock();
std::cout<< "OpenSURF found: " << ipts.size() << " interest points" << std::endl;
std::cout<< "OpenSURF took: " << float(end - start) / CLOCKS_PER_SEC << " seconds" << std::endl;
//绘制检测到的点 Draw the detected points
drawIpoints(img, ipts);
//显示检测结果 Display the result
showImage(img);
return 0;
}
EXP:
IpVec的定义在ipoint.h里,typedef std::vector<Ipoint> IpVec; 也就是说,IpVec是一个vector向量,每个成员是一个Ipoint。而Ipoint是一个类,也在ipoint.h里,作者将它按照结构体使用,都是public。
clock()的使用是为了测试程序运行的时间,一个记录起始时间,一个记录结束时间,最终将两者之差输出,即surfDetDes()特征提取所需要的时间。
drawIpoints()函数是在img基础上增加特征点的描述,说白了,就是添加特征点的函数。
那么,现在进入到surfDetDes()函数内部来探个究竟吧。
//URF描述子特征提取实现函数
surfDetDes定义在surflib.h里面:
//!创建兴趣点描述特征向量的库函数 Library function builds vector of described interest points
inline void surfDetDes(IplImage *img, /*检测兴趣点的图像 image to find Ipoints in */
std::vector<Ipoint> &ipts, /*兴趣点向量的引用 reference to vector of Ipoints */
bool upright = false, /*是否是旋转不变模式 run in rotation invariant mode? */
int octaves = OCTAVES, /*高斯金字塔的组数 number of octaves to calculate */
int intervals = INTERVALS, /*高斯金字塔每组的层数 number of intervals per octave */
int init_sample = INIT_SAMPLE, /*初始抽样步骤 initial sampling step */
float thres = THRES /*斑点反应阈值 blob response threshold */)
{
//创建原图像的积分图像
IplImage *int_img = Integral(img);
//创建快速海森矩阵 Create Fast Hessian Object
FastHessian fh(int_img, ipts, octaves, intervals, init_sample, thres);
//提取兴趣点并存储在向量中 Extract interest points and store in vector ipts
fh.getIpoints();
//创建Surf描述子对象 Create Surf Descriptor Object
Surf des(int_img, ipts);
//提取ipts的描述子 Extract the descriptors for the ipts
des.getDescriptors(upright);
//释放积分图像 Deallocate the integral image
cvReleaseImage(&int_img);
}