深入解析 Harris 角点检测算法:从孔径问题到响应函数的完整推导
在图像处理中,角点是非常重要的特征。为了快速、准确地检测角点,Harris 提出了 Harris 角点检测算法,它基于局部窗口内图像梯度的变化来判断角点。本文将从最基础的孔径问题(Aperture Problem)入手,通过泰勒展开和向量乘法的形式逐步推导 Harris 角点检测的过程,并给出特征值分析和角响应函数的详细解释。
1. 孔径问题的引入
孔径问题常用“理发店门前转灯”进行类比说明。你可以想象一个横着旋转的灯,它看起来像是垂直方向移动,但实际上是水平方向转动。

- 感觉上:垂直移动
- 实际情况:水平旋转
在计算机视觉中,光流的计算就面临类似的问题:在仅有一个小窗口的情况下,无法确定物体的移动方向,尤其在物体具有某种平滑性时,感知的运动方向和实际运动方向可能不一致。这就是“孔径问题”。
2. 图像函数的平移与泰勒展开
在处理图像时,假设我们有一幅灰度图像,它的像素值可以用函数 I ( x , y ) I(x, y) I(x,y) 来表示。这里 x x x 和 y y y 是图像的空间坐标, I ( x , y ) I(x, y) I(x,y) 是在这个点上的像素强度值。Harris 算子的基本思想是当图像发生微小平移时,通过分析像素强度的变化来判断该区域是角点、边缘还是平坦区域。
图像的平移
考虑图像的某个点发生了微小的平移,即从 ( x , y ) (x, y) (x,y) 平移到 ( x + u , y + v ) (x + u, y + v) (x+u,y+v)。那么,经过平移后的像素强度可以表示为 I ( x + u , y + v ) I(x+u, y+v) I(x+u,y+v),如图所示

在处理图像时,假设我们有一幅灰度图像,它的像素值可以用函数 I ( x , y ) I(x, y) I(x,y) 来表示。这里 x x x 和 y y y 是图像的空间坐标, I ( x , y ) I(x, y) I(x,y) 是在这个点上的像素强度值。Harris 算子的基本思想是当图像发生微小平移时,通过分析像素强度的变化来判断该区域是角点、边缘还是平坦区域。
图像的平移
考虑图像的某个点发生了微小的平移,即从 ( x , y ) (x, y) (x,y) 平移到 ( x + u , y + v ) (x + u, y + v) (x+u,y+v)。那么,经过平移后的像素强度可以表示为 I ( x + u , y + v ) I(x+u, y+v) I(x+u,y+v)。
为了简化问题,我们假设这个位移很小,因此可以使用 泰勒展开 对 I ( x + u , y + v ) I(x+u, y+v) I(x+u,y+v) 进行近似:
I ( x + u , y + v ) ≈ I ( x , y ) + u ∂ I ∂ x + v ∂ I ∂ y + 高阶项 I(x+u, y+v) \approx I(x, y) + u \frac{\partial I}{\partial x} + v \frac{\partial I}{\partial y} + \text{高阶项} I(x+u,y+v)≈I(x,y)+u∂x∂I+v∂y∂I+高阶项
其中:
- ∂ I ∂ x \frac{\partial I}{\partial x} ∂x∂I 表示图像在 x x x 方向的梯度,记为 I x I_x Ix;
- ∂ I ∂ y \frac{\partial I}{\partial y} ∂y∂I 表示图像在 y y y 方向的梯度,记为 I y I_y Iy。
因此,我们可以将上式简化为:
I ( x + u , y + v ) ≈ I ( x , y ) + I x u + I y v I(x+u, y+v) \approx I(x, y) + I_x u + I_y v I(x+u,y+v)≈I(x,y)+Ixu+Iyv
这个式子告诉我们,当图像发生微小的平移时,像素值的变化可以通过图像梯度来近似表示。
3. 构造能量函数
在 Harris 角点检测中,关键思想是比较位移前后的像素强度差异,构造一个 能量函数 来度量这种差异。能量函数 E ( u , v ) E(u, v) E(u,v) 描述了图像在窗口 W W W 内的像素强度变化,它定义为:
E ( u , v ) = ∑ ( x , y ) ∈ W ω ( x , y ) [ I ( x + u , y + v ) − I ( x , y ) ] 2 E(u, v) = \sum_{(x, y) \in W} \omega(x, y) \left[ I(x+u, y+v) - I(x, y) \right]^2 E(u,v)=(x,y)∈W∑ω(x,y)[I(x+u,y+v)−I(x,y)]2
其中:
-
ω ( x , y ) \omega(x, y) ω(x,y) 是一个权重函数,通常用于加权窗口内不同像素的影响。权重函数可以是均匀分布的矩形窗口,也可以是高斯加权窗口,如图片所示的两种形式。
- 矩形窗口:窗口内像素权重为 1,外部为 0;
- 高斯窗口:窗口内的像素权重按照高斯分布递减,使得靠近中心的像素有更大的影响。

代入泰勒展开的结果 I ( x + u , y + v ) ≈ I ( x , y ) + I x u + I y v I(x+u, y+v) \approx I(x, y) + I_x u + I_y v I(x+u,y+v)≈I(x,y)+Ixu+Iyv,能量函数可以近似表示为:
E ( u , v ) ≈ ∑ ( x , y ) ∈ W ω ( x , y ) [ I x u + I y v ] 2 E(u, v) \approx \sum_{(x, y) \in W} \omega(x, y) \left[ I_x u + I_y v \right]^2 E(u,v)≈(x,y)∈W∑ω(x,y)[Ixu+Iyv]2
这一步已经将图像的位移引入到了能量函数中,它通过计算窗口内像素的变化来判断图像的局部特性。
4. 向量乘法形式的能量函数
为了便于计算和进一步分析,我们可以将上述能量函数写成矩阵形式。先将 I x u + I y v I_x u + I_y v Ixu+Iyv 写成向量形式:
I x u + I y v = [ I x I y ] [ u v ] I_x u + I_y v = \begin{bmatrix} I_x & I_y \end{bmatrix} \begin{bmatrix} u \\ v \end{bmatrix} Ixu+Iyv=[IxIy][uv]
因此,能量函数 E ( u , v ) E(u, v) E(u,v) 可以写成:
E ( u , v ) = ∑ ( x , y ) ∈ W ω ( x , y ) [ u v ] [ I x 2 I x I y I x I y I y 2 ] [ u v ] E(u, v) = \sum_{(x, y) \in W} \omega(x, y) \begin{bmatrix} u & v \end{bmatrix} \begin{bmatrix} I_x^2 & I_x I_y \\ I_x I_y & I_y^2 \end{bmatrix} \begin{bmatrix} u \\ v \end{bmatrix} E(u,v)=(x,y)∈W∑ω(x,y)[uv][Ix2IxIyIxIyIy2][uv]
进一步,我们定义一个称为 结构张量(M) 的矩阵:
M = ∑ ( x , y ) ∈ W ω ( x , y ) [ I x 2 I x I y I x I y I y 2 ] M = \sum_{(x, y) \in W} \omega(x, y) \begin{bmatrix} I_x^2 & I_x I_y \\ I_x I_y & I_y^2 \end{bmatrix} M=(x,y)∈W∑ω(x,y)[Ix2IxIyIxIyIy2]
于是,能量函数可以简化为:
E ( u , v ) = [ u v ] M [ u v ] E(u, v) = \begin{bmatrix} u & v \end{bmatrix} M \begin{bmatrix} u \\ v \end{bmatrix} E(u,v)=[uv]M[uv]
这就是 Harris 算子中能量函数的向量乘法形式,它为后续的特征值分析奠定了基础。
5. 特征值分析
我们通过特征值分解对结构张量 M M M 进行分析。这个张量 M M M 表示的是图像局部区域的梯度信息,它的特征值 λ 1 \lambda_1 λ1 和 λ 2 \lambda_2 λ2 反映了不同方向上的强度变化。
- λ 1 \lambda_1 λ1 和 λ 2 \lambda_2 λ2 是 M M M 的特征值,它们描述了图像在不同方向上的梯度变化程度。根据特征值的大小关系,我们可以判断局部区域的图像结构。
特征值分解可以写为:
M = R − 1 [ λ 1 0 0 λ 2 ] R M = R^{-1} \begin{bmatrix} \lambda_1 & 0 \\ 0 & \lambda_2 \end{bmatrix} R M=R−1[λ100λ2]R
其中, R R R 是旋转矩阵,用来将图像的局部梯度信息旋转到与特征值对应的方向上。

平坦区域:
- 如果 λ 1 \lambda_1 λ1 和 λ 2 \lambda_2 λ2 都很小,表示在该区域内无论在哪个方向上图像的强度变化都非常小。这意味着该区域是平坦的,图像强度几乎不变。这种区域通常位于图像的背景或均匀纹理处。
- 如图中所示,梯度图的分布在平坦区域非常集中, λ 1 \lambda_1 λ1 和 λ 2 \lambda_2 λ2 都接近零。
边缘区域:
- 如果 λ 1 \lambda_1 λ1 很大,而 λ 2 \lambda_2 λ2 很小,意味着该区域沿着一个方向(通常是边缘的方向)有较大的强度变化,而垂直于该方向的变化非常小。这种情况典型地表示 边缘区域 。
- 从梯度图中可以看出,在边缘区域,数据点呈现拉长的形状,意味着图像沿某一个方向(边缘方向)变化明显,而另一方向上的变化不显著。
角点区域:
- 如果 λ 1 \lambda_1 λ1 和 λ 2 \lambda_2 λ2 都很大,表示图像在该区域内的各个方向都有较大的强度变化。这意味着无论图像在水平或垂直方向移动,都会导致显著的变化,因此可以认为该区域是角点。
- 角点区域在梯度图中显示为近似圆形的分布,表示在多个方向上都有显著的梯度变化。
7. Harris 响应函数
为了快速判断角点,Harris 引入了一个角响应函数:
θ = det ( M ) − α ⋅ trace ( M ) 2 \theta = \det(M) - \alpha \cdot \text{trace}(M)^2 θ=det(M)−α⋅trace(M)2
其中:
- det ( M ) = λ 1 λ 2 \det(M) = \lambda_1 \lambda_2 det(M)=λ1λ2 是矩阵的行列式,表示局部窗口中图像的总变化。
- trace ( M ) = λ 1 + λ 2 \text{trace}(M) = \lambda_1 + \lambda_2 trace(M)=λ1+λ2 是矩阵的迹,表示图像的总强度变化。
- α \alpha α 是经验常数,通常取 0.04 到 0.06。
假设有一个 2 × 2 2 \times 2 2×2 的矩阵:
M = ( 3 2 4 5 ) M = \begin{pmatrix} 3 & 2 \\ 4 & 5 \end{pmatrix} M=(3425)
矩阵的迹为对角线元素的和,即:
trace ( M ) = 3 + 5 = 8 \text{trace}(M) = 3 + 5 = 8 trace(M)=3+5=8
在这个例子中,迹等于 8,表示该矩阵的总强度变化。在物理或图像处理应用中,迹可以用来表示某些总量,如能量、强度等。
通过计算这个响应函数 θ \theta θ,我们可以判断局部区域是否是角点:
- 角点(Corner):
当 λ 1 \lambda_1 λ1 和 λ 2 \lambda_2 λ2 都较大时,说明图像的强度在 x x x 和 y y y 方向上都有明显的变化,即梯度变化较大。这种情况通常发生在角点或交叉点处。 - 边缘(Edge):
当 λ 1 \lambda_1 λ1 较大而 λ 2 \lambda_2 λ2 较小(或相反)时,说明图像在一个方向上有明显变化,而另一个方向上变化较小。此时,局部区域更可能是边缘。 - 平坦区域(Flat Region):
当 λ 1 \lambda_1 λ1 和 λ 2 \lambda_2 λ2 都较小时,说明图像在该区域内没有明显的强度变化(例如,在均匀的平坦区域)。此时,响应函数值 θ \theta θ 也会很小。
8. Harris 算子的优缺点
Harris 角点检测算法能够有效地检测出图像中的角点,并且对图像的 旋转具有较好的不变性 。然而,它也有一些局限性:
- 对尺度不变性较差:Harris 算法对图像缩放不敏感,因此对于不同尺度的图像角点检测效果不佳。
- 容易受到噪声影响:如果图像中存在较多噪声,梯度计算可能会受到干扰,导致角点检测结果不准确。
为了克服这些局限性,常常会将 Harris 角点检测与其他特征提取算法(例如 SIFT 或 SURF)结合使用,以提升检测的鲁棒性。
相关文章:
深入解析 Harris 角点检测算法:从孔径问题到响应函数的完整推导
在图像处理中,角点是非常重要的特征。为了快速、准确地检测角点,Harris 提出了 Harris 角点检测算法,它基于局部窗口内图像梯度的变化来判断角点。本文将从最基础的孔径问题(Aperture Problem)入手,通过泰勒…...
抖音视频制作怎么暂停画面,抖音视频怎么让它有暂停的效果
千万别滥用视频特效,不然它能毁掉你的抖音作品。在创作过程中,应尽量使用类似暂停画面、隐形字幕这样的视觉特效,可以显著提高作品的视觉体验。增强视频表现力的同时,也不会让画面看起来过于夸张。有关抖音视频制作怎么暂停画面的…...
Android GPIO方式解码红外数据
1 红外遥控协议 1.1 基本概念 1)NEC协议,采用PWM方式调制。38KHz载波,一般是由引导码地址码地址反码数据数据反码构成。 遥控接收头端收到的信号为:逻辑1是560us低1680us高,逻辑0是560us低560us高。 地址:u…...
基于SpringBoot+Vue的益农智慧服务平台【提供源码+答辩PPT+参考文档+项目部署】
一、项目技术架构: 本项目是一款SpringBoot益农平台的设计与实现。 该SpringBootVue的益农平台的设计与实现,后端采用SpringBoot架构,前端采用VueElementUI实现页面的快速开发,并使用关系型数据库MySQL存储系统运行数据。本系统分…...
基于springboot的在线考试与学习交流网页
作者:计算机学长阿伟 开发技术:SpringBoot、SSM、Vue、MySQL、ElementUI等,“文末源码”。 系统展示 【2024最新】基于JavaSpringBootVueMySQL的,前后端分离。 开发语言:Java数据库:MySQL技术:…...
JS异步编程进阶(二):rxjs与Vue、React、Angular框架集成及跨框架状态管理实现原理
在现代前端开发中,异步操作已经成为不可或缺的一部分。无论是处理网络请求、响应用户输入,还是监听外部事件,异步编程模式始终占据重要位置。而RxJS作为功能强大的异步编程库,广泛应用于多个框架之中,如Vue、React、An…...
nginx web代理
目录 1.nginx的简单介绍 2.正向代理的应用场景 2.1做访问控制 2.2审计 2.3负载分散 2.4隐私保护和匿名性 3.反向代理的应用场景如下 3.1.负载均衡 2.缓存静态内容 3.压缩和优化内容 4.提供故障转移 5.安全性和匿名性 4.正向代理 4.1web端 4.2lb01代理服务器…...
人形机器人的关节控制
人形机器人的关节控制是机器人技术中的核心环节之一,它直接关系到机器人的运动灵活性、精确度和稳定性。 一、关节结构与设计 人形机器人的关节结构通常包括底座、内圈、外圈和滚珠等组件,这些组件共同构成了关节的旋转和支撑系统。关节的设计需要考虑到承载能力、稳定性以…...
python 爬虫 入门 二、数据解析(正则、bs4、xpath)
目录 一、待匹配数据获取 二、正则 三、bs4 (一)、访问属性 (二)、获取标签的值 (三)、查询方法 四、xpath 后续:登录和代理 上一节我们已经知道了如何向服务器发送请求以获得数据&#x…...
PTX 汇编代码语法
PTX(Parallel Thread Execution)汇编是 NVIDIA 为其 GPU 提供的一种并行指令集架构(ISA),用于编写 GPU 设备代码。PTX 是一种中间表示(IR),在 CUDA 代码编译时生成,之后会…...
【mysql】统计两个相邻任务/事件的间隔时间以及每个任务的平均用时
准备步骤1. 设置查询参数部分1.1 设置需要分析的起始时间1.2. 设置需要分析的时间的长度(分析的结束时间)1.3. 设置分析内容1.4. 设置需要分析的表和字段 2. 自动计算分析2.1 设置起始序号2.2. 筛选user_log表数据并生成带序号的临时表temp_ria2.3. 通过…...
RHCE——笔记
第一章——例行性工作 1:单一致性的例行性工作 仅处理执行一次就结束 at命令 /etc/at.allow —— 写在该文件的人可以使用at命令 /etc/at.deny —— 黑名单 两个文件都不存在,则只有root可以使用 #at工作调度对应的系统服务 [rootlocalhost ~]# p…...
Spring Boot在知识管理中的应用
1系统概述 1.1 研究背景 如今互联网高速发展,网络遍布全球,通过互联网发布的消息能快而方便的传播到世界每个角落,并且互联网上能传播的信息也很广,比如文字、图片、声音、视频等。从而,这种种好处使得互联网成了信息传…...
OpenCV高级图形用户界面(14)交互式地选择一个或多个感兴趣区域函数selectROIs()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 允许用户在给定的图像上选择多个 ROI。 该函数创建一个窗口,并允许用户使用鼠标来选择多个 ROI。控制方式:使用空格键或…...
字节青训营入营考核部分题解
题库链接:https://juejin.cn/problemset?utm_sourceschool&utm_mediumyouthcamp&utm_campaignexamine 1. 计算从x到y的最小步数 问题描述 AB 实验同学每天都很苦恼如何可以更好地进行 AB 实验,每一步的流程很重要,我们目标为了…...
Android调用系统打印图片
拍摄和分享照片是移动设备最受欢迎的用途之一。如果您的应用 拍摄照片、展示照片或允许用户分享图片,则应考虑启用打印功能 和图片。Android 支持库提供了一个便捷的功能,支持使用 只需编写极少的代码和一组简单的打印版式选项。 本节课介绍如何使用 v4…...
网络最快的速度光速,因此‘‘光网络‘‘由此产生
世界上有一种最快的速度又是光,以前传统以太网络规划满足不了现在的需求。 一 有线网规划 二 无线网规划...
WPF -- LiveCharts的使用和源码
LiveCharts 是一个开源的 .NET 图表库,特别适用于 WPF、WinForms 和其他 .NET 平台。它提供了丰富的图表类型和功能,使开发者能够轻松地在应用程序中创建动态和交互式图表。下面我将使用WPF平台创建一个测试实例。 一、LiveCharts的安装和使用 1.安装N…...
spring 如何将mutipartFile转存到本地磁盘
两者的区别和联系 MutipartFile是spring的一部分,File则是java的标准类MutipartFile用于接收web传递的文件,File操作本地系统的文件 MutipartFile 转换File的三种方式 使用MutipartFile 自带的transferTo方法使用java自带的FileOutPutStream流使用java自…...
【学术会议-6】激发灵感-计算机科学与技术学术会议邀您参与,共享学术盛宴,塑造明天的科技梦想!
【学术会议-6】激发灵感-计算机科学与技术学术会议邀您参与,共享学术盛宴,塑造明天的科技梦想! 【学术会议-6】激发灵感-计算机科学与技术学术会议邀您参与,共享学术盛宴,塑造明天的科技梦想! 文章目录 【…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...
Python训练营-Day26-函数专题1:函数定义与参数
题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...
6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙
Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...
用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章
用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章 摘要: 操作系统内核的安全性、稳定性至关重要。传统 Linux 内核模块开发长期依赖于 C 语言,受限于 C 语言本身的内存安全和并发安全问题,开发复杂模块极易引入难以…...
