草庐IT

OpenCV实战——多尺度FAST特征检测

盼小辉丶 2023-06-10 原文

OpenCV实战——多尺度FAST特征检测

0. 前言

FAST 是用于快速检测图像中关键点的方法,而 SURF 和 SIFT 算法的设计重点是尺度不变性。为了同时实现快速检测和尺度不变性,OpenCV 中引入了新的兴趣点检测器,包括 BRISK (Binary Robust Invariant Scalable Keypoints) 检测器(基于 FAST 特征检测器)和 ORB (Oriented FAST and Rotated BRIEF) 检测器。当需要快速可靠的图像匹配时,可以使用特征点检测器 BRISKORB

1. BRISK 特征检测器

可以利用 cv::FeatureDetector 抽象类使用 BRISK 检测关键点。

1.1 BRISK 检测关键点

(1) 首先创建一个检测器的实例,然后在输入图片上调用 detect 方法:

cv::Ptr<cv::xfeatures2d::SiftFeatureDetector> ptrSIFT = new cv::xfeatures2d::SiftFeatureDetector();
ptrSIFT->detect(image, keypoints);

在图像中检测到的多尺度关键点如下图所示:


BRISK 不仅是一个特征点检测器,而且该方法还包括每个检测到的关键点的邻域,接下来,我们将介绍如何使用 BRISK 执行多尺度关键点的快速检测。

1.2 多尺度关键点快速检测

为了检测不同尺度的兴趣点,BRISK 方法首先通过两个下采样过程构建图像金字塔,第一个过程从原始图像大小开始,并在每一层(或 octave) 上将其缩小一半,中间层是通过将原始图像向下采样 1.5 倍来创建的,在这些中间层中,原始图像通过连续的 1/2 采样生成附加层:

然后将 FAST 特征检测器应用于该金字塔的所有图像,关键点提取与 SIFT 使用类似的标准。首先,当将其强度与其八个空间邻居之一进行比较时,可接受的兴趣点必须是局部最大值,然后将该点与上下层中相邻点的分数进行比较,如果它的分数同样更高,那么它就被认为是一个兴趣点,BRISK 的关键在于金字塔的不同层具有不同的分辨率。
该方法需要在尺度和空间上进行插值,以便精确定位每个关键点,插值基于 FAST 关键点分数。在空间中,插值是在 3x3 邻域上执行的,在尺度上,它是通过沿着尺度轴拟合一个一维抛物线通过当前点及其上下两个相邻的局部关键点来计算的;上图中说明了如何进行这种关键点定位。因此,即使在离散图像尺度上执行 FAST 关键点检测,与每个关键点关联的结果检测尺度也是一个连续值。
cv::BRISK 类提供了两个可选参数来控制关键点的检测,第一个参数是 FAST 关键点的阈值,第二个参数是图像金字塔中将生成的 octave 数:

cv::Ptr<cv::BRISK> ptrBRISK = cv::BRISK::create(
                60,     // BRISK 关键点可接受的阈值
                5);     // octave 数量
ptrBRISK->detect(image, keypoints);

OpenCV 中,除了 BRISK 可以作为多尺度快速检测器外,ORB 特征检测器也可以高效的执行关键点检测。

2. ORB 特征检测算法

ORB (Oriented FAST and Rotated BRIEF) 的第一部分指的是关键点检测部分,而第二部分指的是 ORB 提出的描述符,本节中,我们将专注于检测方法。
BRISK 一样,ORB 首先创建一个由多个层组成图像金字塔,其中每一层都是由前一层按特定比例因子(由 cv::ORB 函数中的参数)下采样获得。然后接受最强的 N 个关键点,其中关键点分数由 Harris 角度度量定义。
ORB 检测器的方向与每个检测到的兴趣点相关联,这些信息有助于对齐在不同图像中检测到的关键点的描述符,ORB 中使用关键点周围圆形邻域的质心方向。根据定义,由于 FAST 关键点始终具有偏心的质心,因此连接中心点和质心的直线的角度可以很好的定义质心方向。ORB 特征检测调用方法如下:

cv::Ptr<cv::ORB> ptrORB = cv::ORB::create(
                75,     // 关键点总数
                1.2,    // 层间缩放因子
                8);     // 金字塔中层数
ptrORB->detect(image, keypoints);

得到的结果如下所示:

如上图所示,由于关键点是在每个金字塔层上独立检测的,因此检测器可以在不同尺度上重复检测相同的特征点。

3. 完整代码

头文件 (harrisDetector.h) 完整代码参考 Harris 特征点检测一节,主函数文件 (briskCorners.cpp) 完整代码如下所示:

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/xfeatures2d.hpp>

#include "harrisDetector.h"

int main() {
    // Harris
    cv::Mat image = cv::imread("1.png", 0);
    if (!image.data) return 0;
    std::vector<cv::KeyPoint> keypoints;
    cv::Mat featureImage;
    // BRISK
    cv::transpose(image, image);
    cv::flip(image, image, 0);
    keypoints.clear();
    cv::Ptr<cv::BRISK> ptrBRISK = cv::BRISK::create(
                    60,     // BRISK 关键点可接受的阈值
                    5);     // octave 数量
    ptrBRISK->detect(image, keypoints);
    cv::drawKeypoints(image, keypoints, featureImage, cv::Scalar(255, 255, 255), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
    cv::namedWindow("BRISK");
    cv::imshow("BRISK", featureImage);
    std::cout << "Number of BRISK keypoints: " << keypoints.size() << std::endl;
    // ORB
    image = cv::imread("1.png", 0);
    cv::transpose(image, image);
    cv::flip(image, image, 0);
    keypoints.clear();
    cv::Ptr<cv::ORB> ptrORB = cv::ORB::create(
                    75,     // 关键点总数
                    1.2,    // 层间缩放因子
                    8);     // 金字塔中层数
    ptrORB->detect(image, keypoints);
    cv::drawKeypoints(image, keypoints, featureImage, cv::Scalar(255, 255, 255), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
    cv::namedWindow("ORB");
    cv::imshow("ORB", featureImage);
    std::cout << "Number of ORB keypoints: " << keypoints.size() << std::endl;
    cv::waitKey();
    return 0;
}

相关链接

OpenCV实战(1)——OpenCV与图像处理基础
OpenCV实战(2)——OpenCV核心数据结构
OpenCV实战(3)——图像感兴趣区域
OpenCV实战(4)——像素操作
OpenCV实战(5)——图像运算详解
OpenCV实战(6)——OpenCV策略设计模式
OpenCV实战(7)——OpenCV色彩空间转换
OpenCV实战(8)——直方图详解
OpenCV实战(9)——基于反向投影直方图检测图像内容
OpenCV实战(10)——积分图像详解
OpenCV实战(11)——形态学变换详解
OpenCV实战(12)——图像滤波详解
OpenCV实战(13)——高通滤波器及其应用
OpenCV实战(14)——图像线条提取
OpenCV实战(15)——轮廓检测详解
OpenCV实战(16)——角点检测详解
OpenCV实战(17)——FAST特征点检测

有关OpenCV实战——多尺度FAST特征检测的更多相关文章

  1. ruby - Fast-stemmer 安装问题 - 2

    由于fast-stemmer的问题,我很难安装我想要的任何ruby​​gem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=

  2. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  3. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  4. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

    之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

  5. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  6. ruby - cucumber 特征和步骤定义 - 2

    我是Cucumber测试的新手。我创建了两个特征文件:events.featurepartner.feature并将我的步骤定义放在step_definitions文件夹中:./step_definitions/events.rbpartner.rbCucumber似乎在所有.rb文件中查找步骤信息。有没有办法限制该功能查看特定的步骤定义文件?我之所以要这样做,是因为即使我使用了--guess标志,我也会遇到不明确的匹配错误。我之所以要这样做,有以下几个原因。我正在测试CMS,并希望在不同的功能中测试每种不同的内容类型(事件和合作伙伴)。事件.特征Feature:AddpartnerA

  7. ruby - 检测由 RSpec、Ruby 运行的代码 - 2

    我想知道我的代码是否在rspec下运行。这可能吗?原因是我正在加载一些错误记录器,这些记录器在测试期间会被故意错误(expect{x}.toraise_error)弄得乱七八糟。我查看了我的ENV变量,没有(明显的)测试环境变量的迹象。 最佳答案 在spec_helper.rb的开头添加:ENV['RACK_ENV']='test'现在您可以在代码中检查RACK_ENV是否经过测试。 关于ruby-检测由RSpec、Ruby运行的代码,我们在StackOverflow上找到一个类似的问题

  8. ruby - 使用 Ruby Daemons gem 检测停止 - 2

    我正在使用rubydaemongem。想知道如何向停止操作添加一些额外的步骤?希望我能检测到停止被调用,并向其添加一些额外的代码。任何人都知道我如何才能做到这一点? 最佳答案 查看守护程序gem代码,它似乎没有用于此目的的明显扩展点。但是,我想知道(在守护进程中)您是否可以捕获守护进程在发生“停止”时发送的KILL/TERM信号...?trap("TERM")do#executeyourextracodehereend或者你可以安装一个at_exit钩子(Hook):-at_exitdo#executeyourextracodehe

  9. ruby-on-rails - 特征未注册 : attribute name - 2

    完成这个有困难。我正在使用seed.rb+factory_girl来使用rakedb:seed填充数据库。(我知道固定装置存在,但我想以这种方式完成,这只是一个示例,数据库将填充复杂的关联对象。)我的种子.rb:require'factory_girl_rails'["QM","CDC","SI","QS"].eachdo|n|FactoryGirl.create(:grau,nome:n)end还有我的/factories/graus.rbFactoryGirl.definedofactory:graudonomeendend但是当我运行时:rakedb:seed我得到:rakeab

  10. ruby - Ruby 脚本如何检测到它正在 irb 中运行? - 2

    我有一个定义类的Ruby脚本。我希望脚本执行语句BoolParser.generate:file_base=>'bool_parser'仅当脚本作为可执行文件被调用时,而不是当它被irbrequire(或通过-r在命令行上传递)时。我可以用什么来包装上面的语句,以防止它在我的Ruby文件加载时执行? 最佳答案 条件$0==__FILE__...!/usr/bin/ruby1.8classBoolParserdefself.generate(args)p['BoolParser.generate',args]endendif$0==_

随机推荐