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 相关文章推荐
python根据文件大小打log日志
Oct 09 Python
python判断字符串是否纯数字的方法
Nov 19 Python
python制作小说爬虫实录
Aug 14 Python
Python程序员面试题 你必须提前准备!
Jan 16 Python
python中实现字符串翻转的方法
Jul 11 Python
Python的UTC时间转换讲解
Feb 26 Python
Python3.5 Json与pickle实现数据序列化与反序列化操作示例
Apr 29 Python
对Django项目中的ORM映射与模糊查询的使用详解
Jul 18 Python
django+tornado实现实时查看远程日志的方法
Aug 12 Python
TensorFlow命名空间和TensorBoard图节点实例
Jan 23 Python
Python中Selenium模块的使用详解
Oct 09 Python
python中xlutils库用法浅析
Dec 29 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
浅谈PHP强制类型转换,慎用!
2013/06/06 PHP
使用Smarty 获取当前日期时间和格式化日期时间的方法详解
2013/06/18 PHP
codeigniter中测试通过的分页类示例
2014/04/17 PHP
Laravel中Trait的用法实例详解
2016/03/16 PHP
php+ajax注册实时验证功能
2016/07/20 PHP
PHP的图像处理实例小结【文字水印、图片水印、压缩图像等】
2019/12/20 PHP
JS定时刷新页面及跳转页面的方法
2013/07/04 Javascript
在JavaScript里嵌入大量字符串常量的实现方法
2013/07/07 Javascript
给js文件传参数(详解)
2014/07/13 Javascript
jQuery元素的隐藏与显示实例
2015/01/20 Javascript
Bootstrap导航条可点击和鼠标悬停显示下拉菜单的实现代码
2016/06/23 Javascript
Javascript发送AJAX请求实例代码
2016/08/21 Javascript
微信小程序新增的拖动组件movable-view使用教程
2017/05/20 Javascript
详解vue-cli快速构建项目以及引入bootstrap、jq
2017/05/26 Javascript
jQuery获取table表中的td标签(实例讲解)
2017/07/28 jQuery
VUE中的无限循环代码解析
2017/09/22 Javascript
vue.js分页中单击页码更换页面内容的方法(配合spring springmvc)
2018/02/10 Javascript
浅谈Vue Element中Select下拉框选取值的问题
2018/03/01 Javascript
node+express框架中连接使用mysql(经验总结)
2018/11/10 Javascript
微信小程序map组件结合高德地图API实现wx.chooseLocation功能示例
2019/01/23 Javascript
Vue前端项目部署IIS的实现
2020/01/06 Javascript
Python+Django在windows下的开发环境配置图解
2009/11/11 Python
用python删除java文件头上版权信息的方法
2014/07/31 Python
python 创建一个空dataframe 然后添加行数据的实例
2018/06/07 Python
python实现汉诺塔算法
2021/03/01 Python
python实现汽车管理系统
2018/11/30 Python
selenium3+python3环境搭建教程图解
2018/12/07 Python
python字典setdefault方法和get方法使用实例
2019/12/25 Python
深入研究HTML5实现图片压缩上传功能
2016/03/25 HTML / CSS
《识字五》教学反思
2014/03/01 职场文书
颁奖典礼主持词
2014/03/25 职场文书
讲文明知礼仪演讲稿
2014/09/13 职场文书
新生儿未入户证明
2015/06/23 职场文书
新店开张宣传语
2015/07/13 职场文书
拔河比赛新闻稿
2015/07/17 职场文书
Java实现二分搜索树的示例代码
2022/03/17 Java/Android