首页 > 其他分享 >特征点寻找的基础数据结构和函数

特征点寻找的基础数据结构和函数

时间:2022-12-25 21:32:27浏览次数:42  
标签:const 函数 int InputArray void 寻找 vector 数据结构 cv

    当进行跟踪时或者其他类型的用到关键点及其描述符的分析时,通常需要做三件事情:第一个是根据一些关键点的定义搜索图像并查找该图像中的所有关键点;第二个是为发现的每个关键字创建一个描述符;第三个是通过将所找到的关键点的描述符与一些现有的描述符集进行比较,看看是否可以找到匹配项。

    在跟踪应用程序中,最后一步涉及查找序列的一帧图像中的特征,并尝试将其与前一帧中的特征进行匹配。在目标检测应用程序中,人们通常会在一些(潜在的广泛)数据库中搜索“已知”特征的“已知”与各个目标或目标类相关联的特征。

    对于这些层中的每一个,OpenCV提供了一个遵循“做东西的类”(函子)模型的泛化机制;对于这些阶段中的每一个都有一个抽象基类,它为从其派生的一系列对象定义一个公共接口;最后每个派生类都实现一个特定的算法。


1、cv :: KeyPoint对象


​​
class cv : :KeyPoint {

public :

cv : :Point2f pt; // coordinates of the keypoint
float size; // diameter of the meaningful keypoint neighborhood
float angle; // computed orientation of the keypoint (-1 if none)
float response; // response for which the keypoints was selected
int octave; // octave (pyramid layer) keypoint was extracted from
int class_id; // object id, can be used to cluster keypoints by object

cv : :KeyPoint(
cv : :Point2f _pt,
float _size,
float _angle = - 1,
float _response = 0,
int _octave = 0,
int _class_id = - 1
);
cv : :KeyPoint(
float x,
float y,
float _size,
float _angle = - 1,
float _response = 0,
int _octave = 0,
int _class_id = - 1
);
...
};
​​

3种重载都包括了cv :: Point2f的信息,此外还包括其他一些能够说明“特征”的属性。

2、cv :: Feature2D


​class cv : : Feature2D : public cv : : Algorithm {
public :

virtual void detect(
cv : :InputArray image, // Image on which to detect
vector < cv : :KeyPoint > & keypoints, // Array of found keypoints
cv : :InputArray mask = cv : :noArray()
) const;

virtual void detect(
cv : :InputArrayOfArrays images, // Images on which to detect
vector <vector < cv : :KeyPoint > > & keypoints, // keypoints for each image
cv : :InputArrayOfArrays masks = cv : :noArray ()
) const;

virtual void compute(
cv : :InputArray image, // Image where keypoints are located
std : :vector <cv : :KeyPoint > & keypoints, // input/output vector of keypoints
cv : :OutputArray descriptors ); // computed descriptors, M x N matrix,
// where M is the number of keypoints
// and N is the descriptor size
virtual void compute(
cv : :InputArrayOfArrays image, // Images where keypoints are located
std : :vector <std : :vector <cv : :KeyPoint > > & keypoints, //I/O vec of keypnts
cv : :OutputArrayOfArrays descriptors ); // computed descriptors,
// vector of (Mi x N) matrices, where
// Mi is the number of keypoints in
// the i-th image and N is the
// descriptor size
virtual void detectAndCompute(
cv : :InputArray image, // Image on which to detect
cv : :InputArray mask, // Optional region of interest mask
std : :vector <cv : :KeyPoint > & keypoints, // found or provided keypoints
cv : :OutputArray descriptors, // computed descriptors
bool useProvidedKeypoints = false ); // if true,
// the provided keypoints are used,
// otherwise they are detected

virtual int descriptorSize() const; // size of each descriptor in elements
virtual int descriptorType() const; // type of descriptor elements
virtual int defaultNorm() const; // the recommended norm to be used
// for comparing descriptors.
// Usually, it's NORM_HAMMING for
// binary descriptors and NORM_L2
// for all others.

virtual void read( const cv : :FileNode & );
virtual void write( cv : :FileStorage & ) const;

...
};​

    复杂的定义,注意Feature2D派生自alogorithm算法类。

a、如果它是一个单纯的关键点检测算法(如FAST),实际的实现可能只是执行cv :: Feature2D :: detect(),; 

b、如果它是一个纯特征描述算法(如FREAK),实际的实现可能只是cv :: Feature2D :: compute();

c、在要求“完全解决”的算法的情况下,如SIFT,SURF,ORB,BRISK等,实际的实现就会是cv :: Feature2D :: detectAndCompute(),在这种情况下,detect()和compute()会被隐式地调用。

    对于具体每一种算法,查找关键点的实际方法当然对于cv :: Feature2D的许多可用派生类中的每一个都是不同的。

    值得注意的是,根据算法何时实现,许多关键点特征检测器和提取器都设计在一起成为一个对象。在这种情况下,方法cv::Feature2D::detectAndCompute() 被实现。每当某个算法提供了detectAndCompute()时,强烈建议直接使用它,而不是在后续调用detect(),然后再使用compute()。原因很明显,就是性能更好。


3、cv :: DMatch

寻找到的特征结果需要进行匹配,以方便下一步的计算。


​​class cv : :DMatch {

public :

DMatch(); // sets this->distance
// to std::numeric_limits<float>::max()

DMatch( int _queryIdx, int _trainIdx, float _distance );
DMatch( int _queryIdx, int _trainIdx, int _imgIdx, float _distance );

int queryIdx; // query descriptor index
int trainIdx; // train descriptor index
int imgIdx; // train image index
float distance;

bool operator <( const DMatch &m ) const; // Comparison operator
// based on 'distance'

}​​

    cv :: DMatch的数据成员是queryIdx,trainIdx,imgIdx和distance。前两个辨别与每个图像中的关键点列表匹配的关键点。 imgIdx用于辨别在图像和字典之间寻求匹配的情况下训练图像来自的特定图像。最后一个成员,distance,用来表示匹配的质量。


4、cv :: DescriptorMatcher(关键点匹配类)

    一般有两种不同的情况:对于目标识别的情况,我们需要首先用描述符的字典训练匹配器,然后才能向匹配器呈现单个描述符列表,并告诉我们匹配器存储的哪个(如果有的话)关键点是与我们提供的列表中的那些相匹配;对于跟踪的情形,我们需要提供两个描述符列表,然后匹配器告诉我们它们之间的匹配位置。 

    cv:DescriptorMatcher类接口提供了三个函数match(),knnMatch()和 radiusMatch();对于每个函数,有两个不同的变形 - 一个用于识别(需要一个特征列表并使用经过训练的字典),另一个用于跟踪(需要两个特征列表)。

部分定义: class cv : : DescriptorMatcher {

public :

virtual void add( InputArrayOfArrays descriptors ); // Add train descriptors
virtual void clear(); // Clear train descriptors
virtual bool empty() const; // true if no descriptors
void train(); // Train matcher
virtual bool isMaskSupported() const = 0; // true if supports masks
const vector <cv : :Mat > & getTrainDescriptors() const; // Get train descriptors

// methods to match descriptors from one list vs. "trained" set (recognition)
//
void match(
InputArray queryDescriptors,
vector <cv : :DMatch > & matches,
InputArrayOfArrays masks = noArray ()
);
void knnMatch(
InputArray queryDescriptors,
vector < vector <cv : :DMatch > > & matches,
int k,
InputArrayOfArrays masks = noArray (),
bool compactResult = false
);
void radiusMatch(
InputArray queryDescriptors,
vector < vector <cv : :DMatch > > & matches,
float maxDistance,
InputArrayOfArrays masks = noArray (),
bool compactResult = false
);

// methods to match descriptors from two lists (tracking)
//
// Find one best match for each query descriptor
void match(
InputArray queryDescriptors,
InputArray trainDescriptors,
vector <cv : :DMatch > & matches,
InputArray mask = noArray ()
) const;
// Find k best matches for each query descriptor (in increasing
// order of distances)
void knnMatch(
InputArray queryDescriptors,
InputArray trainDescriptors,
vector < vector <cv : :DMatch > > & matches,
int k,
InputArray mask = noArray(),
bool compactResult = false
) const;
// Find best matches for each query descriptor with distance less
// than maxDistance
void radiusMatch(
InputArray queryDescriptors,
InputArray trainDescriptors,
vector < vector <cv : :DMatch > > & matches,
float maxDistance,
InputArray mask = noArray (),
bool compactResult = false
) const;

virtual void read( const FileNode & ); // Reads matcher from a file node
virtual void write( FileStorage & ) const; // Writes matcher to a file storage

virtual cv : :Ptr <cv : :DescriptorMatcher > clone(
bool emptyTrainData = false
) const = 0;
static cv : :Ptr <cv : :DescriptorMatcher > create(
const string & descriptorMatcherType
);
...
};

​​

    简单比较,match()方法需要通常的cv :: Mat格式的单个关键点描述符列表queryDescriptors。在这种情况下,请记住每行代表单个描述符,每列是该描述符向量表示的一个维度。 

    knnMatch() 函数,它需要与match() 相同的列表描述符。然而,在这种情况下,对于查询列表中的每个描述符,它将从字典中找到特定数量的最佳匹配。

    第三种匹配方法是radiusMatch()。 与搜索k个最佳匹配的k-最近邻匹配不同,半径匹配返回了查询描述符特定距离内的所有匹配。


5、序列化

read()和write()方法分别对应cv :: FileNode和cv :: FileStorage格式的对象,并允许你从磁盘读取和写入匹配器;

clone() 和create() 方法允许你分别创建一个描述符的副本或者通过名称创建一个新的描述符;

感谢阅读至此,希望有所帮助。

标签:const,函数,int,InputArray,void,寻找,vector,数据结构,cv
From: https://blog.51cto.com/jsxyhelu2017/5968397

相关文章

  • 内联函数和重载函数
    内联函数我们知道函数调用是有时间开销的,当函数本身只有几条语句,而函数本身却被反复执行很多次时,函数调用的开销就会显得比较大,为了减小这种函数调用的开销,就引入了内联......
  • C++11:支持函数模板的默认模板参数
    在C++98/03标准中,类模板可以有默认的模板参数,如下:template<typenameT,typenameU=int,UN=0>structFoo{//...};但是却不支持函数的默认模板参数:te......
  • ECMAScript 6 入门教程—Set 和 Map 数据结构
    作者|阮一峰1、Set基本用法ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。Set本身是一个构造函数,用来生成Set数据结构。consts=new......
  • C++类模板、函数模板
    类模板的声明需要template<typename类型参数>,等于C#中的泛型类,如List<T>。template<typenameT>classComplex{public://构造函数Complex(Ta,Tb)......
  • 函数
    函数函数的作用什么是函数用来完成一定的功能。函数名即给对应功能起一个名字为什么要使用函数?事先编好一批常用的函数来实现各种不同的功能,把它们保存在函数库中。需......
  • redis设计与实现(一) redis概念和数据结构
    基础概念     定义       Redis(RemoteDictionaryServer)是一个使用C语言编写的,高性能非关系型的键值对数据库。     特点 基于......
  • Redis数据结构与对象
    参考《Redis设计与实现》系列文章目录和关于我一丶简单动态字符串当redis需要的不仅仅是一个字符串字面量,而是一个可以被修改的字符串值时,就会使用SDS(simpledynamics......
  • Python中使用zip函数的七重境界
    1.引言Python中有一些内置函数,可以使我们的代码非常优雅。​​zip​​函数就是其中之一,但是zip函数的使用对于初学者来说不是很直观,有时容易出错。因此本文将从7个层次来......
  • 【模式识别】判别函数和感知机算法
    给定两个类别的一共8个样本,通过感知机算法求解判别函数defbi_perception():X1=np.array([[0,0,0],[1,0,0],[1,0,1],......
  • csharp通过dll调用opencv函数,图片作为参数
    [blog项目实战派]csharp通过dll调用opencv函数,图片作为参数     一直想做着方面的研究,但是因为这个方面的知识过于小众,也是由于自己找资料的能力......