Opencv计算机视觉编程攻略-第八节 检测兴趣点

news2025/5/19 18:56:18

目录

1.检测图像中的角点

2.快速检测特征

3.尺度不变特征的检测

4.多尺度FAST 特征的检测


  在计算机视觉领域,兴趣点(也称关键点或特征点)应用包括目标识别、图像配准、视觉跟踪、三维重建等。这个概念的原理是,从图像中选取某些特征点并对图像进行局部分析(即提取局部特征),而非观察整幅图像(即提取全局特征)。只要图像中有足够多可检测的兴趣点,并且这些兴趣点各不相同且特征稳定、能被精确地定位,上述方法就十分有效。
  因为要用于图像内容的分析,所以不管图像拍摄时采用了什么视角、尺度和方位,理想情况下同一个场景或目标位置都要检测到特征点。视觉不变性是图像分析中一个非常重要的属性,目前有大量关于它的研究。

1.检测图像中的角点


  角点是很容易在图像中定位的局部特征,并且大量存在于人造物体中(例如墙壁、门、窗户、桌子等)。角点的价值在于它是两条边缘线的接合点,是一种二维特征,可以被精确地检测(即使是亚像素级精度)。与此相反的是位于均匀区域或物体轮廓上的点,这些点在同一物体的不同图像上很难重复精确定位。

        Harris 特征检测方法在假定的兴趣点周围放置了一个小窗口,并观察窗口内某个方向上强度值的平均变化。如果位移向量为(u, v),那么可以用均方差之和表示强度的变化:

       累加的范围是该像素周围一个预先定义的邻域(邻域的尺寸取决于cv::cornerHarris 函数的第三个参数)。在所有方向上计算平均强度变化值,如果不止一个方向的变化值很高,就认为这个点是角点。根据这个定义,Harris 测试的步骤应为:首先获得平均强度值变化最大的方向,然后检查垂直方向上的平均强度变化值,看它是否也很大;如果是,就说明这是一个角点。
  OpenCV 中检测Harris 角点的基本函数是cornerHarris, 调用该函数时输入一幅图像,返回的结果是一个浮点数型图像,其中每个像素表示角点强度。然后对输出图像阈值化,以获得检测角点的集合。

// 检测Harris 角点
cv::Mat cornerStrength;
cv::cornerHarris(image, // 输入图像
        cornerStrength, // 角点强度的图像
        3, // 邻域尺寸
        3, // 口径尺寸
        0.01); // Harris 参数
// 对角点强度阈值化
cv::Mat harrisCorners;
double threshold= 0.0001;
cv::threshold(cornerStrength,harrisCorners,threshold,255,cv::THRESH_BINARY);

// 检测Harris 角点需要两个步骤。
//首先是计算每个像素的Harris 值:
cv::cornerHarris(image,cornerStrength,
        neighbourhood,// 邻域尺寸
        aperture, // 口径尺寸
        k); // Harris 参数
// 计算内部阈值
cv::minMaxLoc(cornerStrength,0,&maxStrength);
// 检测局部最大值
cv::Mat dilated; // 临时图像
cv::dilate(cornerStrength,dilated,cv::Mat());
cv::compare(cornerStrength,dilated, localMax, cv::CMP_EQ);

// 然后,用指定的阈值获得特征点。因为Harris 值的可选范围取决于选择的参数,所以阈值被
// 作为质量等级,用最大Harris 值的一个比例值表示:
cv::Mat getCornerMap(double qualityLevel) {
    cv::Mat cornerMap;
    // 对角点强度阈值化
    threshold= qualityLevel*maxStrength;
    cv::threshold(cornerStrength,cornerTh, threshold, 255,
    cv::THRESH_BINARY);
    // 转换成8 位图像
    cornerTh.convertTo(cornerMap,CV_8U);
    // 非最大值抑制
    cv::bitwise_and(cornerMap,localMax,cornerMap);
    return cornerMap;
}

        得到一个被检测特征的二值角点分布图。因为Harris 特征的检测过程分为两个方法,所以我们可以用不同的阈值来测试检测结果(直到获得适当数量的特征点),而不必重复进行耗时的计算过程。

       为了提升检测效果,前面介绍的类增加了一个额外的非最大值抑制步骤,作用是排除掉紧邻
的Harris 角点。因此,Harris 角点不仅要有高于指定阈值的评分,还必须是局部范围内的最大值。
为了检查这个条件,detect 方法中加入了一个小技巧,即对Harris 评分的图像做膨胀运算:
cv::dilate(cornerStrength, dilated,cv::Mat());

        膨胀运算会在邻域中把每个像素值替换成最大值,因此只有局部最大值的像素是不变的。用
下面的相等测试可以验证这一点:cv::compare(cornerStrength, dilated, localMax,cv::CMP_EQ);
因此矩阵localMax 只有在局部最大值的位置才为真(即非零)。然后将它用于getCornerMap
方法中,排除掉所有非最大值的特征(用cv::bitwise 函数)。
       如何均匀获得角点,从Harris 值最强的点开始(即具有最大的最低特征值),只允许一定距离之外的点成为兴趣点。在OpenCV 中用good-features-to-track(GFTT)实现这个算法。这个算法得名于它检测的特征非常适合作为视觉跟踪程序的起始集合,

// 计算适合跟踪的特征
std::vector<cv::KeyPoint> keypoints;
// GFTT 检测器
cv::Ptr<cv::GFTTDetector> ptrGFTT =
cv::GFTTDetector::create(
500, // 关键点的最大数量
0.01, // 质量等级
10); // 角点之间允许的最短距离
// 检测GFTT
ptrGFTT->detect(image,keypoints);

2.快速检测特征

       Harris 算子对角点(或者更通用的兴趣点)做出了规范的数学定义,该定义基于强度值在两
个互相垂直的方向上的变化率。虽然这是一种看似很完美的定义,但它需要计算图像的导数,而
计算导数是非常耗时的,另一种特征点算子,叫作FAST(Features from Accelerated Segment Test,加速分割测试获得特征)。这种算子专门用来快速检测兴趣点——只需对比几个像素,就可以判断它是否为关键点。

// 关键点的向量
std::vector<cv::KeyPoint> keypoints;
// FAST 特征检测器,阈值为40
cv::Ptr<cv::FastFeatureDetector> ptrFAST =cv::FastFeatureDetector::create(40);
// 检测关键点
ptrFAST->detect(image,keypoints);

// OpenCV 也提供了在图像上画关键点的通用函数:
cv::drawKeypoints(image, // 原始图像
                    keypoints, // 关键点的向量
                    image, // 输出图像
                    cv::Scalar(255,255,255), // 关键点的颜色
                    cv::DrawMatchesFlags::DRAW_OVER_OUTIMG); // 画图标志

        有一种比较有趣的做法,就是用一个负数作为关键点颜色。这样一来,画每个圆时会随机选
用不同的颜色。

       跟Harris 检测器的情况一样,FAST 特征算法源于“什么构成了角点”的定义。FAST 对角点的定义基于候选特征点周围的图像强度值。以某个点为中心做一个圆,根据圆上的像素值判断该点是否为关键点。如果存在这样一段圆弧,它的连续长度超过周长的3/4,并且它上面所有像素的强度值都与圆心的强度值明显不同(全部更暗或更亮),那么就认定这是一个关键点。

3.尺度不变特征的检测

       为解决尺度不变性,计算机视觉界引入了尺度不变特征的概念。它的理念是,不仅在任何尺度下拍摄的物体都能检测到一致的关键点,而且每个被检测的特征点都对应一个尺度因子。理想情况下,对于两幅图像中不同尺度的同一个物体点,计算得到的两个尺度因子之间的比率应该等于图像尺度的比率。近几年,人们提出了多种尺度不变特征,SURF 特征,它的全称为加速稳健特征(Speeded Up Robust Feature)

       SURF 特征检测属于opencv_contrib 库,在编译OpenCV 时包含了附加模块才能使用

        

// 创建SURF 特征检测器对象
cv::Ptr<cv::xfeatures2d::SurfFeatureDetector> ptrSURF =
cv::xfeatures2d::SurfFeatureDetector::create(2000.0);
// 检测关键点
ptrSURF->detect(image, keypoints);
为了画出这些特征,再次使用OpenCV的cv::drawKeypoints 函数,但是要采用cv::Draw
MatchesFlags::DRAW_RICH_KEYPOINTS 标志以显示相关的尺度因子:
// 画出关键点,包括尺度和方向信息
cv::drawKeypoints(image, // 原始图像
keypoints, // 关键点的向量
featureImage, // 结果图像
cv::Scalar(255,255,255), // 点的颜色
cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);

     如果在不同的尺度内用高斯滤波器计算指定像素的拉普拉斯算子,会得到不同的数值。观察滤波器对不同尺度因子的响应规律,所得曲线最终在给定的σ 值处达到最大值。对于以不同尺度拍摄的两幅图像的同一个物体,对应的两个σ 值的比率等于拍摄两幅图像的尺度的比率。这一重要观察是尺度不变特征提取过程的核心。也就是说,为了检测尺度不变特征,需要在图像空间(图像中)和尺度空间(通过在不同尺度下应用导数滤波器得到)分别计算局部最大值。

4.多尺度FAST 特征的检测

  BRISK(Binary Robust Invariant Scalable Keypoints,二元稳健恒定可扩展关键点)检测法,它基于上一节介绍的FAST 特征检测法,另一种检测方法ORB(Oriented FAST and Rotated BRIEF,定向FAST 和旋转BRIEF)。在需要进行快速可靠的图像匹配时,这两种特征点检测法是非常优秀的解决方案。

    BRISK 不仅是一个特征点检测器,它还包含了描述每个被检测关键点的邻域的过程,为了在不同尺度下检测兴趣点,该算法首先通过两个下采样过程构建一个图像金字塔。第一个过程从原始图像尺寸开始,然后每一图层(八度)减少一半。第二个过程先将原始图像的尺寸除以1.5 得到第一幅图像,然后在这幅图像的基础上每一层减少一半,两个过程产生的图层交替在一起。然后在该金字塔的所有图像上应用FAST 特征检测器,提取关键点的条件与SIFT 算法类似。首先,将一个像素与相邻的八个像素之一进行强度值的比较,只有是局部最大值的像素才可能成为关键点。这个条件满足后,比较这个点与上下两层的相邻像素的评分;如果它的评分在尺度上也更高,那么就认为它是一个兴趣点。

// 构造BRISK 特征检测器对象
cv::Ptr<cv::BRISK> ptrBRISK = cv::BRISK::create();
// 检测关键点
ptrBRISK->detect(image, keypoints);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2327925.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于微信小程序的医院挂号预约系统设计与实现

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本微信小程序医院挂号预约系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大…

如何保障话费api接口的稳定性?

保障话费接口的稳定性是确保服务高效运行的关键。以下是基于最新信息的建议&#xff1a; 1. 选择可靠的API服务提供商 信誉和稳定性&#xff1a;选择有良好声誉和稳定服务记录的提供商&#xff0c;查看其服务水平协议&#xff08;SLA&#xff09;以确保高可用性。技术支持&…

video标签播放mp4格式视频只有声音没有图像的问题

video标签播放mp4格式视频只有声音没有图像的问题 这是由于视频格式是hevc(H265)编码的&#xff0c;这种编码格式视频video播放有问题主要是由于以下两种原因导致的&#xff1a; 1、浏览器没有开启硬加速模式&#xff1a; 开启方法&#xff08;以谷歌浏览器为例&#xff09;&a…

解决docker部署的容器第二天访问报错139的问题

前阵子我部署项目&#xff0c;把数据库放宿主机上&#xff0c;结果电脑一重启&#xff0c;Docker 直接把数据库删了个精光&#xff01;我当时的表情 be like &#x1f631;&#xff1a;"我的数据呢&#xff1f;&#xff1f;&#xff1f;" 连备份都没来得及做&#xf…

如何对接银行卡二要素核验接口?

银行卡二要素核验接口是一种通过API&#xff08;应用程序编程接口&#xff09;实现对用户提供的银行卡信息进行基本身份验证的技术服务&#xff0c;主要用于核验银行卡号与持卡人姓名是否一致&#xff0c;从而确认用户身份的真实性和操作合法性。 银行卡二要素核验接口通过调用…

深度学习——深入解读各种卷积的应用场景优劣势与实现细节

前言 卷积操作在深度学习领域中占据着核心地位&#xff0c;其在多种神经网络架构中发挥着关键作用。然而&#xff0c;卷积的种类繁多&#xff0c;每种卷积都有其独特的定义、应用场景和优势。 对于那些对深度学习中不同卷积类型&#xff08;例如 2D 卷积、3D 卷积、11 卷积、转…

Pyinstaller 打包flask_socketio为exe程序后出现:ValueError: Invalid async_mode specified

Pyinstaller 打包flask_socketio为exe程序后出现&#xff1a;ValueError: Invalid async_mode specified 一、详细描述问题描述 Traceback (most recent call last): File "app_3.py", line 22, in <module> File "flask_socketio\__init__.py"…

chromium魔改——navigator.webdriver 检测

chromium源码官网 https://source.chromium.org/chromium/chromium/src 说下修改的chromium源码思路&#xff1a; 首先在修改源码过检测之前&#xff0c;我们要知道它是怎么检测的&#xff0c;找到他通过哪个JS的API来做的检测&#xff0c;只有知道了如何检测&#xff0c;我们…

【力扣hot100题】(048)二叉树的最近公共祖先

依旧只会用递归栈。 栈记录当前遍历的节点&#xff0c;如果有一个节点已经被找到&#xff0c;则不往栈中添加新节点&#xff0c;并且每次回溯删除栈顶节点&#xff0c;每次回溯判断另一个节点有没有在栈顶节点的右边。 /*** Definition for a binary tree node.* struct Tree…

爬虫:请求头,requests库基本使用

请求方式&#xff1a;get(向服务器要资源)和post(提交资源) user-agent&#xff1a;模拟正常用户的一种方式 cookie&#xff1a;登陆保持 referer&#xff1a;表示当前这一次请求是由哪个请求过来的 抓取数据包得到的内容才是判断依据elements中的源码是渲染之后的不能作为…

[物联网iot]对比WIFI、MQTT、TCP、UDP通信协议

第一步&#xff1a;先理解最基础的关系&#xff08;类比快递&#xff09; 假设你要给朋友寄快递&#xff1a; Wi-Fi&#xff1a;相当于“公路和卡车”&#xff0c;负责把包裹从你家运到快递站。 TCP/UDP&#xff1a;相当于“快递公司的运输规则”。 TCP&#xff1a;顺丰快递&…

CSDN自动设置vip文章的解除办法

文章目录 CSDN真的会将“全部可见”文章偷偷自动设置为“VIP可读”最省事的途径&#xff1a;联系客服&#xff0c;预计1-2个工作日可以取消新版“内容管理”内手工操作 CSDN真的会将“全部可见”文章偷偷自动设置为“VIP可读” 今天无意中发现之前一些公开的文章变为仅VIP可读…

P4305 [JLOI2011] 不重复数字

使用stl中的动态数组和unordered_map #include<iostream> #include<iostream> #include<vector> #include<unordered_map> using namespace std; int t; int main(){cin>>t;while(t--){//每次处理一组数据.int n;cin>>n;vector<int&…

Joomla教程—Joomla 模块管理与Joomla 模块类型介绍

Joomla 模块管理 原文&#xff1a;Joomla 模块管理_w3cschool 模块管理&#xff0c;从文字意面上理解&#xff0c;可想而知&#xff0c;就是管理网站中所有的模块&#xff0c;模块的增、删、改、查都会在模块管理进行。这一节将简单介绍joomla后台的模块管理 1、模块管理的界…

安装gvm后普通用户模式下无法使用cd切换目录

安装gvm后普通用户模式下无法使用cd切换目录 今天装完gvm后发现无法使用cd来切换目录了。。。 1.使用type cd命令发现cd命令被定义为了函数 usrusr-pc:~$ type cd cd 是函数 cd () { if __gvm_is_function __gvm_oldcd; then__gvm_oldcd $*;fi;local dot_go_version dot_go_…

Vue中虚拟DOM创建到挂载的过程

Vue中虚拟DOM创建到挂载的过程 流程概括下来基本上就是&#xff1a;模板 → AST → render函数 → 虚拟节点 → 挂载 AST&#xff1a;抽象语法树&#xff0c;它用于记录原始代码中所有的关键信息&#xff0c;根据AST可以将代码从一种语言转化为另一种语言。 虚拟DOM创建到挂载…

选择网上购物系统要看几方面?

随着电子商务的迅猛发展&#xff0c;选择一个合适的网上购物系统已成为许多企业成功的关键。无论是初创企业还是已经成熟的公司&#xff0c;选择合适的购物系统都能显著提升用户体验、提高销售额和优化运营效率。本文将从几个重要方面探讨选择网上购物系统时需要考虑的关键因素…

定制开发开源AI智能名片S2B2C商城小程序:技术赋能商业价值实现路径研究

摘要 在数字经济与社交新零售蓬勃发展的背景下&#xff0c;本研究聚焦"定制开发开源AI智能名片S2B2C商城小程序"这一创新技术解决方案&#xff0c;通过解析其技术架构、功能模块及业务应用场景&#xff0c;探讨其如何支持企业目标达成、补充技术栈短板、实现数据整合…

美关税加征下,Odoo免费开源ERP如何助企业破局?

近期&#xff0c;美国特朗普政府推行的关税政策对全球供应链和进出口企业造成巨大冲击&#xff0c;尤其是依赖中美贸易的企业面临成本激增、利润压缩和合规风险。在此背景下&#xff0c;如何通过数字化转型优化管理效率、降低运营成本成为企业生存的关键。本文以免费开源ERP系统…

Unity中 JobSystem使用整理

Unity 的JobSystem允许创建多线程代码&#xff0c;以便应用程序可以使用所有可用的 CPU 内核来执行代码&#xff0c;这提供了更高的性能&#xff0c;因为您的应用程序可以更高效地使用运行它的所有 CPU 内核的容量&#xff0c;而不是在一个 CPU 内核上运行所有代码。 可以单独使…