千家信息网

opencv3/C++中怎么实现平面对象识别和透视变换

发表于:2025-01-16 作者:千家信息网编辑
千家信息网最后更新 2025年01月16日,本篇内容主要讲解"opencv3/C++中怎么实现平面对象识别和透视变换",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"opencv3/C++中怎么实现平面
千家信息网最后更新 2025年01月16日opencv3/C++中怎么实现平面对象识别和透视变换

本篇内容主要讲解"opencv3/C++中怎么实现平面对象识别和透视变换",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"opencv3/C++中怎么实现平面对象识别和透视变换"吧!

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的鲁棒法;

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

然而,如果不是所有的点对 都符合刚性透视变换(也就是说有一些异常值),那么这个初始估计就会很差。在这种情况下,可以使用三种鲁棒法之一。方法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#includeusing 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特征 Ptrdetector = SURF::create(minHessian); std::vectorkeypoints1; std::vectorkeypoints2; Mat descriptor1, descriptor2; //检测关键点并计算描述符 detector->detectAndCompute(src1, Mat(), keypoints1, descriptor1); detector->detectAndCompute(src2, Mat(), keypoints2, descriptor2); //基于Flann的描述符匹配器 FlannBasedMatcher matcher; std::vectormatches; //从查询集中查找每个描述符的最佳匹配 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::vectorgoodMatches; 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(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS); std::vectorpoint1, 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::vectorcornerPoints1(4); std::vectorcornerPoints2(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++中怎么实现平面对象识别和透视变换"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

方法 变换 平面 矩阵 对象 最小 子集 函数 参数 图像 目标 最大 中值 中点 关键 关键点 内容 坐标 情况 数组 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 如何把图片发送到免费的服务器上 上海邦华网络技术有限公司 服务器查看客户端mac地址 电脑网络安全手抄报防溺水 工业大学网络技术学院 lenovo服务器管理地址 中孚服务器授权管理融合系统 计算机网络技术情景模拟 服务器的系统管理打不开 互联网科技有什么陷阱 网络安全事件涉及人为因素 管理服务器如何修改时间同步 如何把表格数据制作成数据库 校园网络安全工作要点 瑞星网络安全合作 池州医疗软件开发定制 人工智能网络安全有哪些专业 修改手机dns服务器 怀旧服新服务器怎么开 网络科技和网络技术的区别 食堂充卡系统数据库 软件开发是文科理科 数据库语句日期格式转换 嵌入式软件开发有前途吗 管理服务器如何修改时间同步 p2p服务器是什么意思 数据库应用技术学的是什么 软件开发实训实验报告 软件开发广告用语 我市网络安全宣讲六进
0