特征提取是计算机视觉的核心技术,通过识别图像中具有代表性的关键点及其描述信息,实现图像匹配、对象识别、姿态估计等高级任务。本章将系统讲解从基础的图像金字塔、角点检测,到复杂的 ORB 和 SIFT 特征提取与匹配,最终实现基于特征的对象检测完整流程。

一、图像金字塔

图像金字塔是多尺度表示图像的有效方法,通过构建不同分辨率的图像集合,实现多尺度特征提取。

1.1 高斯金字塔

高斯金字塔通过下采样(缩小)构建,每一层都是对上层图像进行高斯模糊后再隔点采样得到。

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;// 构建高斯金字塔
vector<Mat> buildGaussianPyramid(const Mat& img, int levels) {vector<Mat> pyramid;pyramid.push_back(img.clone());  // 第0层(原始图像)Mat current = img;for (int i = 1; i < levels; ++i) {Mat down;// 高斯模糊并下采样(尺寸减半)pyrDown(current, down);pyramid.push_back(down);current = down;}return pyramid;
}// 显示高斯金字塔
void showGaussianPyramid(const vector<Mat>& pyramid) {// 创建一个大图像拼接所有金字塔层int totalHeight = 0;int maxWidth = 0;for (const auto& layer : pyramid) {totalHeight += layer.rows;maxWidth = max(maxWidth, layer.cols);}Mat display(totalHeight, maxWidth, CV_8UC3, Scalar(0, 0, 0));int y = 0;for (size_t i = 0; i < pyramid.size(); ++i) {const Mat& layer = pyramid[i];// 将当前层复制到显示图像layer.copyTo(display(Rect(0, y, layer.cols, layer.rows)));// 显示层索引string text = "Level " + to_string(i);putText(display, text, Point(10, y + 30), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 255, 0), 2);y += layer.rows;}imshow("高斯金字塔", display);
}

1.2 拉普拉斯金字塔

拉普拉斯金字塔通过高斯金字塔各层与上层上采样后的差值构建,用于表示图像的细节信息。

// 构建拉普拉斯金字塔
vector<Mat> buildLaplacianPyramid(const vector<Mat>& gaussianPyramid) {vector<Mat> laplacianPyramid;for (size_t i = 0; i < gaussianPyramid.size() - 1; ++i) {Mat up;// 上采样高斯金字塔上层pyrUp(gaussianPyramid[i + 1], up, gaussianPyramid[i].size());// 当前层减去上采样结果得到拉普拉斯层Mat laplacian = gaussianPyramid[i] - up;laplacianPyramid.push_back(laplacian);}// 最后一层为高斯金字塔的顶层laplacianPyramid.push_back(gaussianPyramid.back().clone());return laplacianPyramid;
}// 从拉普拉斯金字塔重建图像
Mat reconstructFromLaplacian(const vector<Mat>& laplacianPyramid) {Mat current = laplacianPyramid.back();for (int i = laplacianPyramid.size() - 2; i >= 0; --i) {Mat up;pyrUp(current, up, laplacianPyramid[i].size());current = up + laplacianPyramid[i];}return current;
}

1.3 图像金字塔应用

// 多尺度特征检测示例
void multiScaleFeatureDetection(const Mat& img) {// 构建3层高斯金字塔vector<Mat> gaussian = buildGaussianPyramid(img, 3);// 在不同尺度上检测边缘vector<Mat> edges;for (const auto& layer : gaussian) {Mat gray, edge;cvtColor(layer, gray, COLOR_BGR2GRAY);Canny(gray, edge, 50, 150);// 转换为彩色以便显示Mat edgeColor;cvtColor(edge, edgeColor, COLOR_GRAY2BGR);edges.push_back(edgeColor);}// 显示结果imshow("原始图像", img);showGaussianPyramid(gaussian);// 显示多尺度边缘Mat edgeDisplay;vconcat(edges, edgeDisplay);imshow("多尺度边缘检测", edgeDisplay);
}int main() {Mat img = imread("building.jpg");if (img.empty()) {cout << "图像加载失败!" << endl;return -1;}// 高斯金字塔示例vector<Mat> gaussian = buildGaussianPyramid(img, 4);showGaussianPyramid(gaussian);// 拉普拉斯金字塔示例vector<Mat> laplacian = buildLaplacianPyramid(gaussian);// 从拉普拉斯金字塔重建图像Mat reconstructed = reconstructFromLaplacian(laplacian);imshow("原始图像", img);imshow("从拉普拉斯重建", reconstructed);// 多尺度特征检测multiScaleFeatureDetection(img);waitKey(0);destroyAllWindows();return 0;
}

图像金字塔关键应用

  • 多尺度特征检测(确保不同大小的物体都能被检测到)
  • 图像融合与拼接
  • 目标跟踪(适应目标大小变化)
  • 特征匹配(提高匹配鲁棒性)

二、角点检测

角点是图像中亮度变化剧烈的点或在两个边缘交叉处的点,是最常用的局部特征之一。

2.1 Harris 角点检测

Harris 角点检测基于图像灰度的局部变化,通过计算自相关矩阵的特征值来判断是否为角点。

// Harris角点检测
Mat detectHarrisCorners(const Mat& gray, double qualityLevel = 0.01, double k = 0.04) {Mat dst, dstNorm, dstScaled;// 检测Harris角点cornerHarris(gray, dst, 2, 3, k, BORDER_DEFAULT);// 归一化结果normalize(dst, dstNorm, 0, 255, NORM_MINMAX, CV_32FC1, Mat());convertScaleAbs(dstNorm, dstScaled);// 绘制角点Mat result = gray.clone();cvtColor(result, result, COLOR_GRAY2BGR);for (int i = 0; i < dstNorm.rows; ++i) {for (int j = 0; j < dstNorm.cols; ++j) {if ((int)dstNorm.at<float>(i, j) > qualityLevel * 255) {circle(result, Point(j, i), 5, Scalar(0, 0, 255), 2);}}}return result;
}

Harris 角点响应函数:

R = det(M) - k*(trace(M))²

其中,M是自相关矩阵,det(M)是行列式,trace(M)是迹,k是经验常数(通常取 0.04~0.06)。

  • R > 0且较大:角点
  • R ≈ 0:边缘
  • R < 0且较小:平坦区域

2.2 Shi-Tomasi 角点检测

Shi-Tomasi 角点检测是 Harris 算法的改进,使用两个特征值中的最小值作为响应函数,提高了角点检测的稳定性。

// Shi-Tomasi角点检测
Mat detectShiTomasiCorners(const Mat& gray, int maxCorners = 100, double qualityLevel = 0.01, double minDistance = 10) {vector<Point2f> corners;// 参数设置TermCriteria criteria(TermCriteria::EPS | TermCriteria::MAX_ITER, 30, 0.001);// 检测Shi-Tomasi角点goodFeaturesToTrack(gray, corners, maxCorners, qualityLevel, minDistance, Mat(), 3, false, 0.04);// 绘制角点Mat result = gray.clone();cvtColor(result, result, C

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

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

相关文章

Codeforces Round 1049 (Div. 2) D题题解记录

大致题意&#xff1a;给定nnn个区间(li,ri)(l_i,r_i)(li​,ri​)。每次选取两个尚未被标记的区间(l1,r1)(l_1,r_1)(l1​,r1​)与(l2,r2)(l_2,r_2)(l2​,r2​)&#xff0c;使得他们均被标记&#xff0c;同时可以任选x∈[l1,r1]&#xff0c;y∈[l2,r2]x\in[l_1,r_1]&#xff0c;y…

《WINDOWS 环境下32位汇编语言程序设计》第15章 注册表和INI文件

15.1 注册表和INI文件简介在一个操作系统中&#xff0c;无论是操作系统本身还是运行于其中的大部分应用程序&#xff0c;都需要使用某种方式保存配置信息。在DOS系统中&#xff0c;配置信息往往是软件的开发者根据自己的喜好用各种途径加以保存的&#xff0c;比如在磁盘上面写一…

JDK 17、OpenJDK 17、Oracle JDK 17 的说明

Java生态系统的核心概念&#xff1a;简单来说&#xff1a;JDK 17 是一个标准规范&#xff0c;定义了Java开发工具包第17个长期支持版应该包含什么功能。openjdk-17-jdk 是一个具体的实现&#xff0c;是遵循上述规范、由OpenJDK社区提供的开源软件包。下面我们通过一个表格和详细…

手写MyBatis第58弹:如何优雅输出可执行的SQL语句--深入理解MyBatis日志机制:

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

Spring Boot 监控实战:集成 Prometheus 与 Grafana,打造全方位监控体系

前言 在当今微服务架构盛行的时代&#xff0c;应用程序的监控变得尤为重要。Spring Boot 作为广泛使用的微服务框架&#xff0c;其监控需求也日益增加。Prometheus 和 Grafana 作为开源监控领域的佼佼者&#xff0c;为 Spring Boot 应用提供了强大的监控能力。本文将详细介绍如…

JS中的多线程——Web Worker

众所周知&#xff0c;JavaScript 是单线程运行的&#xff08;至于为什么是单线程可以看一下这篇文章——事件循环机制&#xff09;&#xff0c;当浏览器主线程被大量计算任务阻塞时&#xff0c;页面就会出现明显的卡顿现象。Web Worker 提供了在独立线程中运行 JavaScript 的能…

【SQL注入】延时盲注

sleep(n)​​: 核心延时函数。使数据库程序暂停 n秒。​​if(condition, true_expr, false_expr)​​: 条件判断函数。如果 condition为真&#xff0c;执行 true_expr&#xff0c;否则执行 false_expr。​​用于将延时与判断条件绑定​​。​​mid(a, b, c)​​: 字符串截取函数…

IntelliJ IDEA 2025.1 Java Stream Debugger 快速使用指南

1. 功能概览 Java Stream Debugger 提供 Trace Current Stream Chain 功能&#xff0c;用来在调试时分析和可视化 Stream 操作链。 主要用途&#xff1a; 在运行时查看流操作链的每一步输出找出 map/filter 等操作的问题避免手动加 peek() 打印调试2. 使用入口 在 IDEA 2025.1 …

ARM-指令集全解析:从基础到高阶应用

一、ARM 指令集体系结构版本ARM 公司定义了多个指令集版本&#xff1a;ARMv1&#xff1a;原型机 ARM1&#xff0c;没有用于商业产品。ARMv2&#xff1a;扩展 V1&#xff0c;包含 32 位乘法指令和协处理器指令。ARMv3&#xff1a;第一个微处理器 ARM6 核心&#xff0c;支持 Cach…

第3讲 机器学习入门指南

近年来&#xff0c;随着企业和个人生成的数据量呈指数级增长&#xff0c;机器学习已成为日益重要的技术领域。从自动驾驶汽车到流媒体平台的个性化推荐&#xff0c;机器学习算法已广泛应用于各个场景。让我们深入解析机器学习的核心要义。3.1 机器学习定义机器学习是人工智能的…

深入理解跳表:多层索引加速查找的经典实现

跳表&#xff08;Skip List&#xff09;是一种多层有序链表结构&#xff0c;通过引入多级索引加速查找&#xff0c;其核心设计类似于“立体高速公路系统”&#xff0c;底层是原始链表&#xff0c;上面有各种高度的"高架桥"。 高层道路跨度大&#xff0c;连接远方节点…

Flutter 视频播放器——flick_video_player 介绍与使用

在移动端应用中&#xff0c;视频播放是一个常见的功能场景&#xff0c;例如短视频、直播、课程、广告展示等。 Flutter 本身并没有直接提供视频播放器组件&#xff0c;而是依赖第三方库来实现。 今天要介绍的库是 flick_video_player&#xff0c;它基于 video_player 封装&…

编写cmakelists文件常用语句

cmake_minimum_required (VERSION 3.10) 指定最小版本project(XXXX) 指定项目名字 ---------------set(MAIN_EXEC_NAME dwarf_parser) 定义变量${ MAIN_EXEC_NAME } 变量取值set(CMAKE_CXX_STANDARD 14) 指定c14标准&#xff0c;还有11、17、20等标准…

麒麟桌面系统找不到mbr启动,并重新安装grub

根据你提供的情况,“麒麟桌面系统找不到MBR启动”,这通常是由于GRUB引导损坏、MBR记录丢失或分区表异常导致的。你可以按照以下步骤重新安装GRUB并修复MBR启动: ✅ 步骤一:准备工具 使用银河麒麟LiveCD或U盘启动盘(可用Ventoy制作); 启动电脑,选择从U盘或光盘进入Live环…

【音频字幕】构建一个离线视频字幕生成系统:使用 WhisperX 和 Faster-Whisper 的 Python 实现

一、背景介绍 对于一端没有字幕外国视频、字幕&#xff0c;在不懂外语的情况下&#xff0c;怎么获取相关内容&#xff1f;作为技术宅&#xff0c;怎么自建搭建一个语音转文字的环境当前AI技术这么发达&#xff1f; 试试 二、系统设计 音频提取(仅仅是视频需要该逻辑、本身就是音…

Linux ALSA架构:PCM_OPEN流程 (二)

一 应用端源码路径: external\tinyalsa\pcm.c external\tinyalsa\pcm_hw.cstruct pcm *pcm_open(unsigned int card, unsigned int device,unsigned int flags, struct pcm_config *config) {...pcm->ops &hw_ops;pcm->fd pcm->ops->open(card, device,…

tp5的tbmember表闭包查询 openid=‘abc‘ 并且(wx_unionid=null或者wx_unionid=‘‘)

闭包查询 tbmember表闭包查询查询 openid‘abc并且islose0并且islogout0并且&#xff08;wx_unionidnull或者wx_unionid’&#xff09; Db::table(tbmember)->where([openid>abc,islose>0,islogout>0])->where(function ($query){$query->where(wx_unioni…

邪修实战系列(3)

1、第一阶段邪修实战总览&#xff08;9.1-9.30&#xff09; 把第一阶段&#xff08;基础夯实期&#xff09;的学习计划拆解成极具操作性的每日行动方案。这个计划充分利用我“在职学习”的特殊优势&#xff0c;强调“用输出倒逼输入”&#xff0c;确保每一分钟的学习都直接服务…

【GD32】ROM Bootloader、自定义Bootloader区别

Bootloader是应用程序跑起来之前&#xff0c;用于初始化的一段程序&#xff0c;它分为两种&#xff0c;ROM Bootloader、自定义Bootloader。GD32芯片出厂时预烧录在ROM中的Bootloader&#xff08;以下简称ROM Bootloader&#xff09;和自己编写的Bootloader&#xff08;以下简称…

Linux防火墙-Firewalld

一、 概述 按表现形式划分&#xff1a; 软件防火墙&#xff1a; 集成在系统内部&#xff0c;Linux系统&#xff1a; iptables、firewalld、ufw&#xff1b; windows系统下&#xff1a; windows defender 硬件防火墙&#xff1a; 华为防火墙、思科防火墙、奇安信防火墙、深信服防…