千家信息网

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

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,本篇内容主要讲解"opencv3/C++中怎么实现平面对象识别和透视变换",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"opencv3/C++中怎么实现平面
千家信息网最后更新 2026年10月31日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安全错误 数据库的锁怎样保障安全 上海喔噻互联网科技有限公司 互联网科技活动banner 科技金融是不是互联网金融 互联网科技会 科技企业和互联网企业 深圳科技互联网 北京互联网科技有限公司 百单互联网科技有限公司 银优互联网科技有限公司 腾讯科技 互联网女皇 互联网科技论坛 丰台科技园 互联网公司 广州恒生互联网科技有限 青岛科技大学互联网大赛研究生 知域互联网科技有限公司大骗子 互联网科技快讯热点 广州有谷有贝互联网科技有限公司 神州科技互联网有限公司 恒生科技互联网指数十大成分股 六子台科技互联网展会 滨湖区互联网智能科技产品供应 恒银科技与互联网金融 银川新华互联网科技职业技术培训学校图片 赶超互联网科技 微信多开 移动互联网科技公司 玉溪互联网科技怎么选 洛阳共同富裕互联网科技有限公司 互联网科技创新的路径 工业互联网等科技实现智能化赋能 知域互联网科技有限公司官网
0