OpenCV中常用特征提取算法(SURF、ORB、SIFT和AKAZE)用法示例(C++和Python)

OpenCV 中提供了多种常用的特征提取算法,广泛应用于图像匹配、拼接、SLAM、物体识别等任务。以下是 OpenCV 中几个主流特征提取算法的 用法总结与代码示例,涵盖 C++ 和 Python 两个版本。


常用特征提取算法列表

算法特点是否需额外模块
SIFT(尺度不变特征)稳定性强、可旋转缩放xfeatures2d 模块
SURF(加速稳健特征)快速但专利保护xfeatures2d 模块
ORB(Oriented FAST + BRIEF)免费、高速OpenCV 主模块
AKAZE适用于非线性尺度空间OpenCV 主模块
BRISK二进制描述子、适用于实时应用OpenCV 主模块

示例一:ORB 特征提取与匹配

Python 版:

import cv2# 加载图像
img1 = cv2.imread("image1.jpg", cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread("image2.jpg", cv2.IMREAD_GRAYSCALE)# 创建 ORB 检测器
orb = cv2.ORB_create()# 检测关键点和计算描述子
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)# 创建匹配器
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1, des2)# 排序并绘制前 20 个匹配点
matches = sorted(matches, key=lambda x: x.distance)
matched_img = cv2.drawMatches(img1, kp1, img2, kp2, matches[:20], None, flags=2)cv2.imshow("ORB Matches", matched_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

C++ 版:

#include <opencv2/opencv.hpp>
#include <opencv2/features2d.hpp>int main()
{cv::Mat img1 = cv::imread("image1.jpg", cv::IMREAD_GRAYSCALE);cv::Mat img2 = cv::imread("image2.jpg", cv::IMREAD_GRAYSCALE);cv::Ptr<cv::ORB> orb = cv::ORB::create();std::vector<cv::KeyPoint> kp1, kp2;cv::Mat des1, des2;orb->detectAndCompute(img1, cv::noArray(), kp1, des1);orb->detectAndCompute(img2, cv::noArray(), kp2, des2);cv::BFMatcher matcher(cv::NORM_HAMMING, true);std::vector<cv::DMatch> matches;matcher.match(des1, des2, matches);std::sort(matches.begin(), matches.end(),[](const cv::DMatch& m1, const cv::DMatch& m2) {return m1.distance < m2.distance;});cv::Mat img_matches;cv::drawMatches(img1, kp1, img2, kp2, matches, img_matches);cv::imshow("ORB Matches", img_matches);cv::waitKey(0);return 0;
}

示例二:SIFT 特征提取(需额外模块)

Python 版:

import cv2sift = cv2.SIFT_create()
img = cv2.imread("image.jpg", cv2.IMREAD_GRAYSCALE)
kp, des = sift.detectAndCompute(img, None)img_kp = cv2.drawKeypoints(img, kp, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow("SIFT Features", img_kp)
cv2.waitKey(0)

注意:SIFT 在 OpenCV 4.x 中已开放为免费使用,需 pip install opencv-contrib-python


C++ 版:

#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>int main()
{cv::Mat img = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);cv::Ptr<cv::SIFT> sift = cv::SIFT::create();std::vector<cv::KeyPoint> keypoints;cv::Mat descriptors;sift->detectAndCompute(img, cv::noArray(), keypoints, descriptors);cv::Mat output;cv::drawKeypoints(img, keypoints, output, cv::Scalar::all(-1), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);cv::imshow("SIFT", output);cv::waitKey(0);return 0;
}

示例三:AKAZE 特征提取

Python 版:

import cv2akaze = cv2.AKAZE_create()
img = cv2.imread("image.jpg", cv2.IMREAD_GRAYSCALE)
kp, des = akaze.detectAndCompute(img, None)img_kp = cv2.drawKeypoints(img, kp, None, color=(0,255,0))
cv2.imshow("AKAZE", img_kp)
cv2.waitKey(0)

C++ 版:

#include <opencv2/opencv.hpp>int main()
{cv::Mat img = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);cv::Ptr<cv::AKAZE> akaze = cv::AKAZE::create();std::vector<cv::KeyPoint> keypoints;cv::Mat descriptors;akaze->detectAndCompute(img, cv::noArray(), keypoints, descriptors);cv::Mat output;cv::drawKeypoints(img, keypoints, output);cv::imshow("AKAZE", output);cv::waitKey(0);return 0;
}

示例四:SURF 特征提取

小提示

SURF 属于专利算法(由 Hessian Matrix 加速构建特征),因此默认在 opencv-python不可用,需要使用 opencv-contrib 版本:

  • Python: pip install opencv-contrib-python
  • C++: 编译 OpenCV 时需启用 opencv_contrib,并启用 xfeatures2d 模块。

Python 示例

import cv2
import numpy as np# 读取图像
img = cv2.imread("image.jpg", cv2.IMREAD_GRAYSCALE)# 创建 SURF 对象(阈值越高,检测特征点越少)
surf = cv2.xfeatures2d.SURF_create(hessianThreshold=400)# 检测并计算特征点和描述子
keypoints, descriptors = surf.detectAndCompute(img, None)# 绘制关键点
img_kp = cv2.drawKeypoints(img, keypoints, None, (0,255,0), flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)cv2.imshow("SURF Features", img_kp)
cv2.waitKey(0)
cv2.destroyAllWindows()

C++ 示例

#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>int main()
{cv::Mat img = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);if (img.empty()) {std::cerr << "Cannot load image!" << std::endl;return -1;}// 创建 SURF 检测器cv::Ptr<cv::xfeatures2d::SURF> surf = cv::xfeatures2d::SURF::create(400); // Hessian thresholdstd::vector<cv::KeyPoint> keypoints;cv::Mat descriptors;surf->detectAndCompute(img, cv::noArray(), keypoints, descriptors);cv::Mat output;cv::drawKeypoints(img, keypoints, output, cv::Scalar::all(-1), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);cv::imshow("SURF", output);cv::waitKey(0);return 0;
}

特征提取算法比较总结

算法是否开源描述子类型匹配类型特点
SIFT浮点(128维)L2(欧氏距离)稳定性好,适合图像拼接
SURF❌(专利)浮点L2快速但已过时
ORB二值(256位)Hamming(汉明)快速,适合实时系统
AKAZE二值或浮点Hamming/L2稳定性与速度兼顾
BRISK二值Hamming实时性强

小结

  • 推荐优先使用 ORBAKAZE(开源 + 高速);
  • 高精度图像处理可考虑 SIFT
  • 所有算法都可配合 BFMatcherFLANN 进行匹配;
  • 选择依据:速度要求匹配精度是否支持缩放旋转

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

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

相关文章

复杂度+包装类型+泛型

什么是集合框架什么是数据结构什么是算法时间复杂度与空间复杂度的概念时间复杂度的表达方式时间复杂度的大 O 的渐近表示法时间复杂度函数的大小排序包装类和泛型基本数据类型和对应的包装类型包装类型出现的原因什么叫做装箱&#xff08;装包&#xff09;和拆箱&#xff08;拆…

硬件设计学习DAY15——自举电容:MOSFET高端驱动的核心奥秘

每日更新教程&#xff0c;评论区答疑解惑&#xff0c;小白也能变大神&#xff01;" 目录 一.自举电容 1.自举电容的作用 2.自举电路原理 3.工作过程分析 4.实际应用中的问题 5.关键要点 二.自举电容实现MOSFET高端驱动 2.1MOSFET半桥高端驱动的基本原理 2.2自举电…

【SpringAI实战】实现仿DeepSeek页面对话机器人

一、实现效果 二、代码实现 2.1 后端代码 2.2 前端代码 一、实现效果 可以保存聊天记录与会话记录 二、代码实现 2.1 后端代码 pom.xml <!-- 继承Spring Boot父POM&#xff0c;提供默认依赖管理 --><parent><groupId>org.springframework.boot</grou…

RedisJSON 指令精讲JSON.STRLEN 高效统计字符串长度

1 场景与价值 在日志累加、指标采集、消息追踪等场景中&#xff0c;我们常需快速判断某个字符串字段“到底有多长”&#xff0c;以便&#xff1a; 阻止过大日志&#xff1a;若长度超限则截断或归档&#xff1b;动态分桶&#xff1a;按长度选择不同存储策略&#xff1b;性能监控…

大数据量查询计算引发数据库CPU告警问题复盘

大数据量查询计算引发数据库CPU告警问题复盘一、背景二、根因分析三、解决方案方案1&#xff1a;多线程缓存方案2&#xff1a;利用中间表缓存四、总结一、背景 2025年7月份某天&#xff0c;CDP系统每天不定时推送我们的Portal服务&#xff0c;生产环境运营看板会展示统计数据&…

2025最新版虚幻引擎5(UE5)C++入门教程:前言——你的随身教程和学习笔记

大家好&#xff0c;我是开发游戏的老王&#xff0c;一名高校教师&#xff0c;我主讲游戏开发已有十余年时间&#xff0c;通过我的博客大家应该可以了解我所涉猎的游戏技术范畴非常广泛&#xff0c;除了Unreal,Unity,Godot等主流游戏引擎&#xff0c;还包括Blender、Houdini、3D…

(3)重定向 | 时间相关指令 | 文件查找 | 打包与压缩

Ⅰ . 初始重定向01 输出重定向 >在上一节中我们为了方便讲解 head 和 tail 指令&#xff0c;我们用到了 > 去生成了一千行文本。通过 > 将生成的一千行文本写入到了 large.txt 中……我们现在来正式介绍一下&#xff1a;$ echo "内容" > [目标] 本来应…

DTH11测量温湿度学习(第十一天)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-削好皮的Pineapple! &#x1f468;‍&#x1f4bb; hello 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 削好皮的Pineapple! 原创 &#x1f468;‍&#x1f4…

Go语言初识--标识符 可见性

Go语言初识–标识符 可见性 和C语言相似&#xff0c;go语言的基本组成有&#xff1a; 包声明&#xff0c;编写源文件时&#xff0c;必须在非注释的第一行指明这个文件属于哪个包&#xff0c;如package main。引入包&#xff0c;其实就是告诉Go 编译器这个程序需要使用的包&…

Python实例之画小猪佩奇

效果图&#xff1a;python代码以及解释&#xff0c;没有运用模块。 """ 绘制小猪佩奇 """ from turtle import *def nose(x,y):"""画鼻子"""penup()# 将海龟移动到指定的坐标goto(x,y)pendown()# 设置海龟的方向&…

Unity笔记——事件中心

事件中心是什么事件中心是 Unity 游戏开发中常用的架构设计&#xff0c;它基于观察者模式 或 发布-订阅模式&#xff0c;通过委托和事件构建的一种消息管理系统。主要用于降低代码耦合度&#xff0c;实现模块间的松耦合通信的消息处理系统能大幅提升代码的可维护性和扩展性&…

Java: 反射机制的 ParameterizedType(参数化类型)

在 Java 中&#xff0c;ParameterizedType 是 java.lang.reflect 包下的一个接口&#xff0c;属于反射 API 的一部分&#xff0c;主要用于表示参数化类型&#xff08;即带有类型参数的泛型类型&#xff09;。它是 Java 反射机制中处理泛型类型信息的关键接口之一。 一、什么是参…

OkHttp 与 Retrofit 完美结合:打造高效的 Android 网络请求

前言在现代 Android 开发中&#xff0c;网络请求是几乎每个应用都必不可少的功能。OkHttp 和 Retrofit 作为当前最流行的网络请求库组合&#xff0c;为开发者提供了简洁高效的解决方案。本文将详细介绍如何将这两者结合使用&#xff0c;充分发挥它们的优势。一、OkHttp 和 Retr…

系统辨识建模

系统辨识建模 一、系统辨识建模的作用 1. 建立真实物理系统的数学模型 2. 为后续控制器/强化学习算法提供仿真环境 3. 提高控制精度和安全性 二、本文的系统辨识是怎么做的 1. 实验采集 2. 数学建模 3. 在控制系统中的作用 三、实际用法流程(简化版) 1. 系统辨识阶段 2. 强化…

Android开发:Java与Kotlin深度对比

1. 语言特性与现代性 Java (特别是 Android 主要使用的 Java 8 及之前版本): 相对冗长&#xff1a; 需要编写更多的样板代码&#xff08;如 getter/setter、findViewById 的显式类型转换、匿名内部类等&#xff09;。空指针异常 (NPE)&#xff1a; 类型系统默认允许 null&#…

米家打印机驱动:Wi-Fi 无线打印丝滑顺畅不卡顿,从此告别对打印机干瞪眼

各位小米家居控们&#xff0c;你们有没有过这种经历&#xff0c;新买的打印机回家&#xff0c;结果电脑跟它像俩傲娇的小情侣&#xff0c;死活不搭话&#xff1f;急得你想当场表演一个“打印机抱头痛哭”&#xff1f;别急&#xff0c;今天就给你们安利个神队友——米家打印机驱…

日语学习-日语知识点小记-构建基础-JLPT-N3阶段(7):自動詞 & 他動詞

日语学习-日语知识点小记-构建基础-JLPT-N3阶段&#xff08;7&#xff09;&#xff1a;自動詞 &#xff06; 他動詞1、前言&#xff08;1&#xff09;情况说明&#xff08;2&#xff09;工程师的信仰2、知识点&#xff08;&#xff11;&#xff09;自動詞 &#xff06; 他動…

深入理解设计模式:访问者模式详解

在软件开发中&#xff0c;我们经常会遇到需要对一个复杂对象结构进行操作的情况。随着需求的不断变化&#xff0c;我们可能需要在这个对象结构上添加各种新的操作。如果直接在对象结构中添加这些操作&#xff0c;会导致类的职责过重&#xff0c;且每次添加新操作都需要修改原有…

Linux timerfd 定时器封装

使用 timerfd epoll() 实现&#xff0c;简洁精确。没定义 MU_ERROR 宏的话替换为 printf 即可。mu_timer.h:#ifndef _MU_TIMER_H_ #define _MU_TIMER_H_#ifdef __cplusplus extern "C" { #endif#include <stdint.h> #include <time.h> #include <pth…

【样式效果】Vue3实现仿制iOS按钮动态效果

iOS开关效果定义变量&#xff1a; <style scoped lang"scss">.layout {// 按钮宽度$button-width: 500px;// 按钮高度$button-height: 250px;// 按钮里面圆形直径$circle-diameter: 200px;// 按钮背景与里面圆形间距$button-circle-offset:calc(($button-he…