zoukankan      html  css  js  c++  java
  • 特征点寻找的基础数据结构和函数

        当进行跟踪时或者其他类型的用到关键点及其描述符的分析时,通常需要做三件事情:第一个是根据一些关键点的定义搜索图像并查找该图像中的所有关键点;第二个是为发现的每个关键字创建一个描述符;第三个是通过将所找到的关键点的描述符与一些现有的描述符集进行比较,看看是否可以找到匹配项。
        在跟踪应用程序中,最后一步涉及查找序列的一帧图像中的特征,并尝试将其与前一帧中的特征进行匹配。在目标检测应用程序中,人们通常会在一些(潜在的广泛)数据库中搜索“已知”特征的“已知”与各个目标或目标类相关联的特征。
        对于这些层中的每一个,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() 方法允许你分别创建一个描述符的副本或者通过名称创建一个新的描述符;
    感谢阅读至此,希望有所帮助。




  • 相关阅读:
    UNDO表空间的ORA1122错误解决(二)转
    Oracle 碎片整理
    如何解决Ora00600 4194错误转自eygle
    Oracle维护常用sql语句
    ORA01152: file 1 was not restored from a sufficiently old backup
    oracle的一些信息抽取脚本.sql
    Flash Recovery Area空间不足导致数据库不能打开
    HP—UNIX的信息收集脚本
    详细解读 STATSPACK 报告
    OLTP和OLAP
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/7525952.html
Copyright © 2011-2022 走看看