opencv3/C++ 平面对象识别&透视变换方式


Posted in Python onDecember 11, 2019

findHomography( )

函数findHomography( )找到两个平面之间的透视变换H。

参数说明:

Mat findHomography( 
InputArray srcPoints, //原始平面中点的坐标
InputArray dstPoints, //目标平面中点的坐标
int method = 0, //用于计算单应性矩阵的方法
double ransacReprojThreshold = 3, 
OutputArray mask=noArray(), //通过鲁棒法(RANSAC或LMEDS)设置的可选输出掩码
const int maxIters = 2000, //RANSAC迭代的最大次数,2000是它可以达到的最大值
const double confidence = 0.995 //置信度
);

用于计算单应性矩阵的方法有:

0 :使用所有点的常规方法;

RANSAC:基于RANSAC的鲁棒法;

LMEDS :最小中值鲁棒法;

RHO :基于PROSAC的鲁棒法;

opencv3/C++ 平面对象识别&透视变换方式

被最小化。如果参数方法被设置为默认值0,则函数使用所有的点对以简单的最小二乘方案计算初始单应性估计。

然而,如果不是所有的点对 opencv3/C++ 平面对象识别&透视变换方式 都符合刚性透视变换(也就是说有一些异常值),那么这个初始估计就会很差。在这种情况下,可以使用三种鲁棒法之一。方法RANSAC,LMeDS和RHO尝试使用这个子集和一个简单的最小二乘算法来估计单应矩阵的各个随机子集(每个子集有四对),然后计算计算的单应性的质量/良好度(这是RANSAC的内点数或LMeD的中值重投影误差)。然后使用最佳子集来产生单应矩阵的初始估计和内点/外点的掩码。

不管方法是否鲁棒,计算的单应性矩阵都用Levenberg-Marquardt方法进一步细化(仅在鲁棒法的情况下使用inlier)以更多地减少再投影误差。

RANSAC和RHO方法几乎可以处理任何异常值的比率,但需要一个阈值来区分异常值和异常值。 LMeDS方法不需要任何阈值,但只有在超过50%的内部值时才能正常工作。最后,如果没有异常值且噪声相当小,则使用默认方法(method = 0)。

perspectiveTransform()

函数perspectiveTransform()执行矢量的透视矩阵变换。

参数说明:

void perspectiveTransform(
InputArray src, //输入双通道或三通道浮点数组/图像
OutputArray dst, //输出与src相同大小和类型的数组/图像
InputArray m //3x3或4x4浮点转换矩阵
);

平面对象识别:

#include<opencv2/opencv.hpp>
#include<opencv2/xfeatures2d.hpp>
using namespace cv;
using namespace cv::xfeatures2d;

int main()
{
 Mat src1,src2;
 src1 = imread("E:/image/image/card.jpg");
 src2 = imread("E:/image/image/cards.jpg");
 if (src1.empty() || src2.empty())
 {
  printf("can ont load images....\n");
  return -1;
 }
 imshow("image1", src1);
 imshow("image2", src2);

 int minHessian = 400;
 //选择SURF特征
 Ptr<SURF>detector = SURF::create(minHessian);
 std::vector<KeyPoint>keypoints1;
 std::vector<KeyPoint>keypoints2;
 Mat descriptor1, descriptor2;
 //检测关键点并计算描述符
 detector->detectAndCompute(src1, Mat(), keypoints1, descriptor1);
 detector->detectAndCompute(src2, Mat(), keypoints2, descriptor2);

 //基于Flann的描述符匹配器
 FlannBasedMatcher matcher;
 std::vector<DMatch>matches;
 //从查询集中查找每个描述符的最佳匹配
 matcher.match(descriptor1, descriptor2, matches);
 double minDist = 1000;
 double maxDist = 0;
 for (int i = 0; i < descriptor1.rows; i++)
 {
  double dist = matches[i].distance;
  printf("%f \n", dist);
  if (dist > maxDist)
  {
   maxDist = dist;
  }
  if (dist < minDist)
  {
   minDist = dist;
  }

 }
 //DMatch类用于匹配关键点描述符的
 std::vector<DMatch>goodMatches;
 for (int i = 0; i < descriptor1.rows; i++)
 {
  double dist = matches[i].distance;
  if (dist < max(2*minDist, 0.02))
  {
   goodMatches.push_back(matches[i]);
  }
 }
 Mat matchesImg;
 drawMatches(src1, keypoints1, src2, keypoints2, goodMatches, matchesImg, Scalar::all(-1), 
  Scalar::all(-1), std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);

 std::vector<Point2f>point1, point2;
 for (int i = 0; i < goodMatches.size(); i++)
 {
  point1.push_back(keypoints1[goodMatches[i].queryIdx].pt);
  point2.push_back(keypoints2[goodMatches[i].trainIdx].pt);
 }

 Mat H = findHomography(point1, point2, RANSAC);
 std::vector<Point2f>cornerPoints1(4);
 std::vector<Point2f>cornerPoints2(4);
 cornerPoints1[0] = Point(0, 0);
 cornerPoints1[1] = Point(src1.cols, 0);
 cornerPoints1[2] = Point(src1.cols, src1.rows);
 cornerPoints1[3] = Point(0,src1.rows);
 perspectiveTransform(cornerPoints1, cornerPoints2, H);

 //绘制出变换后的目标轮廓,由于左侧为图像src2故坐标点整体右移src1.cols
 line(matchesImg, cornerPoints2[0] + Point2f(src1.cols, 0), cornerPoints2[1] + Point2f(src1.cols, 0), Scalar(0,255,255), 4, 8, 0);
 line(matchesImg, cornerPoints2[1] + Point2f(src1.cols, 0), cornerPoints2[2] + Point2f(src1.cols, 0), Scalar(0,255,255), 4, 8, 0);
 line(matchesImg, cornerPoints2[2] + Point2f(src1.cols, 0), cornerPoints2[3] + Point2f(src1.cols, 0), Scalar(0,255,255), 4, 8, 0);
 line(matchesImg, cornerPoints2[3] + Point2f(src1.cols, 0), cornerPoints2[0] + Point2f(src1.cols, 0), Scalar(0,255,255), 4, 8, 0);

 //在原图上绘制出变换后的目标轮廓
 line(src2, cornerPoints2[0], cornerPoints2[1], Scalar(0,255,255), 4, 8, 0);
 line(src2, cornerPoints2[1], cornerPoints2[2], Scalar(0,255,255), 4, 8, 0);
 line(src2, cornerPoints2[2], cornerPoints2[3], Scalar(0,255,255), 4, 8, 0);
 line(src2, cornerPoints2[3], cornerPoints2[0], Scalar(0,255,255), 4, 8, 0);

 imshow("output", matchesImg);
 imshow("output2", src2);

 waitKey();
 return 0;
}

opencv3/C++ 平面对象识别&amp;透视变换方式

opencv3/C++ 平面对象识别&amp;透视变换方式

opencv3/C++ 平面对象识别&amp;透视变换方式

以上这篇opencv3/C++ 平面对象识别&透视变换方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
pycharm安装图文教程
May 02 Python
python 实现tar文件压缩解压的实例详解
Aug 20 Python
Python全排列操作实例分析
Jul 24 Python
python3+selenium实现126邮箱登陆并发送邮件功能
Jan 23 Python
Python3.5局部变量与全局变量作用域实例分析
Apr 30 Python
Windows平台Python编程必会模块之pywin32介绍
Oct 01 Python
利用python实现冒泡排序算法实例代码
Dec 01 Python
将pymysql获取到的数据类型是tuple转化为pandas方式
May 15 Python
Python 处理日期时间的Arrow库使用
Aug 18 Python
python更新数据库中某个字段的数据(方法详解)
Nov 18 Python
Django模板报TemplateDoesNotExist异常(亲测可行)
Dec 18 Python
python基于pexpect库自动获取日志信息
Feb 01 Python
Python Lambda函数使用总结详解
Dec 11 #Python
Python迭代器模块itertools使用原理解析
Dec 11 #Python
Python+Selenium+phantomjs实现网页模拟登录和截图功能(windows环境)
Dec 11 #Python
Python partial函数原理及用法解析
Dec 11 #Python
opencv3/python 鼠标响应操作详解
Dec 11 #Python
通过实例简单了解Python中yield的作用
Dec 11 #Python
opencv3/Python 稠密光流calcOpticalFlowFarneback详解
Dec 11 #Python
You might like
AM/FM收音机的安装与调试
2021/03/02 无线电
用php和MySql来与ODBC数据连接
2006/10/09 PHP
php mssql 时间格式问题
2009/01/13 PHP
基于php设计模式中工厂模式详细介绍
2013/05/15 PHP
smarty模板引擎中变量及变量修饰器用法实例
2015/01/22 PHP
使用Appcan客户端自动更新PHP版本号(全)
2015/07/31 PHP
php实现的mysqldb读写分离操作类示例
2017/02/07 PHP
javascript入门基础之私有变量
2010/02/23 Javascript
js对象关系图 方便dom操作
2012/03/18 Javascript
ExtJS下 Ext.Direct加载和提交过程排错小结
2013/04/02 Javascript
基于jquery实现日历签到功能
2020/09/11 Javascript
easyui导出excel无法弹出下载框的快速解决方法
2016/11/10 Javascript
Angular.js中定时器循环的3种方法总结
2017/04/27 Javascript
jQuery Ajax使用FormData上传文件和其他数据后端web.py获取
2017/06/11 jQuery
vue-cli如何引入bootstrap工具的方法
2017/10/19 Javascript
element ui 表格动态列显示空白bug 修复方法
2018/09/04 Javascript
详解key在Vue列表渲染时究竟起到了什么作用
2019/04/20 Javascript
jsonp跨域获取百度联想词的方法分析
2019/05/13 Javascript
vue 使用高德地图vue-amap组件过程解析
2019/09/07 Javascript
vue v-for 点击当前行,获取当前行数据及event当前事件对象的操作
2020/09/10 Javascript
JavaScript常用工具函数库汇总
2020/09/17 Javascript
Python提示[Errno 32]Broken pipe导致线程crash错误解决方法
2014/11/19 Python
基于Django filter中用contains和icontains的区别(详解)
2017/12/12 Python
Python爬虫中urllib库的进阶学习
2018/01/05 Python
Python 25行代码实现的RSA算法详解
2018/04/10 Python
Python读取xlsx文件的实现方法
2019/07/04 Python
pandas 中对特征进行硬编码和onehot编码的实现
2019/12/20 Python
对django 2.x版本中models.ForeignKey()外键说明介绍
2020/03/30 Python
基于python的opencv图像处理实现对斑马线的检测示例
2020/11/29 Python
遮罩层 + Iframe实现界面自动显示的示例代码
2020/04/26 HTML / CSS
财务部出纳岗位职责
2013/12/22 职场文书
素质拓展感言
2014/01/29 职场文书
小学生运动会报道稿
2014/09/12 职场文书
婚庆主持词大全
2015/06/30 职场文书
小学六一儿童节活动开幕词
2016/03/04 职场文书
apache虚拟主机配置的三种方式(小结)
2022/07/23 Servers