关于人体动作神态好段识别中surf 中hessian阈值一般设为多少

【图文】SURF算法分析_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
SURF算法分析
上传于|0|0|文档简介
&&总结多篇论文,针对现有的SURF匹配算法进行分析
大小:661.00KB
登录百度文库,专享文档复制特权,财富值每天免费拿!
你可能喜欢算法(49)
程序运行问题(4)
【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑
本系列文章由&@浅墨_毛星云&&出品,转载请注明出处。&&&
文章链接:&
作者:毛星云(浅墨)&&& &&微博:&
写作当前博文时配套使用的OpenCV版本:&2.4.9
本篇文章中,我们一起探讨了OpenCV中重映射和SURF特征点检测相关的知识点,主要一起了解OpenCV中重映射相关的函数remap,SURF算法在OpenCV中的体现与应用。此博文一共有三个配套的麻雀虽小但五脏俱全的示例程序,其经过浅墨详细注释过的代码都在文中贴出,且文章最后提供了综合示例程序的下载。
依然是先看看程序运行截图。
SURF特征点检测:&
一、OpenCV重映射
1.1&重映射的概念简析
重映射,就是把一幅图像中某位置的像素放置到另一个图片指定位置的过程。&为了完成映射过程, 我们需要获得一些插值为非整数像素的坐标,因为源图像与目标图像的像素坐标不是一一对应的。&一般情况下,我们通过重映射来表达每个像素的位置 (x,y),像这样 :
g(x,y) = f ( h(x,y) )
在这里, g( ) 是目标图像, f() 是源图像, 而h(x,y) 是作用于 (x,y) 的映射方法函数。
来看个例子。 若有一幅图像 I ,想满足下面的条件作重映射:
h(x,y) = (I.cols - x, y )
这样的话,图像会按照 x 轴方向发生翻转。那么,源图像和效果图分别如下:
在OpenCV中,我们用函数remap( )来实现简单重映射,下面我们就一起来看看这个函数。
1.2&remap( )函数解析
remap( )函数会根据我们指定的映射形式,将源图像进行重映射几何变换,基于的式子如下:
需要注意,此函数不支持就地(in-place)操作。看看其原型和参数。
C++: void remap(InputArray src, OutputArraydst, InputArray map1, InputArray map2, int interpolation, intborderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位或者浮点型图像。第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放函数调用后的输出结果,需和源图片有一样的尺寸和类型。第三个参数,InputArray类型的map1,它有两种可能的表示对象。
表示点(x,y)的第一个映射。表示CV_16SC2 , CV_32FC1 或CV_32FC2类型的X值。
第四个参数,InputArray类型的map2,同样,它也有两种可能的表示对象,而且他是根据map1来确定表示那种对象。
若map1表示点(x,y)时。这个参数不代表任何值。表示CV_16UC1 , CV_32FC1类型的Y值(第二个值)。
第五个参数,int类型的interpolation,插值方式,之前的resize( )函数中有讲到,需要注意,resize( )函数中提到的INTER_AREA插值方式在这里是不支持的,所以可选的插值方式如下:
INTER_NEAREST - 最近邻插值INTER_LINEAR – 双线性插值(默认值)INTER_CUBIC – 双三次样条插值(逾4×4像素邻域内的双三次插值)INTER_LANCZOS4 -Lanczos插值(逾8×8像素邻域的Lanczos插值)
第六个参数,int类型的borderMode,边界模式,有默认值BORDER_CONSTANT,表示目标图像中“离群点(outliers)”的像素值不会被此函数修改。第七个参数,const Scalar&类型的borderValue,当有常数边界时使用的值,其有默认值Scalar( ),即默认值为0。
1.3&详细注释的重映射示例程序
下面放出精简后的以remap函数为核心的示例程序,方便大家快速掌握remap函数的使用方法。
#include&opencv2/highgui/highgui.hpp&
#include&opencv2/imgproc/imgproc.hpp&
#include &iostream&
using namespace
int main( )
MatsrcImage, dstI
Matmap_x, map_y;
srcImage= imread( &1.jpg&, 1 );
if(!srcImage.data) { printf(&读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n&); return false; }
imshow(&原始图&,srcImage);
dstImage.create(srcImage.size(), srcImage.type() );
map_x.create(srcImage.size(), CV_32FC1 );
map_y.create(srcImage.size(), CV_32FC1 );
for(int j = 0; j & srcImage.j++)
for(int i = 0; i & srcImage.i++)
map_x.at&float&(j,i)= static_cast&float&(srcImage.cols - i);
map_y.at&float&(j,i)= static_cast&float&(j);
remap(srcImage, dstImage, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0,0) );
imshow(&【程序窗口】&, dstImage );
waitKey();
显示效果图:
&最近在举行世界杯,这里的图片素材就是巴西队的球星们~
1.4&OpenCV2.X中remap函数源代码
这里我们放出remap函数的源码,供需要了解其实现细节的朋友们观看,浅墨在这里不花时间对其进行剖析。
void cv::remap( InputArray _src,OutputArray _dst,
InputArray _map1, InputArray_map2,
int interpolation, intborderType, const Scalar& borderValue )
static RemapNNFunc nn_tab[] =
remapNearest&uchar&, remapNearest&schar&,remapNearest&ushort&, remapNearest&short&,
remapNearest&int&, remapNearest&float&,remapNearest&double&, 0
static RemapFunc linear_tab[] =
remapBilinear&FixedPtCast&int, uchar, INTER_REMAP_COEF_BITS&,RemapVec_8u, short&, 0,
remapBilinear&Cast&float, ushort&, RemapNoVec, float&,
remapBilinear&Cast&float, short&, RemapNoVec, float&, 0,
remapBilinear&Cast&float, float&, RemapNoVec, float&,
remapBilinear&Cast&double, double&, RemapNoVec, float&, 0
static RemapFunc cubic_tab[] =
remapBicubic&FixedPtCast&int, uchar, INTER_REMAP_COEF_BITS&,short, INTER_REMAP_COEF_SCALE&, 0,
remapBicubic&Cast&float, ushort&, float, 1&,
remapBicubic&Cast&float, short&, float, 1&, 0,
remapBicubic&Cast&float, float&, float, 1&,
remapBicubic&Cast&double, double&, float, 1&, 0
static RemapFunc lanczos4_tab[] =
remapLanczos4&FixedPtCast&int, uchar, INTER_REMAP_COEF_BITS&,short, INTER_REMAP_COEF_SCALE&, 0,
remapLanczos4&Cast&float, ushort&, float, 1&,
remapLanczos4&Cast&float, short&, float, 1&, 0,
remapLanczos4&Cast&float, float&, float, 1&,
remapLanczos4&Cast&double, double&, float, 1&, 0
Mat src = _src.getMat(), map1 = _map1.getMat(), map2 = _map2.getMat();
CV_Assert( map1.size().area() & 0 );
CV_Assert( !map2.data || (map2.size() == map1.size()));
_dst.create( map1.size(), src.type() );
Mat dst = _dst.getMat();
if( dst.data == src.data )
src = src.clone();
int depth = src.depth();
RemapNNFunc nnfunc = 0;
RemapFunc ifunc = 0;
const void* ctab = 0;
bool fixpt = depth == CV_8U;
bool planar_input = false;
if( interpolation == INTER_NEAREST )
nnfunc = nn_tab[depth];
CV_Assert( nnfunc != 0 );
if( interpolation == INTER_AREA )
interpolation = INTER_LINEAR;
if( interpolation == INTER_LINEAR )
ifunc = linear_tab[depth];
else if( interpolation == INTER_CUBIC )
ifunc = cubic_tab[depth];
else if( interpolation == INTER_LANCZOS4 )
ifunc = lanczos4_tab[depth];
CV_Error( CV_StsBadArg, &Unknown interpolation method& );
CV_Assert( ifunc != 0 );
ctab = initInterTab2D( interpolation, fixpt );
const Mat *m1 = &map1, *m2 = &map2;
if( (map1.type() == CV_16SC2 && (map2.type() == CV_16UC1 ||map2.type() == CV_16SC1 || !map2.data)) ||
(map2.type() == CV_16SC2 && (map1.type() == CV_16UC1 ||map1.type() == CV_16SC1 || !map1.data)) )
if( map1.type() != CV_16SC2 )
std::swap(m1, m2);
CV_Assert( ((map1.type() == CV_32FC2 || map1.type() == CV_16SC2)&& !map2.data) ||
(map1.type() == CV_32FC1 && map2.type() == CV_32FC1) );
planar_input = map1.channels() == 1;
RemapInvoker invoker(src, dst, m1, m2, interpolation,
borderType,borderValue, planar_input, nnfunc, ifunc,
parallel_for_(Range(0, dst.rows), invoker,dst.total()/(double)(1&&16));
好了,重映射先就讲这么多,在文章末尾还有一个综合一点的示例程序供大家学习。下面我们开始讲解SURF相关的内容。
二.SURF特征点检测
SURF算法有一些不错的内容和用法,OpenCV中使用颇多,浅墨会花一些篇幅对其进行讲解。今天的这篇文章只是一个小小的开头,主要介绍SURF特征点检测。
先简单了解一下SURF算法的大概内容吧。
2.1&SURF算法概览
SURF,我们简单介绍一下,英语全称为SpeededUp Robust Features,直译的话就是“加速版的具有鲁棒性的特征“算法,由Bay在2006年首次提出。SURF是尺度不变特征变换算法(SIFT算法)的加速版。一般来说,标准的SURF算子比SIFT算子快好几倍,并且在多幅图片下具有更好的稳定性。SURF最大的特征在于采用了harr特征以及积分图像的概念,这大大加快了程序的运行时间。SURF可以应用于计算机视觉的物体识别以及3D重构中。
PS: 由于我们的专栏侧重点是教大家如何快速入门OpenCV编程,不是来进行图像处理科普的,所以原理部分不会花笔墨多讲。一方面是浅墨也不喜欢讲这些枯燥的概念,另一方面是大家肯定应该也不喜欢看这些枯燥的原理,大家是喜欢看代码的?( ̄▽ ̄?)。就像小魏CPU童鞋在博客上写的,“Talk is cheap. Show me thecode.”
所以原理部分大家就自行用搜索引擎去学习吧,浅墨会将更多的笔墨用来分享网络上独一无二的干货。
2.2&前世今生——SURF类相关OpenCV源码剖析
OpenCV中关于SURF算法的部分,常常涉及到的是SURF、SurfFeatureDetector、SurfDescriptorExtractor这三个类,这一小节我们就来对他们进行人肉,挖挖其背景,看看他们究竟是什么来头。
在D:\Program Files (x86)\opencv\sources\modules\nonfree\include\opencv2\nonfree下的features2d.hpp头文件中,我们可以发现这样两句定义:
typedef SURF SurfFeatureD
typedef SURF SurfDescriptorE
我们都知道,typedef声明是为现有类型创建一个新的名字,类型别名。这就表示,SURF类忽然同时有了两个新名字SurfFeatureDetector以及SurfDescriptorExtractor。
也就是说,我们平常使用的SurfFeatureDetector类和SurfDescriptorExtractor类,其实就是SURF类,他们三者等价。
然后在这两句定义的上方,我们可以看到SURF类的类声明全貌:
class CV_EXPORTS_W SURF : public Feature2D
CV_WRAP SURF();
explicit CV_WRAP SURF(double hessianThreshold,
int nOctaves=4, intnOctaveLayers=2,
bool extended=true, boolupright=false);
CV_WRAP int descriptorSize() const;
CV_WRAP int descriptorType() const;
void operator()(InputArray img, InputArray mask,
CV_OUTvector&KeyPoint&& keypoints) const;
void operator()(InputArray img, InputArray mask,
CV_OUTvector&KeyPoint&& keypoints,
OutputArray descriptors,
booluseProvidedKeypoints=false) const;
AlgorithmInfo* info() const;
CV_PROP_RW double hessianT
CV_PROP_RW int nO
CV_PROP_RW int nOctaveL
CV_PROP_RW bool
CV_PROP_RW bool
protected:
void detectImpl( const Mat& image, vector&KeyPoint&&keypoints, const Mat& mask=Mat() ) const;
void computeImpl( const Mat& image, vector&KeyPoint&&keypoints, Mat& descriptors ) const;
可以发现SURF类公共继承自Feature2D类,我们再次进行转到,可以在路径d:\Program Files(x86)\opencv\build\include\opencv2\features2d\features2d.hpp看到Feature2D类的声明:
class CV_EXPORTS_W Feature2D : public FeatureDetector,public DescriptorExtractor
CV_WRAP_AS(detectAndCompute) virtual voidoperator()( InputArray image, InputArray mask,
CV_OUTvector&KeyPoint&& keypoints,
OutputArray descriptors,
bool useProvidedKeypoints=false ) const =0;
CV_WRAP void compute( const Mat& image, CV_OUT CV_IN_OUTstd::vector&KeyPoint&& keypoints, CV_OUT Mat& descriptors )const;
CV_WRAP static Ptr&Feature2D& create( const string& name );
显然,Feature2D类又是公共继承自FeatureDetector以及 DescriptorExtractor类。继续刨根问底,我们看看其父类FeatureDetector以及 DescriptorExtractor类的定义:
首先是FeatureDetector类:
class CV_EXPORTS_W FeatureDetector : publicvirtual Algorithm
virtual ~FeatureDetector();
CV_WRAP void detect( const Mat& image, CV_OUTvector&KeyPoint&& keypoints, const Mat& mask=Mat() ) const;
void detect( const vector&Mat&& images,vector&vector&KeyPoint& && keypoints, constvector&Mat&& masks=vector&Mat&() ) const;
CV_WRAP virtual bool empty() const;
CV_WRAP static Ptr&FeatureDetector& create( const string&detectorType );
protected:
virtual void detectImpl( const Mat& image,vector&KeyPoint&& keypoints, const Mat& mask=Mat() ) const = 0;
static void removeInvalidPoints( const Mat& mask,vector&KeyPoint&& keypoints );
这里,我们发现了我们经常会用到的detect( )方法重载的两个原型,原来是SURF类经过两层的继承,从FeatureDetector类继承而来。
* Detect keypoints in an image.
The image.
* keypoints The detectedkeypoints.
Mask specifyingwhere to look for keypoints (optional). Must be a char
matrix withnon-zero values in the region of interest.
CV_WRAP void detect( const Mat& image, CV_OUTvector&KeyPoint&& keypoints, const Mat& mask=Mat() ) const;
* Detect keypoints in an image set.
Image collection.
* keypoints Collection of keypoints detected in aninput images. keypoints[i] is a set of keypoints detected in an images[i].
Masks for imageset. masks[i] is a mask for images[i].
void detect( const vector&Mat&& images,vector&vector&KeyPoint& && keypoints, constvector&Mat&& masks=vector&Mat&() ) const;
同样,看看SURF类的另一个“爷爷”DescriptorExtractor类的声明
class CV_EXPORTS_W DescriptorExtractor :public virtual Algorithm
virtual ~DescriptorExtractor();
CV_WRAP void compute( const Mat& image, CV_OUT CV_IN_OUTvector&KeyPoint&& keypoints, CV_OUT Mat& descriptors ) const;
void compute( const vector&Mat&& images,vector&vector&KeyPoint& && keypoints, vector&Mat&&descriptors ) const;
CV_WRAP virtual int descriptorSize() const = 0;
CV_WRAP virtual int descriptorType() const = 0;
CV_WRAP virtual bool empty() const;
CV_WRAP static Ptr&DescriptorExtractor& create( const string&descriptorExtractorType );
protected:
virtual void computeImpl( const Mat& image,vector&KeyPoint&& keypoints, Mat& descriptors ) const = 0;
static void removeBorderKeypoints( vector&KeyPoint&&keypoints,
SizeimageSize, int borderSize );
上述代码表明FeatureDetector 类和DescriptorExtractor类都虚继承自Algorithm基类。
历经千辛万苦,终于,我们找到SURF类德高望重的祖先——OpenCV中的Algorithm基类。看看其原型声明:
class CV_EXPORTS_W Algorithm
Algorithm();
virtual ~Algorithm();
string name() const;
template&typename _Tp& typename ParamType&_Tp&::member_typeget(const string& name) const;
template&typename _Tp& typename ParamType&_Tp&::member_typeget(const char* name) const;
CV_WRAP int getInt(const string& name) const;
CV_WRAP double getDouble(const string& name) const;
CV_WRAP bool getBool(const string& name) const;
CV_WRAP string getString(const string& name) const;
CV_WRAP Mat getMat(const string& name) const;
CV_WRAP vector&Mat& getMatVector(const string& name) const;
CV_WRAP Ptr&Algorithm& getAlgorithm(const string& name) const;
void set(const string& name, int value);
void set(const string& name, double value);
void set(const string& name, bool value);
void set(const string& name, const string& value);
void set(const string& name, const Mat& value);
void set(const string& name, const vector&Mat&& value);
void set(const string& name, const Ptr&Algorithm&& value);
template&typename _Tp& void set(const string& name, constPtr&_Tp&& value);
CV_WRAP void setInt(const string& name, int value);
CV_WRAP void setDouble(const string& name, double value);
CV_WRAP void setBool(const string& name, bool value);
CV_WRAP void setString(const string& name, const string& value);
CV_WRAP void setMat(const string& name, const Mat& value);
CV_WRAP void setMatVector(const string& name, constvector&Mat&& value);
CV_WRAP void setAlgorithm(const string& name, constPtr&Algorithm&& value);
template&typename _Tp& void setAlgorithm(const string& name,const Ptr&_Tp&& value);
void set(const char* name, int value);
void set(const char* name, double value);
void set(const char* name, bool value);
void set(const char* name, const string& value);
void set(const char* name, const Mat& value);
void set(const char* name, const vector&Mat&& value);
void set(const char* name, const Ptr&Algorithm&& value);
template&typename _Tp& void set(const char* name, constPtr&_Tp&& value);
void setInt(const char* name, int value);
void setDouble(const char* name, doublevalue);
void setBool(const char* name, bool value);
void setString(const char* name, const string& value);
void setMat(const char* name, const Mat& value);
void setMatVector(const char* name, const vector&Mat&& value);
void setAlgorithm(const char* name, const Ptr&Algorithm&&value);
template&typename _Tp& void setAlgorithm(const char* name, constPtr&_Tp&& value);
CV_WRAP string paramHelp(const string& name) const;
int paramType(const char* name) const;
CV_WRAP int paramType(const string& name) const;
CV_WRAP void getParams(CV_OUT vector&string&& names) const;
virtual void write(FileStorage& fs) const;
virtual void read(const FileNode& fn);
typedef Algorithm* (*Constructor)(void);
typedef int (Algorithm::*Getter)() const;
typedef void (Algorithm::*Setter)(int);
CV_WRAP static void getList(CV_OUT vector&string&&algorithms);
CV_WRAP static Ptr&Algorithm& _create(const string& name);
template&typename _Tp& static Ptr&_Tp& create(conststring& name);
virtual AlgorithmInfo* info() const
{ return 0;}
关于这几个类缠绵悱恻的关系,画个图就一目了然了,也就是这样的过程:
3.3&drawKeypoints函数详解
因为接下来的示例程序需要用到drawKeypoints函数,我们在这里顺便讲一讲。
顾名思义,此函数用于绘制关键点。
C++: void drawKeypoints(const Mat&image, const vector&KeyPoint&& keypoints, Mat& outImage, constScalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT )
第一个参数,const Mat&类型的src,输入图像。第二个参数,const vector&KeyPoint&&类型的keypoints,根据源图像得到的特征点,它是一个输出参数。第三个参数,Mat&类型的outImage,输出图像,其内容取决于第五个参数标识符falgs。第四个参数,const Scalar&类型的color,关键点的颜色,有默认值Scalar::all(-1)。第五个参数,int类型的flags,绘制关键点是的特征标识符,有默认值DrawMatchesFlags::DEFAULT。&可以在如下这个结构体中选取值。
struct DrawMatchesFlags
DEFAULT = 0,
DRAW_OVER_OUTIMG = 1,
NOT_DRAW_SINGLE_POINTS = 2,
DRAW_RICH_KEYPOINTS = 4
三、综合示例部分
因为这次的两个知识点关联度不大,所以不方便组织起来成为一个综合示例程序。在这里我们分开将其放出。
3.1 &&重映射综合示例程序
先放出以remap为核心的综合示例程序,可以用按键控制四种不同的映射模式。且利用了OpenCV版本标识宏“CV_VERSION”,在帮助文字相关代码中加入了一句:
printf(&\t当前使用的OpenCV版本为 OpenCV &CV_VERSION);
便可以智能检测出当前使用的OpenCV版本,并输出。如图:
按键说明也可以由上图看出。
放出这个程序详细注释的源代码:
#include &opencv2/highgui/highgui.hpp&
#include &opencv2/imgproc/imgproc.hpp&
#include &iostream&
using namespace
using namespace std;
#define WINDOW_NAME &【程序窗口】&
//为窗口标题定义的宏
Mat g_srcImage, g_dstI
Mat g_map_x, g_map_y;
int update_map( int key);
static void ShowHelpText( );
int main( int argc, char** argv )
system(&color 2F&);
ShowHelpText();
g_srcImage = imread( &1.jpg&, 1 );
if(!g_srcImage.data ) { printf(&读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n&); return false; }
imshow(&原始图&,g_srcImage);
g_dstImage.create( g_srcImage.size(), g_srcImage.type() );
g_map_x.create( g_srcImage.size(), CV_32FC1 );
g_map_y.create( g_srcImage.size(), CV_32FC1 );
namedWindow( WINDOW_NAME, CV_WINDOW_AUTOSIZE );
imshow(WINDOW_NAME,g_srcImage);
while( 1 )
int key = waitKey(0);
if( (key & 255) == 27 )
cout && &程序退出...........\n&;
update_map(key);
remap( g_srcImage, g_dstImage, g_map_x, g_map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0, 0) );
imshow( WINDOW_NAME, g_dstImage );
int update_map( int key )
for( int j = 0; j & g_srcImage.j++)
for( int i = 0; i & g_srcImage.i++)
switch(key)
if( i & g_srcImage.cols*0.25 && i & g_srcImage.cols*0.75 && j & g_srcImage.rows*0.25 && j & g_srcImage.rows*0.75)
g_map_x.at&float&(j,i) = static_cast&float&(2*( i - g_srcImage.cols*0.25 ) + 0.5);
g_map_y.at&float&(j,i) = static_cast&float&(2*( j - g_srcImage.rows*0.25 ) + 0.5);
g_map_x.at&float&(j,i) = 0;
g_map_y.at&float&(j,i) = 0;
g_map_x.at&float&(j,i) = static_cast&float&(i);
g_map_y.at&float&(j,i) = static_cast&float&(g_srcImage.rows - j);
g_map_x.at&float&(j,i) = static_cast&float&(g_srcImage.cols - i);
g_map_y.at&float&(j,i) = static_cast&float&(j);
g_map_x.at&float&(j,i) = static_cast&float&(g_srcImage.cols - i);
g_map_y.at&float&(j,i) = static_cast&float&(g_srcImage.rows - j);
static void ShowHelpText()
printf(&\n\n\n\t欢迎来到重映射示例程序~\n\n&);
printf(&\t当前使用的OpenCV版本为 OpenCV &CV_VERSION);
printf( &\n\n\t按键操作说明: \n\n&
&\t\t键盘按键【ESC】- 退出程序\n&
&\t\t键盘按键【1】-
第一种映射方式\n&
&\t\t键盘按键【2】- 第二种映射方式\n&
&\t\t键盘按键【3】- 第三种映射方式\n&
&\t\t键盘按键【4】- 第四种映射方式\n&
&\n\n\t\t\t\t\t\t\t\t by浅墨\n\n\n&
运行效果图。首先是原始图:
第一种重映射:
第二种重映射:&
第三种重映射:&
第四种重映射:&
3.2&SURF特征点检测综合示例程序
这个示例程涉及到如下三个方面:
使用 FeatureDetector 接口来发现感兴趣点。使用 SurfFeatureDetector 以及其函数 detect 来实现检测过程使用函数 drawKeypoints 绘制检测到的关键点。
详细注释的源代码:
#include &opencv2/core/core.hpp&
#include &opencv2/features2d/features2d.hpp&
#include &opencv2/highgui/highgui.hpp&
#include &opencv2/nonfree/nonfree.hpp&
#include &iostream&
using namespace
static void ShowHelpText( );
int main( int argc, char** argv )
system(&color 2F&);
ShowHelpText( );
Mat srcImage1 = imread(&1.jpg&, 1 );
Mat srcImage2 = imread(&2.jpg&, 1 );
if( !srcImage1.data || !srcImage2.data )
{ printf(&读取图片错误,请确定目录下是否有imread函数指定名称的图片存在~! \n&); return false; }
imshow(&原始图1&,srcImage1);
imshow(&原始图2&,srcImage2);
int minHessian = 400;
SurfFeatureDetector detector( minHessian );
std::vector&KeyPoint& keypoints_1, keypoints_2;
detector.detect( srcImage1, keypoints_1 );
detector.detect( srcImage2, keypoints_2 );
Mat img_keypoints_1; Mat img_keypoints_2;
drawKeypoints( srcImage1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
drawKeypoints( srcImage2, keypoints_2, img_keypoints_2, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
imshow(&特征点检测效果图1&, img_keypoints_1 );
imshow(&特征点检测效果图2&, img_keypoints_2 );
waitKey(0);
void ShowHelpText()
printf(&\n\n\n\t欢迎来到【SURF特征点检测】示例程序~\n\n&);
printf(&\t当前使用的OpenCV版本为 OpenCV &CV_VERSION);
printf( &\n\n\t按键操作说明: \n\n&
&\t\t键盘按键任意键- 退出程序\n\n&
&\n\n\t\t\t\t\t\t\t\t by浅墨\n\n\n&);
运行效果图。
第一组图片对比效果:
第二组图片对比效果:
本篇文章的配套源代码请点击这里下载:
【浅墨OpenCV入门教程之十七】配套源代码之重映射下载
【浅墨OpenCV入门教程之十七】配套源代码之SURF特征点检测下载
OK,今天的内容大概就是这些,我们下篇文章见:)
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:43195次
排名:千里之外
转载:94篇
(1)(4)(1)(6)(12)(46)(2)(27)(1)(1)

我要回帖

更多关于 人体动作姿态识别综述 的文章

 

随机推荐