openCV 特征点识别 与findHomography算法过滤

2023-10-31

 

一,首先我们对函数先进行分析

findHomography:

 计算多个二维点对之间的最优单映射变换矩阵 H(3行x3列) (就是对图片的矫正),使用最小均方误差或者RANSAC方法

函数功能:找到两个平面之间的转换矩阵。


 

这里涉及到映射变换的知识,

 

 

 下面介绍下什么是映射变换:

 1,如下图所示:

如果平面上点场的点建立了一个一一对应,并且满足:

(1)任何共线三点的象仍是共线三点;

(2)共线四点的交比不变。

则这个一一对应叫做点场的射影变换,简称射影变换

交比:      

 

一维射影变换:

 二维的图像是这样的

 


  射影变换也叫做单应(Homography)

 

 图1通过H矩阵变换变成图2,就是这个函数的公式

                                       X′=HX

X′代表图2

其操作过程

  • 在“大”图像(目标图像)上选择4个点和“小”图像(被合并图像)的四角做对应,然后根据这4对对应的点计算两幅图像的单应矩阵。
  • 得到单应矩阵H后,利用函数warpPerspective将H应用到“小”图像上,得到图像M
  • 将图像M合并到目标图像中选择的四个点的位置

 

复制代码

Mat cv::findHomography ( InputArray srcPoints,
InputArray dstPoints,
int method = 0,
double ransacReprojThreshold = 3,
OutputArray mask = noArray(),
const int maxIters = 2000,
const double confidence = 0.995 
)

复制代码

参数详解:

srcPoints    源平面中点的坐标矩阵,可以是CV_32FC2类型,也可以是vector<Point2f>类型
dstPoints    目标平面中点的坐标矩阵,可以是CV_32FC2类型,也可以是vector<Point2f>类型
method       计算单应矩阵所使用的方法。不同的方法对应不同的参数,具体如下:
0 - 利用所有点的常规方法
RANSAC - RANSAC-基于RANSAC的鲁棒算法
LMEDS - 最小中值鲁棒算法
RHO - PROSAC-基于PROSAC的鲁棒算法
ransacReprojThreshold
将点对视为内点的最大允许重投影错误阈值(仅用于RANSAC和RHO方法)。如果

则点被认为是个外点(即错误匹配点对)。若srcPoints和dstPoints是以像素为单位的,则该参数通常设置在1到10的范围内。

mask
可选输出掩码矩阵,通常由鲁棒算法(RANSAC或LMEDS)设置。 请注意,输入掩码矩阵是不需要设置的。

maxIters RANSAC 算法的最大迭代次数,默认值为2000。
confidence 可信度值,取值范围为0到1.

首先定义两个vector保存对应的4对点

复制代码

//图片映射矩阵把不同角度的图片矫正
void findHomographyText(){

    // Read source image.
    Mat src = imread("F:\\视觉\\opencv\\pic\\1.png");
    // Four corners of the book in source image
    vector<Point2f> pts_src;
    pts_src.push_back(Point2f(0, 0));
    pts_src.push_back(Point2f(src.cols, 0));
    pts_src.push_back(Point2f(src.cols, src.rows));
    pts_src.push_back(Point2f(0, src.rows));

    // Four corners of the book in destination image.
    vector<Point2f> pts_dst;
    pts_dst.push_back(Point2f(0, 0));
    pts_dst.push_back(Point2f(src.cols/4, 0));
    pts_dst.push_back(Point2f(src.cols/3, src.rows));
    pts_dst.push_back(Point2f(0, src.rows/2));

    // Calculate Homography
    Mat h = findHomography(pts_src, pts_dst);

    // Output image
    Mat im_out;
    // Warp source image to destination based on homography
    warpPerspective(src, im_out, h, src.size());

    // Display images
    imshow("Source Image", src);
    imshow("Warped Source Image", im_out);

    waitKey(0);

}

复制代码

结果如下图所示对图像进行拉伸

步骤如下

1,相求H 

 vector<Point2f> pts_src;
    pts_src.push_back(Point2f(0, 0));
    pts_src.push_back(Point2f(src.cols, 0));
    pts_src.push_back(Point2f(src.cols, src.rows));
    pts_src.push_back(Point2f(0, src.rows));

    // Four corners of the book in destination image.
    vector<Point2f> pts_dst;
    pts_dst.push_back(Point2f(0, 0));
    pts_dst.push_back(Point2f(src.cols/4, 0));
    pts_dst.push_back(Point2f(src.cols/3, src.rows));
    pts_dst.push_back(Point2f(0, src.rows/2));

    // Calculate Homography
    Mat h = findHomography(pts_src, pts_dst);

通过H求对应的图像(映射到输出图片上)

warpPerspective(src, im_out, h, src.size());
warpPerspective:通过H求取

im_out输出值介绍完两个主要的函数下面开始对图像进行识别和标记

2,SURF对图像的识别和标记

1,开发思路

(1)使用SIFT或者SURF进行角点检测,获取两个图像的的角点集合

(2)根据两个集合,使用特征点匹配,匹配类似的点 FlannBasedMatcher

(3)过滤特征点对。

(4)通过特征点对,求出H值

(5)画出特征区域

代码实现:

1,使用SIFT或者SURF进行角点检测,获取两个图像的的角点集合

 src = imread("F:\\视觉\\opencv\\pic\\11.png");//读图片
src3 = imread("F:\\视觉\\opencv\\pic\\5.png");//读图片

int minHessian = 400;
    cvtColor(src, src, COLOR_BGR2GRAY);
    cvtColor(src3, src3, COLOR_BGR2GRAY);

    Ptr<SIFT> detector = SIFT::create(minHessian);
    vector<KeyPoint> keypoints_obj;//图片1特征点
    vector<KeyPoint> keypoints_scene;//图片2特征点
    Mat descriptor_obj, descriptor_scene;

    //找出特征点存到keypoints_obj与keypoints_scene点集中
    detector->detectAndCompute(src, Mat(), keypoints_obj, descriptor_obj);
    detector->detectAndCompute(src3, Mat(), keypoints_scene, descriptor_scene);

    // matching 找到特征集合
    FlannBasedMatcher matcher;
    vector<DMatch> matches;
    matcher.match(descriptor_obj, descriptor_scene, matches);

2,过滤相似度高的图像

// find good matched points
    double minDist = 1000;
    double maxDist = 0;

    for (int i = 0; i < descriptor_obj.rows; i++) {
        double dist = matches[i].distance;
        if (dist > maxDist) {
            maxDist = dist;
        }
        if (dist < minDist) {
            minDist = dist;
        }
    }
    printf("max distance : %f\n", maxDist);
    printf("min distance : %f\n", minDist);

    vector<DMatch> goodMatches;
    //过滤相同的点
    for (int i = 0; i < descriptor_obj.rows; i++) {
        double dist = matches[i].distance;//相识度
        printf("distance : %f\n", dist);
        if (dist < max(3 * minDist, 0.2)) {
            goodMatches.push_back(matches[i]);
        }
    }

3,求出H

vector<Point2f> obj;
    vector<Point2f> objInScene;
    for (size_t t = 0; t < goodMatches.size(); t++) {
        //把DMatch转成坐标 Point2f
        obj.push_back(keypoints_obj[goodMatches[t].queryIdx].pt);

        objInScene.push_back(keypoints_scene[goodMatches[t].trainIdx].pt);
    }
    //用来求取“射影变换”的H转制矩阵函数  X'=H X ,并使用RANSAC消除一些出错的点
    Mat H = findHomography(obj, objInScene, RANSAC);

4,使用H求出映射到大图的点

vector<Point2f> obj_corners(4);
    vector<Point2f> scene_corners(4);
    obj_corners[0] = Point(0, 0);
    obj_corners[1] = Point(src.cols, 0);
    obj_corners[2] = Point(src.cols, src.rows);
    obj_corners[3] = Point(0, src.rows);
    //透视变换(把斜的图片扶正)
    cout << H << endl;
    perspectiveTransform(obj_corners, scene_corners, H);

5,在原图上画线段

1

2

3

4

5

6

7

8

9

Mat dst;

    cvtColor(src3, dst, COLOR_GRAY2BGR);

    line(dst, scene_corners[0], scene_corners[1], Scalar(0, 0, 255), 2, 8, 0);

    line(dst, scene_corners[1], scene_corners[2], Scalar(0, 0, 255), 2, 8, 0);

    line(dst, scene_corners[2], scene_corners[3], Scalar(0, 0, 255), 2, 8, 0);

    line(dst, scene_corners[3], scene_corners[0], Scalar(0, 0, 255), 2, 8, 0);

 

 

    imshow("Draw object", dst);

  相似效果

 

 

谢谢,如果觉得可以请点个赞!转发请付链接。。。。

 

 原文参考:https://blog.csdn.net/fengyeer20120/article/details/87798638

https://www.cnblogs.com/wangguchangqing/p/4645805.html

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

openCV 特征点识别 与findHomography算法过滤 的相关文章

  • 使用react-grid-layout和echarts-for-react实现一个支持拖拽的自定义响应式dashboard页面

    文章目录 使用react grid layout和echarts for react实现一个支持拖拽的自定义响应式dashboard页面 需求概要 技术栈 简单实现 参考 使用react grid layout和echarts for re
  • python画聚类树状图_聚类分析python画树状图--Plotly(dendrogram)用法解析

    1 前言 聚类分析是机器学习和数据分析中非常常见的分类方法 当我们用到层次聚类 系统聚类 时 最常用的分析方法就是绘制树状图 比较常见的统计软件像SPSS SAS R等都可以直接绘制树状图 比较简单 今天主要介绍下python怎么绘制 2
  • 校园欺凌——四位学生的乱伦之战!!!

    校园欺凌 Impossible 学生之战 Non existent 乱伦 Take leave ok 兄弟姊妹们 今天我们来学习循环结构第一章 gt gt gt While与Do Whlie 循环 重复得做某一件事情 Such as 打印5
  • QVariant的用法

    前言 QVariant这个类很神奇 或者说方便 很多时候 需要几种不同的数据类型需要传递 如果用结构体 又不大方便 容器保存的也只是一种数据类型 而QVariant则可以统统搞定 介绍 帮助文档上说 The QVariant class a
  • 云化背景下的接口测试覆盖率自动化检查

    一 问题来源 在云化场景下 API的测试覆盖是一项重要评估与考察指标 除了开发者自测试外 UT 还可以利用云化测试平台 流水线等方法进行相关指标的检查与考核 利用这种方法既可以减轻开发者测试工作量 不必在本地做大量的 降低人为指标灰度空间
  • Android10.0 Binder通信原理(八)-Framework层分析

    Android取经之路 的源码都基于Android Q 10 0 进行分析 Android取经之路 系列文章 系统启动篇 Android系统架构Android是怎么启动的Android 10 0系统启动之init进程Android10 0系
  • 虚拟机Ubuntu操作系统最基本终端命令(安装包+详细解释+详细演示)

    虚拟机及乌班图 Ubuntu操作系统 提示 大家需要软件的可以直接在此链接中提取 链接 https pan baidu com s 1 4VHGTlXjIuVhBINeOuBCA 提取码 nd0c 文章目录 虚拟机及乌班图 Ubuntu操作
  • 数据质量测试:测试数据有效性和准确性的方法

    以下为作者观点 来看看你认同吗 如果西西弗斯 编者注 希腊神话中的人物 是一个数据分析师或数据科学家 他在山上滚动的巨石将是他的数据质量保障 即使所有获取 处理和建模的工程流程都无懈可击 但在数据管道的任何阶段测试数据质量的能力 以及面对
  • java中的集合框架

    一 集合框架 集合框架 java做好的用来管理乱七八糟的一堆数据的java类库 集合 乱七八糟的一堆 框架 做好的java类库 Java中的集合框架总体被分为2个大部分第一个大部分是用来处理单列数据的集合 最大的接口时Collection接
  • 小白开发微信小程序49--本地服务器部署测试小程序

    相信大家对微信小程序的基础和项目应该没有太大问题了 如果还有对微信小程序开发有一些问题 请查看回顾 微信小程序开发者开发好一款微信小程序后 怎么才能发布呢 如何将其提交给微信审核呢 在前面的 领航教育 项目开发中 后台采用的是C 开发语言
  • matlab 计算点云最大距离

    RANSAC 一 算法原理 1 算法概述 2 主要函数 二 代码实现 三 结果展示 四 参考链接 一 算法原理 1 算法概述 计算同一个点云中所有点之间的最大距离 是4PCS配准算法中进行重叠度预估的重要一步 是实现手写4PCS及能够对其改
  • LeetCode刷题-10

    数组 121 买卖股票的最佳时机 题目描述 题目样例 Java方法 暴力法 代码 复杂度 Java方法 一次遍历 算法思路 代码 复杂度 题目描述 给定一个数组 prices 它的第 i 个元素 prices i 表示一支给定股票第 i 天
  • 榜样访谈——董宇航:在俱乐部中收获爱情

    先做一个简单的自我介绍吧 董宇航 大家好 我是来自辽宁工程技术大学的董宇航 我是网络工程专业的 今年大三 同时也担任CSDN辽宁工程技术大学高校俱乐部俱乐部的主席 我们在线下也有一个经过学校正规备案的学生社团叫软件学院创客俱乐部 在计算机学
  • $sql=mysql_query(_MySQL mysql_query 函数执行SQL语句

    mysql query 函数 PHP MySQL 函数库中 mysql query 函数用于向 MySQL 发送并执行 SQL 语句 对于没有数据返回结果集的 SQL 如 UPDATE DELETE 等在执行成功时返回 TRUE 出错时返回
  • JenKins 自动化打包上传到服务器的fir 工具

    fir im Jenkins 插件使用方法 fir im Jenkins 插件可以更快速地上传 apk ipa 安装包到 fir im 安装 Jenkins 方法一 直接下载安装包 Download Jenkins 安装完成后在 Termi
  • PTA老板的作息表

    记得当时考场上没想到数组开始和结尾加00 00 00和23 59 59 考完才想起来 当时在那写判断 真的菜傻了 新浪微博上有人发了某老板的作息时间表 表示其每天 4 30 就起床了 但立刻有眼尖的网友问 这时间表不完整啊 早上九点到下午一
  • 自参考和对比学习正则化的Few-shot医学图像分割

    文章目录 Few shot Medical Image Segmentation Regularized with Self reference and Contrastive Learning 摘要 本文方法 Local Prototyp
  • 10大流行的 Metro UI 风格的 Bootstrap 主题和模板

    Metro UI 是一种界面展示技术 是 Windows 8 的主要界面显示风格 Metro 界面和 iOS Android 界面最大的区别在于 后两种都是以应用为主要呈现对象 而 Metro 界面强调的是信息本身 而不是冗余的界面元素 同
  • /usr/bin/env: bash: No such file or directory

    usr bin env bash r 没有这样的文件或目录 usr bin env bash No such file or directory 解决方法 sed i s r shell文件名
  • Unity新建脚本中无法继承MonoBehaviour(MonoBehaviour为灰色)

    第一种解决方法 第一步 在视图中找到解决方案资源管理器 第二步 点击显示所有文件 第三步 找到不能继承MonoBehaviour的脚本右键包括在项目中 第二种解决方法 第一步 同样打开解决方案资源管理器 第二步 右键点击解决方案 点击添加

随机推荐