热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

学习OpenCV范例(二十一)——Keypoints+Knn+findHomography进行目标定位

本范例的代码主要都是学习OpenCV——通过KeyPoints进行目标定位这篇博客提供的,然后在它的基础上稍加修改,检测keypoints点的检测器是S

本范例的代码主要都是 学习OpenCV——通过KeyPoints进行目标定位这篇博客提供的,然后在它的基础上稍加修改,检测keypoints点的检测器是SURF,获取描述子也是用到SURF来描述,而用到的匹配器是FlannBased,匹配的方式是Knn方式,最后通过findHomography寻找单映射矩阵,perspectiveTransform获得最终的目标,在这个过程中还通过单映射矩阵来进一步去除伪匹配,这里只是贴出代码和代码解析,至于原理还没弄得特别明白,希望接下来可以继续学习,学懂了算法原理再来补充。

1、代码实现

#include "stdafx.h"
#include "opencv2/opencv.hpp"
#include
#include using namespace cv;
using namespace std;
Mat src,frameImg;
int width;
int height;
vector srcCorner(4);
vector dstCorner(4); static bool createDetectorDescriptorMatcher( const string& detectorType, const string& descriptorType, const string& matcherType, Ptr& featureDetector, Ptr& descriptorExtractor, Ptr& descriptorMatcher )
{ cout <<"" <" <} bool refineMatchesWithHomography(const std::vector& queryKeypoints, const std::vector& trainKeypoints, float reprojectionThreshold, std::vector& matches, cv::Mat& homography )
{ const int minNumberMatchesAllowed &#61; 4; if (matches.size() queryPoints(matches.size()); std::vector trainPoints(matches.size()); for (size_t i &#61; 0; i inliersMask(matches.size()); homography &#61; cv::findHomography(queryPoints, trainPoints, CV_FM_RANSAC, reprojectionThreshold, inliersMask); std::vector inliers; for (size_t i&#61;0; i minNumberMatchesAllowed; } bool matchingDescriptor(const vector& queryKeyPoints,const vector& trainKeyPoints, const Mat& queryDescriptors,const Mat& trainDescriptors, Ptr& descriptorMatcher, bool enableRatioTest &#61; true)
{ vector> m_knnMatches; vectorm_Matches; if (enableRatioTest) { cout<<"KNN Matching"<knnMatch(queryDescriptors,trainDescriptors,m_knnMatches,2); for (size_t i&#61;0; i BFMatcher(new cv::BFMatcher(cv::NORM_HAMMING, true)); BFMatcher->match(queryDescriptors,trainDescriptors, m_Matches ); } Mat homo; float homographyReprojectionThreshold &#61; 1.0; bool homographyFound &#61; refineMatchesWithHomography( queryKeyPoints,trainKeyPoints,homographyReprojectionThreshold,m_Matches,homo); if (!homographyFound) return false; else { if (m_Matches.size()>10){std::vector obj_corners(4);obj_corners[0] &#61; cvPoint(0,0); obj_corners[1] &#61; cvPoint( src.cols, 0 );obj_corners[2] &#61; cvPoint( src.cols, src.rows ); obj_corners[3] &#61; cvPoint( 0, src.rows );std::vector scene_corners(4);perspectiveTransform( obj_corners, scene_corners, homo);line(frameImg,scene_corners[0],scene_corners[1],CV_RGB(255,0,0),2); line(frameImg,scene_corners[1],scene_corners[2],CV_RGB(255,0,0),2); line(frameImg,scene_corners[2],scene_corners[3],CV_RGB(255,0,0),2); line(frameImg,scene_corners[3],scene_corners[0],CV_RGB(255,0,0),2); return true; }return true;} }
int main()
{ string filename &#61; "box.png"; src &#61; imread(filename,0); width &#61; src.cols; height &#61; src.rows; string detectorType &#61; "SIFT"; string descriptorType &#61; "SIFT"; string matcherType &#61; "FlannBased"; Ptr featureDetector; Ptr descriptorExtractor; Ptr descriptorMatcher; if( !createDetectorDescriptorMatcher( detectorType, descriptorType, matcherType, featureDetector, descriptorExtractor, descriptorMatcher ) ) { cout<<"Creat Detector Descriptor Matcher False!"< queryKeypoints; Mat queryDescriptor; featureDetector->detect(src,queryKeypoints); descriptorExtractor->compute(src,queryKeypoints,queryDescriptor); VideoCapture cap(0); // open the default camera cap.set( CV_CAP_PROP_FRAME_WIDTH,320);cap.set( CV_CAP_PROP_FRAME_HEIGHT,240 );if(!cap.isOpened()) // check if we succeeded { cout<<"Can&#39;t Open Camera!"< trainKeypoints; Mat trainDescriptor; Mat frame,grayFrame;char key&#61;0; // frame &#61; imread("box_in_scene.png"); while (key!&#61;27) { cap>>frame; if (!frame.empty()){frame.copyTo(frameImg);printf("%d,%d\n",frame.depth(),frame.channels());grayFrame.zeros(frame.rows,frame.cols,CV_8UC1);cvtColor(frame,grayFrame,CV_BGR2GRAY); trainKeypoints.clear(); trainDescriptor.setTo(0); featureDetector->detect(grayFrame,trainKeypoints); if(trainKeypoints.size()!&#61;0) { descriptorExtractor->compute(grayFrame,trainKeypoints,trainDescriptor); bool isFound &#61; matchingDescriptor(queryKeypoints,trainKeypoints,queryDescriptor,trainDescriptor,descriptorMatcher); imshow("foundImg",frameImg); } }key &#61; waitKey(1); } cap.release();return 0;
}



2、运行结果

\| \texttt{dstPoints} _i -  \texttt{convertPointsHomogeneous} ( \texttt{H} * \texttt{srcPoints} _i) \|  >  \texttt{ransacReprojThreshold}

那么点i则被考虑为内部点&#xff0c;如果srcPoints和dstPoints是以像素为单位&#xff0c;通常把参数设置为1-10范围内 

mask &#xff1a;可选的输出掩码( CV_RANSAC or CV_LMEDS ). 输入的掩码值被忽略. &#xff08;存储inliers的点&#xff09;                            

这个函数的作用是在原平面和目标平面之间返回一个单映射矩阵

s_i  \vecthree{x&#39;_i}{y&#39;_i}{1} \sim H  \vecthree{x_i}{y_i}{1}

因此反投影误差\sum _i \left ( x&#39;_i- \frac{h_{11} x_i &#43; h_{12} y_i &#43; h_{13}}{h_{31} x_i &#43; h_{32} y_i &#43; h_{33}} \right )^2&#43; \left ( y&#39;_i- \frac{h_{21} x_i &#43; h_{22} y_i &#43; h_{23}}{h_{31} x_i &#43; h_{32} y_i &#43; h_{33}} \right )^2是最小的。

如果参数被设置为0&#xff0c;那么这个函数使用所有的点和一个简单的最小二乘算法来计算最初的单应性估计&#xff0c;但是&#xff0c;如果不是所有的点对都完全符合透视变换&#xff0c;那么这个初始的估计会很差&#xff0c;在这种情况下&#xff0c;你可以使用两个robust算法中的一个。 RANSAC 和LMeDS , 使用坐标点对生成了很多不同的随机组合子集&#xff08;每四对一组&#xff09;&#xff0c;使用这些子集和一个简单的最小二乘法来估计变换矩阵&#xff0c;然后计算出单应性的质量&#xff0c;最好的子集被用来产生初始单应性的估计和掩码。
RANSAC方法几乎可以处理任何异常&#xff0c;但是需要一个阈值&#xff0c; LMeDS 方法不需要任何阈值&#xff0c;但是只有在inliers大于50%时才能计算正确&#xff0c;最后&#xff0c;如果没有outliers和噪音非常小&#xff0c;则可以使用默认的方法。

PerspectiveTransform

功能&#xff1a;向量数组的透视变换

结构&#xff1a;

void perspectiveTransform(InputArray src, OutputArray dst, InputArray m)

src &#xff1a;输入两通道或三通道的浮点数组&#xff0c;每一个元素是一个2D/3D 的矢量转换

dst &#xff1a;输出和src同样的size和type
m &#xff1a;3x3 或者4x4浮点转换矩阵
转换方法为&#xff1a;

(x, y, z)  \rightarrow (x&#39;/w, y&#39;/w, z&#39;/w)

(x&#39;, y&#39;, z&#39;, w&#39;) &#61;  \texttt{mat} \cdot \begin{bmatrix} x & y & z & 1  \end{bmatrix}

w &#61;  \fork{w&#39;}{if $w&#39; \ne 0$}{\infty}{otherwise}





推荐阅读
  • 电话号码的字母组合解题思路和代码示例
    本文介绍了力扣题目《电话号码的字母组合》的解题思路和代码示例。通过使用哈希表和递归求解的方法,可以将给定的电话号码转换为对应的字母组合。详细的解题思路和代码示例可以帮助读者更好地理解和实现该题目。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 本文详细介绍了使用C#实现Word模版打印的方案。包括添加COM引用、新建Word操作类、开启Word进程、加载模版文件等步骤。通过该方案可以实现C#对Word文档的打印功能。 ... [详细]
author-avatar
CPA娇_588
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有