精华内容
下载资源
问答
  • VSLAM C++代码编写中的问题报错与解决方案
    2020-04-18 16:28:20

    0. 前言:

    • 在VSLAM代码的编写实践中,遇到不少基础问题,花费不少时间才找到问题解决方案,因此利用此博客记录代码编写过程中的问题报错与解决方案。

    1. C++相关

    (1)报错关键词:"undefined reference to"

    • 报错代码:
    /home/XXXXXX/VSLAMwys/app/run_wysSLAM.cpp:51: undefined reference to `wysSLAM::pose::pose_estimation_2d2d(std::vector<cv::KeyPoint, std::allocator<cv::KeyPoint> >, std::vector<cv::KeyPoint, std::allocator<cv::KeyPoint> >, std::vector<cv::DMatch, std::allocator<cv::DMatch> >, cv::Mat&, cv::Mat&)'
    
    • 现象说明:在IDE工具(kdeveloper)中点击该报错,指向的是调用该函数的位置,即main函数中,如下:
      wysSLAM::pose::pose_estimation_2d2d(keypoints1, keypoints1, matches, R, t);

    但是该语句并没有任何错误,函数使用作用域解析运算符进行了正确调用,网络上的解释多为库函数未链接成功,但对CmakeLists.txt部分检查后未发现错误。最后,有博客提到构造函数,因此在阅读C++ Primer Plus后发现,自己在定义的成员函数时未使用作用域解析运算符(::)来标识所属的类!  即:void pose_estimation_2d2d(){}

    解决方案:在类成员函数的.cpp实现文件中改为如下代码即可编译通过。

    void pose::pose_estimation_2d2d(){}

    (1+)报错关键词:"undefined reference to"其他原因

    • 报错代码:
    ......
    void NNCluster(vector<cv::Point3f> &Cluster0, vector<int> &ClusterList0, vector<vector<cv::Point3f>> &Cluster0_final, vector<vector<int>> &ClusterList0_final)
    
    int main {}
    
    void NNCluster(vector<cv::Point3f> Cluster0, vector<int> ClusterList0, vector<vector<cv::Point3f>> Cluster0_final, vector<vector<int>> ClusterList0_final) {}
    • 正确代码:在成员函数中加入 &,使得声明的部分与成员函数主题的定义一致
    ......
    void NNCluster(vector<cv::Point3f> &Cluster0, vector<int> &ClusterList0, vector<vector<cv::Point3f>> &Cluster0_final, vector<vector<int>> &ClusterList0_final)
    
    int main {}
    
    void NNCluster(vector<cv::Point3f> &Cluster0, vector<int> &ClusterList0, vector<vector<cv::Point3f>> &Cluster0_final, vector<vector<int>> &ClusterList0_final) {}

     

     

     

    • 报错代码:
    /home/XXXXXX/VSLAMwys/app/run_wysSLAM.cpp:75:76: error: cannot call member function ‘void wysSLAM::tri::triangulation(const std::vector<cv::KeyPoint>&, const std::vector<cv::KeyPoint>&, const std::vector<cv::DMatch>&, const cv::Mat&, const cv::Mat&, std::vector<cv::Point3_<double> >&)’ without object
    
    • 现象说明:没有把成员函数声明为static函数,否则需要通过对象来调用该函数。不明确根本原因,但是相比将函数在头文件中声明为static,通过创建对象来调用函数看起来更合理,目的更明确:即通过该类创建一个对象,使用该对象中的运算。但如果只是函数,两种方法似乎类似,都是调用一种算法,但是如果是带有不同内置参数的对象,后一种方法就更合适。
    • 解决方案a:把成员函数声明为static函数
    static void triangulation(……)
    • 解决方案b:通过对象来调用该函数
    wysSLAM::tri asd;
    asd.wysSLAM::tri::triangulation (keypoints1, keypoints2, matches, R, t, points);

    (3)报错关键词:error: expected primary-expression before ‘matches’

    • 这个比较好解决,对应关键词matches前面的表达有错误,我这里是在构造函数时,在输入的数据成员matches前加了数据类型的定义,而这个matches在之前的语句中已经定义过了。

    (4)vector<int> a; cout<<a<<endl; cout报错,而vector<cv::Point3f> b; cout<<b<<endl;正确

    2. cmake相关

    3. OpenCV相关

    (1) 报错关键词:error: ‘type’ is not a member of ‘cv::DataType<unsigned int>’

    • 这个比较好解决,检查所使用的构造函数,输入该构造函数的数据成员的数据类型是否不对应。

    (2)  #include<opencv2/xfeatures2d.hpp>无效

    • 需要配套安装与opencv版本对应的opencv_contrib
    • 查看opencv版本命令:pkg-config --modversion opencv

    (3)无法解码多工传送的流

    • StereoVO.open("StereoVO_WYS.avi", CV_FOURCC('X', 'V', 'I', 'D') ,10, cv::Size(width,height)); 
      // 原因:输入的是黑白图像,但是却没有声明使用的是黑白,而默认的为彩色
      // 教训:调用时补全,不做缺省
      StereoVO.open("StereoVO_WYS.avi", CV_FOURCC('X', 'V', 'I', 'D') ,10, cv::Size(width,height), 0); 

       

    4. ROS相关

    持续更新……

    更多相关内容
  • corners:包含大量本地信息的像素块,并能够在另一张图中被快速识别 keypoints:作为 corners 的扩展,它将像素块的信息进行编码从而使得更易辨识,至少在原则... vector< cv::KeyPoint >& keypoints // in/out ...

    corners:包含大量本地信息的像素块,并能够在另一张图中被快速识别

    keypoints:作为 corners 的扩展,它将像素块的信息进行编码从而使得更易辨识,至少在原则上唯一

    descriptors:它是对 keypoints 进一步处理的结果。通常它具有更低的维度,从而使得图像块能够在另一幅不同的图像中被更快地识别

    KeyPoints对象

    为了描述关键点,Opencv 关键点的类定义如下:

    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
    	);
    	...
    };
    

    参数说明:

    1. pt:关键点的位置
    2. size:关键点的范围
    3. angle:关键点角度
    4. response:能够给某个关键点更强烈响应的检测器,有时能够被理解为特性实际存在的概率
    5. octave:标示了关键点被找到的层级,总是希望在相同的层级找到对应的关键点
    6. class_id:标示关键点来自于哪一个目标

     为了查找并计算描述符,Opencv 定义了如下抽象类。

    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;
    	...
    };
    

    函数说明:

    1. detect:用于计算 Keypoint
    2. compute:用于计算 descriptor
    3.  detectAndCompute:不同的关键点检测算法对于同一幅图像常常得到不同的结果,而且在算法计算过程中需要一种特殊的图像表示,其计算量很大,如果分开进行此步骤将重复进行两次,因此如果需要得到描述符,通常建议直接使detectAndCompute 函数
    4. descriptorSize:返回描述符向量的长度
    5. descriptorType:描述符元素的类型
    6. defaultNorm:描述符的归一化方法,指定了如何比较两个描述符,比如对于01描述符,可以使用 NORM_HAMMING;而对于 SIFT 和 SURF,则可以使用 NORM_L2 或者 NORM_L1。

    一个实际的实现可以只实现其中的某个或几个方法:

    cv::Feature2D::detect():FAST(只寻找FAST关键点,因为FAST只能寻找关键点)
    cv::Feature2D::compute():FREAK(对已知的关键点计算FREAK描述符,FREAK只能用于描述符)
    cv::Feature2D::detectAndCompute():SIFT,SURF,ORB,BRISK。(4种方法既能够寻找关键点也可以生成对应的描述符)算法中将隐式调用检测和计算方法

    cv::DMatch 对象的类定义

    通常,一个匹配器尝试在一副或一组图中匹配一幅图中的关键点,如果匹配成功,将返回 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'
    }
    

    成员说明:

    1. queryIdx, trainIdx:指定了每幅图像中关键点与关键点列表中元素的匹配情况。其中,默认 query image 为新图片,而 training image 为旧图片
    2. imgIdx:指定要匹配哪一个训练图像
    3. distance:给出了匹配程度
    4. operator<():给定基于 distance 的比较方式

    cv::DescriptorMatcher 抽象类

        通常匹配器被应用在目标识别和跟踪两个场景中。其中目标识别需要我们训练匹配器——给出已知物体最大区分度的描述符,然后根据我们给出的描述符给出字典中哪个描述符与之相匹配。而跟踪则要求在给定两组描述符的条件下,给出它们之间的匹配情况。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
    	);
    	...
    };
    

    函数说明:

    1. add:添加描述符,其中每个元素都是一个 Mat,每一行是一个描述符,列数是描述符的维数
    2. getTrainDescriptors:获得已添加的描述符
    3. clear,empty:清空和判断匹配器是否添加了描述符
    4. train:当加载完所有描述符时,通常需要运行 train 函数。它将基于使用的匹配方法生成指定数据结构,以便将来更高效地加速匹配过程。通常如果提供了 train 方法,必须在调用匹配方法之前调用 train 方法。
    5. match(), knnMatch(), and radiusMatch():用于目标识别的函数,其中 match() 方法只返回最优匹配,即查询列表上的每个关键点将于列表中的“最佳匹配”匹配;而 knnMatch() 将返回前 k 个最优匹配,返回值是vector< vector<cv::DMatch> >& matches,这里的matches[i][j]表示trainDescriptors中描述符的第j个最佳匹配(i表示查询列表中的描述符个数,j表示在字典中找到的匹配描述符个数,一共有k个,即matches[i]是由k个DMatch对象组成的vector,这里面的k个DMatch对象都是对应于queryDescriptors查询列表中的一个描述符)radiusMatch 则返回所有距离小于指定距离的匹配。
    6. read,write:存储和加载匹配器,特别对于大型数据库,不用再保存所有图片
    7. clone,create:其中 emptyTrainData 标示是否使用原始训练数据,而 create 可接受如下方法的字符串 

     第一组方法用于将图像与预先存储的描述集合进行匹配,目的是建立一个关键点字典1,2,3,4;

     第二组方法是在目标识别中使用的一组匹配方法,它们每个都使用描述符列表,成为查询列表,与训练好的字典中的描述符进行比较,有3种方法match(), knnMatch(), and radiusMatch();

     第三组方法,支持两个描述符列表,用于跟踪,这些方法忽略内部字典的任何描述符,而是将queryDescriptors列表中的描述符与trainDescriptors进行比较。

    关键点滤波器

    关键点滤波器用于从现有的关键点中查找更佳的关键点或者去除相同的关键点。

    class cv::KeyPointsFilter {
    public:
    	static void runByImageBorder(
    		vector< cv::KeyPoint >& keypoints, // in/out list of keypoints
    		cv::Size imageSize, // Size of original image
    		int borderSize // Size of border in pixels
    	);
    	static void runByKeypointSize(
    		vector< cv::KeyPoint >& keypoints, // in/out list of keypoints
    		float minSize, // Smallest keypoint to keep
    		float maxSize = FLT_MAX // Largest one to keep
    	);
    	static void runByPixelsMask(
    		vector< cv::KeyPoint >& keypoints, // in/out list of keypoints
    		const cv::Mat& mask // Keep where mask is nonzero
    	);
    	static void removeDuplicated(
    		vector< cv::KeyPoint >& keypoints // in/out list of keypoints
    	);
    	static void retainBest(
    		vector< cv::KeyPoint >& keypoints, // in/out list of keypoints
    		int npoints // Keep this many
    	);
    }
    

    函数说明:

    1. runByImageBorder():去除所有小于图像边缘大小的关键点,不过必须事先指定之前使用的 imageSize
    2. runByKeypointSize():去除所有小于 minSize 或者大于 maxSize 的关键点
    3. runByPixelsMask():去除所有 mask 中为零的关键点
    4. removeDuplicated():去除重复的关键点
    5. retainBest():去除关键点直到数量降为 npoints

    匹配方法

    Brute force matching with cv::BFMatcher

    暴力搜索就是直接根据询问集从训练集中查找,唯一需要指定的是距离度量方法(normType),可用选项如下表:

    class cv::BFMatcher : public cv::DescriptorMatcher {
    public:
    	BFMatcher(int normType, bool crossCheck = false);
    	virtual ~BFMatcher() {}
    	virtual bool isMaskSupported() const { return true; }
    	virtual Ptr<DescriptorMatcher> clone(
    		bool emptyTrainData = false
    	) const;
    	...
    };
    

    其中 crosscheck 如果置 1,那么必须两者分别为对方的最近邻。这能够有效的降低错误匹配,不过将花费更多的时间。 

    Fast approximate nearest neighbors and cv::FlannBasedMatcher

    快速近似最近邻,indexParams参数默认使用的索引方法是kdtree,tree的数目默认是4,

    class cv::FlannBasedMatcher : public cv::DescriptorMatcher {
    public:
    	FlannBasedMatcher(
    		const cv::Ptr< cv::flann::IndexParams>& indexParams
    		= new cv::flann::KDTreeIndexParams(),
    		const cv::Ptr< cv::flann::SearchParams>& searchParams
    		= new cv::flann::SearchParams()
    	);
    	virtual void add(const vector<Mat>& descriptors);
    	virtual void clear();
    	virtual void train();
    	virtual bool isMaskSupported() const;
    	virtual void read(const FileNode&); // Read from file node
    	virtual void write(FileStorage&) const; // Write to file storage
    	virtual cv::Ptr<DescriptorMatcher> clone(
    		bool emptyTrainData = false
    	) const;
    	...
    };
    

    参数说明:

    SearchParams:

    struct cv::flann::SearchParams : public cv::flann::IndexParams {
    	SearchParams(
    		int checks = 32, // Limit on NN candidates to check
    		float eps = 0, // (Not used right now)
    		bool sorted = true // Sort multiple returns if 'true'
    	);
    };
    

    IndexParams :

    1、Linear indexing with cv::flann::LinearIndexParams:其等效于 cv::BFMatcher

    // 等价于 cv::BFMatcher
    cv::FlannBasedMatcher matcher(
    	new cv::flann::LinearIndexParams(), // Default index parameters
    	new cv::flann::SearchParams() // Default search parameters
    );
    

    2、KD-tree indexing with cv::flann::KDTreeIndexParams:使用随机 kd-trees 进行匹配,其默认值为 4,如果通常设置为 16 

    cv::FlannBasedMatcher matcher(
    	new cv::flann::KDTreeIndexParams(16), // Index using 16 kd-trees
    	new cv::flann::SearchParams() // Default search parameters
    );
    

     3、Hierarchical k-means tree indexing with cv::flann::KMeansIndexParams:索引使用层级 k-means 分簇

    struct cv::flann::KMeansIndexParams : public cv::flann::IndexParams {
    	KMeansIndexParams(
    		int branching = 32, // Branching factor for tree
    		int iterations = 11, // Max for k-means stage
    		float cb_index = 0.2, // Probably don't mess with
    		cv::flann::flann_centers_init_t centers_init
    		= cv::flann::CENTERS_RANDOM
    	);
    };
    

     4、Combining KD-trees and k-means with cv::flann::CompositeIndexParams:混合使用 kd-trees 和 k-means 方法

    struct cv::flann::CompositeIndexParams : public cv::flann::IndexParams {
        CompositeIndexParams(
            int trees = 4, // Number of trees
            int branching = 32, // Branching factor for tree
            int iterations = 11, // Max for k-means stage
            float cb_index = 0.2, // Usually leave as-is
            cv::flann::flann_centers_init_t centers_init
            = cv::flann::CENTERS_RANDOM
        );
    };

    5、Locality-sensitive hash (LSH) indexing with cv::flann::LshIndexParams:使用 hash 函数将相似的目标放置到相同的桶中,其只能被用于处理二值特性,比如汉明距离

    struct cv::flann::LshIndexParams : public cv::flann::IndexParams {
        LshIndexParams(
            unsigned int table_number, // Number of hash tables to use, usually '10' to '30'
            unsigned int key_size, // key bits, usually '10' to '20'
            unsigned int multi_probe_level // Best to just set this to '2'
        );
    };

    6、Automatic index selection with cv::flann::AutotunedIndexParams:让算法自主选择一个合适的索引方法

    struct cv::flann::AutotunedIndexParams : public cv::flann::IndexParams {
        AutotunedIndexParams(
            float target_precision = 0.9, // Percentage of searches required
                                          // to return an exact result
            float build_weight = 0.01, // Priority for building fast
            float memory_weight = 0.0, // Priority for saving memory
            float sample_fraction = 0.1 // Fraction of training data to use
        );
    };

    显示结果

    Displaying keypoints with cv::drawKeypoints

    void cv::drawKeypoints(
    	const cv::Mat& image, // Image to draw keypoints
    	const vector< cv::KeyPoint >& keypoints, // List of keypoints to draw
    	cv::Mat& outImg, // image and keypoints drawn
    	const Scalar& color = cv::Scalar::all(-1), // Use different colors
    	int flags = cv::DrawMatchesFlags::DEFAULT
    );
    

    参数说明:

    1. color:cv::Scalar::all(-1) 自动使用不同的颜色
    2. flags:cv::DrawMatchesFlags::DEFAULT 使用小圆圈,cv::DrawMatchesFlags:: DRAW_RICH_KEYPOINTS 标记为 size 大小的圆圈,并标记 angle 的方向

    Displaying keypoint matches with cv::drawMatches

    void cv::drawMatches(
        const cv::Mat& img1, // "Left" image
        const vector< cv::KeyPoint >& keypoints1, // Keypoints (lt. img)
        const cv::Mat& img2, // "Right" image
        const vector< cv::KeyPoint >& keypoints2, // Keypoints (rt. img)
        const vector< cv::DMatch >& matches1to2, // List of matches
        cv::Mat& outImg, // Result images
        const cv::Scalar& matchColor = cv::Scalar::all(-1),
        const cv::Scalar& singlePointColor = cv::Scalar::all(-1),
        const vector<char>& matchesMask = vector<char>(),
        int flags
        = cv::DrawMatchesFlags::DEFAULT
    )
    void cv::drawMatches(
        const cv::Mat& img1, // "Left" image
        const vector< cv::KeyPoint >& keypoints1, // Keypoints (lt. img)
        const cv::Mat& img2, // "Right" image
        const vector< cv::KeyPoint >& keypoints2, // Keypoints (rt. img)
        const vector< vector<cv::DMatch> >& matches1to2, // List of lists
                                                         // of matches
        cv::Mat& outImg, // Result images
        const cv::Scalar& matchColor // and connecting line
        = cv::Scalar::all(-1),
        const cv::Scalar& singlePointColor // unmatched ones
        = cv::Scalar::all(-1),
        const vector< vector<char> >& matchesMask // only draw for nonzero
        = vector< vector<char> >(),
        int flags = cv::DrawMatchesFlags::DEFAULT
    );


    参数说明:

    1. img1,img2,keypoints1,keypoints2:给出了两张图片和分别的关键点
    2. matches1to2:表示了关键点的匹配关系,其中 keypoints1[i] 与 keypoints2[matches[i]] 相匹配
    3. outImg:匹配结果
    4. matchcolor:匹配的关键点将用线连接,同时标记上此颜色
    5. singlePointColor:没有匹配的关键点将使用此颜色
    6. matcherMask:匹配上的关键点位置将被置一
    7. flags:cv::DrawMatchesFlags::DEFAULT(输出结果在 outImg 中,同时用小圆圈标记);cv::DrawMatchesFlags::DRAW_OVER_OUTIMG(并不重新分配 outImg 的空间,这样可以多次调用 cv::drawMatches(),将结果绘制在一张图上);cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS(并不绘制未匹配上的关键点);cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS(将关键点用带尺度和方向的圆标示)

    from:Opencv 关键点和描述符(二)—— 通用关键点和描述符

    实例:

    #include <opencv2\opencv.hpp>
    #include<opencv2\nonfree\nonfree.hpp>//SIFT
    #include<opencv2\legacy\legacy.hpp>//BFMatch暴力匹配
    #include <vector>
    #include<iostream>
    using namespace std;
    using namespace cv;
    
    void main()
    {
    	Mat srcImg1 = imread("111.jpg");
    	Mat srcImg2 = imread("111temp.jpg");
    	//定义SIFT特征检测类对象
    	SiftFeatureDetector siftDetector;
    	//定义KeyPoint变量
    	vector<KeyPoint>keyPoints1;
    	vector<KeyPoint>keyPoints2;
    	//特征点检测
    	siftDetector.detect(srcImg1, keyPoints1);
    	siftDetector.detect(srcImg2, keyPoints2);
    	//绘制特征点(关键点)
    	Mat feature_pic1, feature_pic2;
    	drawKeypoints(srcImg1, keyPoints1, feature_pic1, Scalar::all(-1));
    	drawKeypoints(srcImg2, keyPoints2, feature_pic2, Scalar::all(-1));
    	//显示原图
    	//imshow("src1", srcImg1);
    	//imshow("src2", srcImg2);
    	//显示结果
    	imshow("feature1", feature_pic1);
    	imshow("feature2", feature_pic2);
    
    	//计算特征点描述符 / 特征向量提取
    	SiftDescriptorExtractor descriptor;
    	Mat description1;
    	descriptor.compute(srcImg1, keyPoints1, description1);
    	Mat description2;
    	descriptor.compute(srcImg2, keyPoints2, description2);
    	cout << description1.cols << endl;
    	cout << description1.rows << endl;
    
    	//进行BFMatch暴力匹配
    	BruteForceMatcher<L2<float>>matcher;    //实例化暴力匹配器
    	vector<DMatch>matches;   //定义匹配结果变量
    	matcher.match(description1, description2, matches);  //实现描述符之间的匹配
    
    														 //匹配结果筛选
    	nth_element(matches.begin(), matches.begin() + 29, matches.end());   //提取出前30个最佳匹配结果     
    	matches.erase(matches.begin() + 30, matches.end());    //剔除掉其余的匹配结果
    
    	Mat result;
    	drawMatches(srcImg1, keyPoints1, srcImg2, keyPoints2, matches, result, Scalar(0, 255, 0), Scalar::all(-1));//匹配特征点绿色,单一特征点颜色随机
    	imshow("Match_Result", result);
    
    	waitKey(0);
    }

    结果:

    展开全文
  • OpenCV中KeyPoint

    千次阅读 2019-08-12 15:03:08
    Opencv中KeyPoint类中的默认构造函数如下: CV_WRAP KeyPoint() : pt(0,0), size(0), angle(-1), response(0), octave(0), class_id(-1) {} 现分析各项属性 pt(x,y):关键...

    https://blog.csdn.net/u010821666/article/details/52883580

    Opencv中KeyPoint类中的默认构造函数如下: 

    CV_WRAP KeyPoint() : pt(0,0), size(0), angle(-1), response(0), octave(0), class_id(-1) {}
    现分析各项属性

    pt(x,y):关键点的点坐标;

    size():该关键点邻域直径大小;

    angle:角度,表示关键点的方向,值为[零,三百六十),负值表示不使用。

    response:响应强度,网络上有如下解释:

    1)”The response, by which the strongest keypoints have been selected.”

    2)”Responseis indeed an indicator of “how good” (roughly speaking, in terms of corner-ness) a point is. The higher, the better. The strongest keypoints means the ones that are the best.“

    octacv:从哪一层金字塔得到的此关键点。

    class_id:当要对图片进行分类时,用class_id对每个关键点进行区分,默认为-1。
    https://blog.csdn.net/linsk/article/details/76838878

    你可以看到,每个关键点都有一个cv :: Point2f成员,这只是告诉我们它位于哪里。size告诉我们关于关键点周围的区域,无论是在某种程度上都包含关键点存在的确定,或者在这个关键点的描述符中扮演一个角色。Angle仅对某些关键点有意义,许多关键点实现旋转对称,而不是在最严格的意义上实际上是不变的,而是通过在比较两个描述符时可以考虑某种自然方向(这不是一个复杂的想法,如果你正在看铅笔的两个图像,旋转显然很重要,但是如果你想比较它们,你可以在进行比较之前以相同的方向轻松地将它们形象化)。

    response可以用于更强烈地响应一个关键点的探测器。在某些情况下,这可以被解释为该特征实际存在的概率。Octave被用来当在图像金字塔中找到关键点时,在这些情况下,重要的是知道哪个标尺是关键点,因为在大多数情况下,我们希望在新图像中以相同或相似的比例找到匹配。最后,关于类ID,在构造关键点数据库时,使用class_id来区分与一个对象相关联的关键点和与另一个对象相关联的关键点(当我们在“摘要”关键点匹配类别中讨论关键点匹配接口时,我们将返回到这一点: cv :: DescriptorMatcher)。

    cv :: KeyPoint对象有两个构造函数,它们基本相同;其唯一的区别是您可以设置关键点的位置与两个浮点数或单个cv :: Point2f对象。 其实呢,除非你正在编写自己的关键点查找器,你不会倾向于使用这些功能。如果您正在使用库中可用的检测,描述符构造和比较功能,通常您甚至不会看到关键点对象。

     

    展开全文
  • Vector与KeyPoint

    2016-06-13 21:50:00
    CV_EXPORTS_W void drawKeypoints( const Mat& image, const vector<KeyPoint>& keypoints, CV_OUT Mat& outImage, const Scalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT ); // Draws ...

     from:  http://www.cnblogs.com/my-idiot-days/archive/2013/05/01/3053831.html

        近来,博主烦恼于问题丛生的特征点提取与匹配算法。更苦于X疼的各种无休止的各种类型数据的存存取取。博主还是个菜鸟,因此此前一直用的是傻气的一维数组存取,不管是什么图像的灰度值啊,还是计算出来的每个点的XX值,都用一维数组。结果就是,超麻烦,存取不易且每次都需要求取数组长度!

        今天,博主发现了C++中的vector,真是好用啊!C++有这么个容器博主居然一直不知道。

        参考:http://www.cplusplus.com/reference/vector/vector/

           代码实例:

        1.首先包含头文件

    #include<vector>

            2.测试代码

    int  i,j;
    std::vector <cv::Point> VectorPoints;
    for (i=0;i<5;i++)
         for (j=0;j<5;j++)
         {
             cv::Point myPoint = Point(i,j);
             VectorPoints.push_back(myPoint);
         }
     
         for (i=0;i<VectorPoints.size();i++)
             cout<<VectorPoints.at(i)<<endl;

    说明:首先定义一个Point(即Point2i---二维整型的点)类型的变量VectorPoints,这就是我们创建的用来存储Point类型的点的容器啦。<cv::Point>表示容器中所装的数据的类型,double啊,int啊,各种都可以。之后,博主用二重循环给我们的容器装数据:定义一个我们要装的数据的类型的变量(这里叫myPoint),给这个变量赋值,然后调用vector变量的push_back函数(参数即为该类型数据)。我们就把这些数据装入容器了。

    我们可以用cout输出数据来看看。用at我们可以轻易地访问容器中的第i个元素(数据)。VectorPoints.at(i)有两个变量x,y即为我们刚才复制的i,j。VectorPoints.at(i).x和VectorPoints.at(i).y直接可以得到某个Point类型数据的x、y元素。

        为了绘制特征点并将两幅匹配了的图像的对应点连起来,博主又呕心沥血,才知道原来OpenCV有现成的函数。不过,只在网上搜到了sift、surf算子中使用的,没有找到明白的单独讨论的文字。不管有是没有,博主还是简单写一写吧。

    代码是最好的讲解,先上代码:

    vector<KeyPoint> keypoint_test;
    KeyPoint mykeypoint=KeyPoint(3,3,3,-1,0,0,-1);
    keypoint_test.push_back(mykeypoint);
    mykeypoint=KeyPoint(7,7,3,-1,0,0,-1);
    keypoint_test.push_back(mykeypoint);
    mykeypoint=KeyPoint(11,11,3,-1,0,0,-1);
    keypoint_test.push_back(mykeypoint);
    Mat mat_test=imread( "D:\\test.jpg" );
    Mat mat_show;
    drawKeypoints(mat_test,keypoint_test,mat_show,Scalar::all(-1),0);
    imshow( "show" ,mat_show);

     说明:在OpenCV的绘制特征点和匹配点绘制及连线中,都反复地使用了KeyPoint这种数据类型,因此首先定义一个数据类型为KeyPoint的vector容器,名之keypoint_test。接着,我们给容器装数据:KeyPoint比之Pont多了些参数,头两个参数分别是float型,第三个是绘制点的大小,再后就都是用的默认参数,博主还没有深究,是对着下边的features2d.hpp中的东西对着打的(后四个参数:-1,0 ,0,-1)。之后,如法炮制地调用函数push_back,我们就得到了装载了数据的vector容器keypoint_test。接下来的绘制就简单了。Mat型变量读取图像,再定义一个Mat性变量mat_show用于绘制。最后调用drawKeypoints,参数分别是:原始图像,待绘制的数据keypoint_test,绘制所用的图像,任意颜色,ID号(同一幅图像相同)。这样简单几步就大功告成啦。

    参考:

    复制代码
        //! the default constructor
        CV_WRAP KeyPoint() : pt(0,0), size(0), angle(-1), response(0), octave(0), class_id(-1) {}
        //! the full constructor
        KeyPoint(Point2f _pt, float _size, float _angle=-1,
                float _response=0, int _octave=0, int _class_id=-1)
                : pt(_pt), size(_size), angle(_angle),
                response(_response), octave(_octave), class_id(_class_id) {}
        //! another form of the full constructor
        CV_WRAP KeyPoint(float x, float y, float _size, float _angle=-1,
                float _response=0, int _octave=0, int _class_id=-1)
                : pt(x, y), size(_size), angle(_angle),
                response(_response), octave(_octave), class_id(_class_id) {}
    复制代码

     

    复制代码
    // Draw keypoints.
    CV_EXPORTS_W void drawKeypoints( const Mat& image, const vector<KeyPoint>& keypoints, CV_OUT Mat& outImage,
                                     const Scalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT );
    
    // Draws matches of keypints from two images on output image.
    CV_EXPORTS void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
                                 const Mat& img2, const vector<KeyPoint>& keypoints2,
                                 const vector<DMatch>& matches1to2, Mat& outImg,
                                 const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1),
                                 const vector<char>& matchesMask=vector<char>(), int flags=DrawMatchesFlags::DEFAULT );
    复制代码

     

    转载于:https://www.cnblogs.com/zengcv/p/5582196.html

    展开全文
  • cv2.KeyPointcv2.DMatch

    千次阅读 2022-01-13 16:43:24
    cv2.Keypoint Attribute Comments .pt 点的坐标 .size 点邻域大小 .angle 特征点方向 .response .octave 特征点所在的金字塔组 .class_id 类型 cv2.DMatch Attribute Comments ....
  • OpenCV中的KeyPoint

    2018-07-25 10:32:49
    CV_WRAP KeyPoint() : pt(0,0), size(0), angle(-1), response(0), octave(0), class_id(-1) {} 现分析各项属性 pt(x,y):关键点的点坐标;point2f类型; size():该关键点邻域直径大小; angle:角度,表示关键点...
  •  DRAW_OVER_OUTIMG:函数不创建输出的图像,而是直接在输出图像变量空间绘制,要求本身输出图像变量就是一个初始化好了的,size与type都是已经初始化好的变量  NOT_DRAW_SINGLE 单点的特征点不被绘制  DRAW_RICH_...
  • C++语法:vector的使用

    2020-07-13 17:27:37
    【1】vector的创建与元素插入【2】vector元素的访问【3】vector的基本使用技巧【4】vector的几个重要操作 【1】vector的创建与元素插入 std::vector<cv::Point> points; //vector容器中保存的类型是Point for ...
  • 配准常见的评判标准就是关键点坐标之间的误差(TRE),关键点的标注就成了绕不开的过程。有很多图像处理软件都可以实现在图像上画点并且显示鼠标处的坐标,如windows自带的绘图软件,ImageJ等,但是我当下的任务需求...
  • 文章目录图像直方图代码实现cv::FAST和cv::ORB 检测图像特征点cv::FAST和cv::ORB 检测图像特征点代码实现ORB_SLAM2::ORB和自己实现ORB图像特征点检测效果对比ORB_SLAM2::ORB和自己实现ORB图像特征点检测效果对比代码...
  • 保存特征点各种信息的KeyPoint类在使用中是不透明的,我们来看看KeyPoint类的主要属性: 主要包含的特征点信息有:位置、邻域直径、特征的方向、响应强度、多尺度信息和分类等。特征点匹配的实现就是通过逐个匹配...
  • ++i) { if (status[i]) { cv::KeyPoint kp(kps_current[i], 7); Feature::Ptr feature(new Feature(current_frame_, kp)); feature->map_point_ = last_frame_->features_left_[i]->map_point_; current_frame_->...
  • 计算机视觉理论中的特征描述是常见的目标分析技术之一,关键点检测与关键点提取是目标特征分析的重要步骤。局部图像特征描述的核心基础问题是不变性和可分性分析,不变性是基于特征描述对视角变化的不变性、尺度变化...
  • Opencv中SIFT特征检测代码详细解释

    千次阅读 2019-05-26 20:40:56
    Opencv中SIFT特征检测代码详细解释 #include <opencv2/opencv.hpp> #include <opencv2/xfeatures2d.hpp>...using namespace cv; using namespace std; using namespace cv::xfeatures2d; ...
  • // -- 创建vector数组存储特征点 vector<cv::KeyPoint> keypoints1,keypoints2; detector->detect(img1,keypoints1); detector->detect(img2,keypoints2); //opencv版本问题如下: //-----------------------------...
  • 今天调程序发现一个问题,代码... cv::Mat Pw = cv::Mat::zeros(3,1,CV_32FC1);//世界坐标 Pw.at(0,0) = 0.0; Pw.at(1,0) = 0.0; Pw.at(2,0) = 0.0; PointCloud.push_back(Pw);//将世界原点添加到点云中 Pw.at
  • 计算机视觉纳米学位 这个存储库包含我在的练习和项目。 由 Saurav Raghuvanshi 创建 该存储库包含我在 Udacity 计算机视觉纳米学位计划中的所有练习和项目 项目一:人脸关键点检测 在这个项目中,我构建了一个面部...
  • // 如果单目初始器还没有被创建,则创建单目初始器 if(!mpInitializer) { // Set Reference Frame // 单目初始帧的特征点数必须大于100 if(mCurrentFrame.mvKeys.size()>100) { // 步骤1:得到用于初始化的...
  • 这篇博客主要记录了我在深蓝学院视觉slam课程中的课后习题,因为是为了统计知识点来方便自己以后查阅,所以有部分知识可能不太严谨,如果给大家造成了困扰请见谅,大家发现了问题也可以私信或者评论给我及时改正,...
  • surf算法为每个检测到的特征定义了位置和尺度,尺度值可以用于定义围绕特征点的窗口大小,不论物体的尺度在窗口是怎么样的,都将包含相同的视觉信息,这些信息用于表示特征点以使得它们与众不同。 SURF 算法,全称...
  • 就不细说了 void ORBextractor::ProcessDesp(cv::InputArray _image, cv::InputArray _mask, vector<vector<cv::KeyPoint>>& _allKeypoints, vector<cv::KeyPoint>& _mKeypoints,cv::OutputArray _descriptors) { cv...
  • 计算机视觉中的金字塔思想及实现前言一、案例:多层光流法追踪点1. 构建图像金字塔2. 初始化一个最粗的特征3. 由粗到精的调用这个函数二、案例:多层光流法直接估计位姿总结 前言 金字塔是一种常见的计算机视觉处理...
  • 第一节 特征检测与描述 OpenCV提供了丰富的特征检测算法,比如SIFT(Scale Invariant Feature Transform)、AffineFeature、AgastFeatureDetector、AKAZE...SIFT类继承了cv::Feature2D类,通过create静态方法创建。 stati
  • def draw_features(img, features): """Draw features""" # Convert to OpenCV KeyPoints cv_kps = [] for f in features: cv_kps.append(cv2.KeyPoint(f.pt[0], f.pt[1], f.size)) # ...
  • 这里写自定义目录标题COCO数据集Keypoint标注格式COCO数据集官网Keypoint Detection关键点检测 COCO数据集Keypoint标注格式 COCO数据集官网 COCO全程是Common Object in COntext,是CV里很常用的一个数据集。 COCO...
  • 用来记录该帧存在该特征点,std::weak_ptr frame_ 该特征点的像素位置 ,2d类型,用cv中的关键点类记录 cv::KeyPoint position_ 一个地图点类型的弱指针,用来表达该2d特征点对应的三维地图点weak_ptr map_point_ ...
  • cv::Ptr<cv::算子> 给算子起的名字 = cv::算子::create(阈值); e.g. cv::Ptr<cv::ORB> orb = cv::ORB::create(nkeypoint); 检测 上一步给算子起的名字-> detect(图片, 内容为KeyPoints的vector向量);...
  • 我认为这个模型最大的弊端,是它需要割裂地训练3个子网: 首先训练keypoint子网 固定backbone参数,训练detection子网 用上述两个子网来生成数据,训练PRN子网 这样的训练不仅速度慢,还割裂了几个网络间的信息传递...
  • #include #include #include #include #include #include using namespace cv; using namespace std; /*************************************************** * 本节演示了如何根据data/目录下的十张图训练字典 * **...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,853
精华内容 741
关键字:

cv::keypoint创建

友情链接: zabbix.zip