虽然像Sobel和Canny这样的边缘检测器擅长找到图像强度在一个方向上急剧变化的边界,但有时我们需要更鲜明的点。设想在视频中跟踪物体或在从不同视角拍摄的两张图像之间匹配特征。沿着直线边缘的点可能模糊不清——如果你沿着边缘滑动一个小块区域,它看起来几乎一样。我们通常需要的是强度在多个方向上显著变化的点。这些点通常被称为角点。角点很有用,因为它们代表两条或多条边缘交汇的点,或者高曲率的点。与简单边缘上的点相比,即使图像发生旋转或视角发生微小变化,角点也往往更稳定,更容易持续定位。那么,我们如何找到这些角点呢?由Chris Harris和Mike Stephens于1988年开发的Harris角点检测器,提供了一种流行且有效的方法,基于对局部强度变化的分析。滑动窗口的直观思路设想取一个小的、固定大小的窗口(例如,5x5像素)并在图像上滑动它。对于窗口的每个位置,我们都会问:“如果我们朝任何方向稍微移动一下窗口,这个窗口内部的内容会发生多大变化?”考虑三种情况:平坦区域: 如果窗口当前位于均匀强度区域(如一片晴朗的天空或一面素色墙壁),朝任何方向(水平、垂直、对角)稍微移动窗口,窗口内像素的外观几乎不会改变,甚至根本不变。变化非常小。边缘区域: 如果窗口位于直线边缘中心,沿着边缘方向移动它可能不会引起窗口内容的显著变化。然而,垂直于边缘移动它,当窗口跨过强度边界时,会引起非常明显的改变。因此,存在显著变化,但主要在一个方向上。角点区域: 如果窗口位于角点或纹理在多个方向上显著变化的点上,那么朝任何方向稍微移动窗口都会导致窗口内容发生实质性变化。这是Harris检测器主要寻找的特征。这种直观思路可以这样可视化:digraph Harris_Intuition { rankdir=LR; node [shape=box, style=rounded, fontname="helvetica", fontsize=10]; edge [fontsize=10, fontname="helvetica"]; subgraph cluster_flat { label = "平坦区域"; bgcolor="#e9ecef"; node [shape=square, label="", style=filled, fillcolor="#ced4da", fixedsize=true, width=0.4, height=0.4]; f_center [label="窗口", fillcolor="#868e96"]; f_up [pos="0,0.7!", fillcolor="#ced4da"]; f_down [pos="0,-0.7!", fillcolor="#ced4da"]; f_left [pos="-0.7,0!", fillcolor="#ced4da"]; f_right [pos="0.7,0!", fillcolor="#ced4da"]; f_center -> f_up [label="微小变化", color="#adb5bd"]; f_center -> f_down [label="微小变化", color="#adb5bd"]; f_center -> f_left [label="微小变化", color="#adb5bd"]; f_center -> f_right [label="微小变化", color="#adb5bd"]; } subgraph cluster_edge { label = "边缘区域"; bgcolor="#e9ecef"; node [shape=square, label="", style=filled, fixedsize=true, width=0.4, height=0.4]; e_center [label="窗口", fillcolor="#868e96"]; e_up [pos="0,0.7!", fillcolor="#ced4da"]; // 沿着边缘移动 e_down [pos="0,-0.7!", fillcolor="#ced4da"]; // 沿着边缘移动 e_left [pos="-0.7,0!", fillcolor="#495057"]; // 跨越边缘移动 e_right [pos="0.7,0!", fillcolor="#495057"]; // 跨越边缘移动 e_center -> e_up [label="微小变化", color="#adb5bd"]; e_center -> e_down [label="微小变化", color="#adb5bd"]; e_center -> e_left [label="较大变化", color="#f03e3e", style=bold]; e_center -> e_right [label="较大变化", color="#f03e3e", style=bold]; } subgraph cluster_corner { label = "角点区域"; bgcolor="#e9ecef"; node [shape=square, label="", style=filled, fixedsize=true, width=0.4, height=0.4]; c_center [label="窗口", fillcolor="#868e96"]; c_up [pos="0,0.7!", fillcolor="#495057"]; // 向上移动 c_down [pos="0,-0.7!", fillcolor="#ced4da"]; // 向下移动 c_left [pos="-0.7,0!", fillcolor="#495057"]; // 向左移动 c_right [pos="0.7,0!", fillcolor="#ced4da"]; // 向右移动 c_center -> c_up [label="较大变化", color="#f03e3e", style=bold]; c_center -> c_down [label="较大变化", color="#f03e3e", style=bold]; c_center -> c_left [label="较大变化", color="#f03e3e", style=bold]; c_center -> c_right [label="较大变化", color="#f03e3e", style=bold]; } }滑动窗口在不同图像区域上稍微移动时的行为。角点在所有方向的移动下都表现出显著变化。使用梯度量化变化Harris检测器并非真的在所有方向上移动窗口并计算差异(这会很慢),而是使用了一种更巧妙的数学方法,基于图像梯度。还记得我们使用Sobel算子时遇到的梯度$I_x$和$I_y$吗?它们分别衡量水平(x)和垂直(y)方向上的强度变化速率。Harris检测器查看这些梯度在以像素$(x,y)$为中心的窗口内的分布。它将这些信息归纳为一个小的2x2矩阵,通常被称为$M$或“结构张量”:$$ M = \sum_{\text{window}} \begin{bmatrix} I_x^2 & I_x I_y \ I_x I_y & I_y^2 \end{bmatrix} $$不必过多担心矩阵运算本身。重要的一点是,这个矩阵$M$能够表示梯度在窗口内的方向分布:平坦区域: 窗口内所有位置的$I_x$和$I_y$都很小,因此矩阵$M$中的数值也会很小。边缘区域: 梯度很大,但主要在一个方向上(垂直于边缘)。例如,在垂直边缘上,$I_x$会很大而$I_y$会很小。这种结构会在矩阵$M$中体现出来。角点区域: 梯度在多个方向上都很大($I_x$和$I_y$都比较大),导致矩阵$M$中出现较大值。Harris响应分数 (R)Harris和Stephens发现了一种计算单一分数的方法,称为角点响应$R$,可以直接从这个矩阵$M$计算,无需显式计算复杂的特征值等。公式如下:$$ R = \det(M) - k (\text{trace}(M))^2 $$组成部分说明:$\det(M)$ 是矩阵$M$的行列式。计算方法为 $M_{11}M_{22} - M_{12}M_{21}$。$\text{trace}(M)$ 是矩阵$M$的迹。它是对角线元素的和:$M_{11} + M_{22}$。$k$ 是一个敏感度参数,通常是一个小值,例如0.04到0.06。它是根据经验选择的。$R$的值告诉我们窗口当前所在的区域类型:$R$很大且为正: 表示一个角点。两个梯度($I_x, I_y$)都很大,并且在窗口内方向变化。这对应于向任何方向移动窗口都会引起较大变化的情况。$R$为负值(大数值): 表示一条边缘。存在显著梯度,但主要在一个方向上。这对应于只有当垂直于边缘移动窗口时才会引起较大变化的情况。$|R|$很小: 表示一个平坦区域。梯度在所有方向上都很小。移动窗口几乎不会引起变化。寻找角点Harris检测器算法会计算图像中每个像素的$R$分数(考虑以该像素为中心的窗口)。结果是一个“角点响应图”,其中较高的正值表示角点。为了得到最终的角点,通常还会应用另外两个步骤:阈值处理: 只有$R$分数高于特定阈值的像素才被视为潜在的角点候选。这可以滤除平坦区域和大多数边缘。非极大值抑制 (NMS): 一个真实角点周围的小邻域内很可能会有多个像素具有较高的$R$分数。NMS会检查每个候选像素周围的小区域(例如3x3或5x5),并只保留该区域中$R$分数最高的像素,抑制其他像素。这可以确保我们为每个角点只检测到一个明确的点。总结与局限Harris角点检测器提供了一种计算高效的方法,用于识别图像中强度在多个方向上显著变化的区域。它使用局部窗口内的图像梯度来计算一个响应分数($R$),从而区分角点、边缘和平坦区域。它是一种用于寻找有特点点的基本方法。一个局限是,基本的Harris检测器不具备尺度不变性。如果你放大得非常近,一个角点可能看起来像一条边缘,或者一个小的纹理图案从远处看可能像一个角点,但放大后会分解为边缘。计算中使用的窗口大小会影响检测到的角点的尺度。更先进的检测器在此基础上进行改进以处理尺度变化,但分析局部强度结构的核心思路仍然很重要。