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删除windows垃圾文件的方法
Jul 14 Python
Python基于递归算法实现的走迷宫问题
Aug 04 Python
Python基于pygame模块播放MP3的方法示例
Sep 30 Python
python爬虫headers设置后无效的解决方法
Oct 21 Python
基于python 二维数组及画图的实例详解
Apr 03 Python
查看django版本的方法分享
May 14 Python
python匹配两个短语之间的字符实例
Dec 25 Python
django实现用户注册实例讲解
Oct 30 Python
Python使用qrcode二维码库生成二维码方法详解
Feb 17 Python
解决Keras 中加入lambda层无法正常载入模型问题
Jun 16 Python
Python中lru_cache的使用和实现详解
Jan 25 Python
Python3 多线程(连接池)操作MySQL插入数据
Jun 09 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
全国FM电台频率大全 - 22 重庆市
2020/03/11 无线电
给php新手谈谈我的学习心得
2007/02/25 PHP
PHP cron中的批处理
2008/09/16 PHP
yii框架源码分析之创建controller代码
2011/06/28 PHP
php像数组一样存取和修改字符串字符
2014/03/21 PHP
PHP实现适用于自定义的验证码类
2016/06/15 PHP
浅谈PHP的排列组合(如输入a,b,c 输出他们的全部组合)
2017/03/14 PHP
javascript 单例/单体模式(Singleton)
2011/04/07 Javascript
基于jquery实现的表格分页实现代码
2011/06/21 Javascript
利用JQuery和Servlet实现跨域提交请求示例分享
2014/02/12 Javascript
js实现字符串的16进制编码不加密
2014/04/25 Javascript
javascript与有限状态机详解
2014/05/08 Javascript
javascript实现获取cookie过期时间的变通方法
2014/08/14 Javascript
Mac OS X 系统下安装和部署Egret引擎开发环境
2014/09/03 Javascript
了不起的node.js读书笔记之node的学习总结
2014/12/22 Javascript
javascript删除数组重复元素的方法汇总
2015/06/24 Javascript
WordPress中利用AJAX技术进行评论提交的实现示例
2016/01/12 Javascript
javascript的函数劫持浅析
2016/09/26 Javascript
BootStrap框架中的data-[ ]自定义属性理解(推荐)
2017/02/14 Javascript
解决vue组件中使用v-for出现告警问题及v for指令介绍
2017/11/11 Javascript
Electron中实现大文件上传和断点续传功能
2018/10/28 Javascript
vue 表单之通过v-model绑定单选按钮radio
2019/05/13 Javascript
[01:07]2015国际邀请赛 中国区预选赛精彩回顾
2015/06/15 DOTA
[01:13:46]iG vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
python 把数据 json格式输出的实例代码
2016/10/31 Python
Anaconda下配置python+opencv+contribx的实例讲解
2018/08/06 Python
Python 保持登录状态进行接口测试的方法示例
2019/08/06 Python
利用pytorch实现对CIFAR-10数据集的分类
2020/01/14 Python
解决pycharm安装第三方库失败的问题
2020/05/09 Python
美国最大点评网站:Yelp
2018/02/14 全球购物
纠纷协议书
2014/04/16 职场文书
2014年资料员工作总结
2014/11/18 职场文书
交通事故死亡赔偿协议书
2014/12/03 职场文书
租赁协议书
2015/01/27 职场文书
公司员工管理制度
2015/08/04 职场文书
JavaScript架构localStorage特殊场景下二次封装操作
2022/06/21 Javascript