Feature Detection Fundamentals

Imagine two photographs of the same building. One is taken from a parking lot, the other from a rooftop. They are taken minutes apart, with the sun in a different position. A human glances at both and instantly recognizes the same window corners. They also spot the same doorframe and the same brick edges. Teaching a computer to make that same correspondence is harder. This means matching pixel patch to pixel patch, across viewpoint, scale, and lighting changes. This is the founding problem of classical computer vision. It starts with feature detection. A raw image is a grid of numbers with no built-in notion of "interesting." Most pixels are redundant. A patch of blue sky or a flat wall tells you almost nothing. It reveals little about where you are in the picture. It also reveals little about how the picture has moved. Feature detection is the algorithmic process of finding informative image locations. These are the small minority of points, edges, or blobs. Their local neighborhood must be distinctive enough to be found again reliably. This should hold true even after the image changes. This matters enormously in practice. Panorama stitching, 3D reconstruction from photos, and visual odometry for robots and drones all rely on it. So do augmented reality tracking and image retrieval. All of these begin by asking a key question. Which pixels can I trust to reappear? And how do I describe them so I can recognize them later? The big picture is a two-stage pipeline. It recurs across decades of vision research and into modern deep networks. First, detect candidate locations. Then describe them with a compact signature for matching. This article is about the detect half. More specifically, it covers the conceptual foundations every detector must satisfy. This includes everything from 1980s corner detectors to today's learned keypoint networks. We will not yet build a specific detector. Instead, we build the vocabulary and criteria for judging detectors. These are repeatability, distinctiveness, locality, and their formal costs. Together they let us judge whether any detector is any good. By the end of this article, you will gain several skills. You will be able to state precisely what makes a pixel location a "good feature." You will reason about the trade-offs between locality and distinctiveness. You will understand why flat regions and pure edges are both bad feature candidates. And you will see the mathematical bridge that connects these ideas. This bridge runs via the local image gradient and autocorrelation. It leads directly into the Harris corner detector. Eventually, it extends into fully scale-invariant systems like SIFT.

Key takeaways
  • A feature is a small image region whose local structure is distinctive enough to be re-identified across images of the same scene.
  • Good features need three properties: repeatability (found again despite transformations), distinctiveness (locally unique, matchable), and locality (small support, robust to occlusion/clutter).
  • Flat regions have no structure to lock onto; straight edges suffer the aperture problem — only corners and blob-like textures pin down position in both directions.
  • The local autocorrelation of image intensity, built from the gradient structure tensor, is the mathematical tool that separates flat, edge, and corner regions.
  • Feature detection is stage one of a two-stage pipeline: detect keypoints, then describe them for matching — used in panoramas, SLAM, AR, and structure-from-motion.
  • These criteria motivate concrete algorithms covered next: Harris Corner Detection and scale-space blob/corner detectors like SIFT: Scale-Invariant Features.
The core insight

A good image feature is a location whose small neighborhood looks unlike its surroundings but the same as itself under realistic image change — a tension resolved by demanding repeatability, distinctiveness, and locality simultaneously.

The idea

A feature in classical computer vision is a compact, localized piece of image structure — typically a point (keypoint), sometimes a small region or an edge segment — selected because it can be reliably located again in another image of the same scene, and because its local appearance is distinctive enough to be matched against candidates elsewhere. This is different from "feature" in the general machine-learning sense (any input variable); here a feature is itself an output of an algorithm run over the image, chosen from millions of candidate pixel locations. Three formal properties define a good feature, and nearly every detector in the literature can be understood as an attempt to optimize them:

Repeatability. If the same 3D scene point is imaged twice — under a different viewpoint, scale, rotation, illumination, or with sensor noise — the detector should fire at the corresponding image location in both images. Formally, if xx is a detected feature in image I1I_1 and TT is the (possibly unknown) geometric/photometric transformation mapping I1I_1 to I2I_2, we want the detector applied to I2I_2 to also fire near T(x)T(x). Repeatability is measured empirically as the fraction of features in one image that have a corresponding detection within some pixel tolerance in the transformed image.

Distinctiveness (saliency). The local neighborhood around the feature must contain enough information to distinguish it from other locations, both nearby and across the whole image. A feature with a highly distinctive local signature can be matched confidently by comparing descriptors; a feature that looks like a thousand other pixels (e.g., anywhere inside a flat gray wall) cannot be matched — matching becomes ambiguous or impossible. Distinctiveness is what makes the later description stage (assigning a vector to the patch) actually useful.

Locality. The feature should be defined by a small spatial neighborhood. This buys robustness to occlusion (only part of the scene needs to be visible), to clutter (background changes don't affect the feature), and to non-rigid or non-planar scene structure (local regions are closer to planar/rigid than the whole scene). Locality trades off against distinctiveness: a huge neighborhood carries more information (more distinctive) but is less local (less robust and less repeatable under perspective/occlusion change). A fourth, more practical property is efficiency: since a detector must scan every pixel (and often every scale) of every image, detection must be computable in time roughly linear in image size, using cheap local operations — this is why almost every classical detector is built from convolutions and simple pointwise arithmetic on image gradients, rather than expensive global search. The central diagnostic question a detector must answer at every pixel is: does the local neighborhood have enough two-dimensional structure to pin down its own location? This question has a clean geometric answer once we look at how image intensity changes when a small patch is shifted.

How it works

Why flat regions and edges fail

Consider a small window WW centered at pixel (x,y)(x, y), and ask how much the intensity pattern inside WW changes when the window is shifted by a small displacement (u,v)(u, v). Define the sum of squared differences (SSD) — the local autocorrelation:

E(u,v)=∑(xi,yi)∈Ww(xi,yi) [I(xi+u,yi+v)−I(xi,yi)]2E(u, v) = \sum_{(x_i, y_i) \in W} w(x_i, y_i)\, \big[I(x_i + u, y_i + v) - I(x_i, y_i)\big]^2

where ww is a weighting window (uniform or Gaussian) emphasizing pixels near the center. This single function E(u,v)E(u,v) is the conceptual seed of essentially all corner/blob detectors, and the analysis of its shape gives us the classification a good detector must perform:

  • Flat region: II is nearly constant in WW. Then E(u,v)≈0E(u,v) \approx 0 for all (u,v)(u,v) — the window can slide in any direction with almost no change. There is no way to localize this pixel; it is indistinguishable from its neighbors. Reject.
  • Edge: II varies strongly across the edge but is nearly constant along the edge direction. Then E(u,v)E(u,v) is large for shifts across the edge but near zero for shifts along it. This is the classical aperture problem: looking through a small local window at an edge, you cannot tell how far the edge has moved along its own direction. Position along the edge is unconstrained. Reject as a point feature (edges remain useful as edge features, but not as localizable keypoints).
  • Corner / blob / high-texture region: II varies significantly in every direction. Then E(u,v)E(u,v) grows quickly for shifts in all directions — the window's appearance changes no matter which way you nudge it. This is exactly the property that makes a location repeatable and precisely localizable. Accept.

This qualitative story is made quantitative by locally approximating E(u,v)E(u,v) using a first-order (gradient) Taylor expansion of II, which yields a 2×22\times 2 matrix — the structure tensor (also called the second-moment matrix):

M=∑(xi,yi)∈Ww(xi,yi)[Ix2IxIyIxIyIy2]M = \sum_{(x_i,y_i)\in W} w(x_i,y_i) \begin{bmatrix} I_x^2 & I_x I_y \\ I_x I_y & I_y^2 \end{bmatrix}

built entirely from the local image gradients Ix,IyI_x, I_y — precisely the prerequisite concept this article assumes. Then, to second order,

E(u,v)≈[uv]M[uv].E(u,v) \approx \begin{bmatrix} u & v \end{bmatrix} M \begin{bmatrix} u \\ v \end{bmatrix}.

The eigenvalues λ1≥λ2≥0\lambda_1 \ge \lambda_2 \ge 0 of MM tell the whole story:

Eigenvalue patternLocal structureFeature verdict
λ1≈λ2≈0\lambda_1 \approx \lambda_2 \approx 0flat regionreject
λ1≫λ2≈0\lambda_1 \gg \lambda_2 \approx 0edge (one strong gradient direction)reject (aperture problem)
λ1≥λ2≫0\lambda_1 \ge \lambda_2 \gg 0corner / blob (two strong directions)accept

This eigen-analysis is exactly the mechanism that Harris Corner Detection turns into a practical, efficient score (avoiding an explicit, costly eigendecomposition at every pixel), and it is the same structural idea that scale-space detectors extend across scale in SIFT: Scale-Invariant Features.

The generic detection pipeline

Regardless of which exact scoring function is used, every classical feature detector follows the same generic algorithmic shape: ``` ALGORITHM GenericFeatureDetector(image I, window radius r, threshold τ) ------------------------------------------------------------------ 1. Compute image gradients Ix, Iy (e.g. via Sobel convolution) 2. For every pixel p in I: Form the local structure tensor M(p) using gradients in a window of radius r around p (Gaussian-weighted) Compute a scalar "cornerness" score S(p) from M(p) (e.g. from eigenvalues, or a fast proxy — see Harris) 3. Threshold: mark p as a CANDIDATE if S(p) > τ 4. Non-maximum suppression: For each candidate p, keep it only if S(p) is the maximum among candidates in its local neighborhood (removes duplicate detections clustered on one corner) 5. Return the surviving set of keypoints {p : locally maximal, S(p) > τ} ------------------------------------------------------------------ ``` Two implementation details matter for correctness, and both are common sources of bugs:

  • Gaussian weighting, not a hard box window. A uniform box window makes M(p)M(p) discontinuous as pixels enter/exit the window under sub-pixel shifts, hurting repeatability. A Gaussian weight ww gives a smooth, rotation-invariant estimate of local structure.
  • Non-maximum suppression (NMS) is not optional. Without it, a single strong corner produces a whole cluster of neighboring pixels above threshold, all describing "the same" feature — wasting computation and destroying the locality/distinctiveness of downstream matching. NMS enforces that detected features are spatially well-separated local maxima of the score.
Figure
From raw image structure to an accept/reject decision at each pixel
Flat region λ1 ≈ λ2 ≈ 0 reject: no structure Edge λ1 ≫ λ2 ≈ 0 reject: aperture problem Corner λ1 ≥ λ2 ≫ 0 accept: localizable gradients Ix, Iy → structure tensor M(p) → score S(p) → threshold + non-max suppression → keypoints (this scoring step is specialized in Harris corners and generalized across scale in SIFT)

Complexity & correctness

Time complexity. Let the image have N=HWN = HW pixels and let the local window used to build M(p)M(p) have O(w2)O(w^2) pixels (a small constant, e.g. 7×77\times7 or 9×99\times9). Gradient computation is a fixed-size convolution: O(N)O(N). Building M(p)M(p) at every pixel via Gaussian-weighted sums can be implemented as a small set of separable convolutions (Ix2I_x^2, Iy2I_y^2, IxIyI_xI_y each smoothed by a separable Gaussian), so this step is also O(N⋅w)O(N \cdot w) using separable filtering, effectively O(N)O(N) for fixed window size. Scoring is O(1)O(1) per pixel, thresholding is O(N)O(N), and non-maximum suppression over a fixed neighborhood is O(N)O(N). Total: O(N)O(N), i.e., linear in image size — essential, since a detector must run on every pixel of every frame in real-time systems like visual SLAM.

Space complexity. We must store the gradient image and the three second-moment channels, each O(N)O(N), so overall space is O(N)O(N), independent of the number of features actually detected.

Why O(N)O(N) is the right target, and the honest tradeoff. A naive "compare every pixel's neighborhood to every other pixel's neighborhood" approach to finding distinctive regions is O(N2)O(N^2) or worse and is never used for detection (it belongs, in a bounded form, to the later matching stage). Locality is precisely what saves us: because the structure tensor only requires information from a small, fixed-radius window, the cost per pixel is O(1)O(1) (constant window size), giving global linear-time detection. This is a direct algorithmic payoff of the locality property demanded earlier — a feature definition that required global context (e.g., "is this patch unique in the whole image?") would force at least O(N)O(N) work per pixel, yielding O(N2)O(N^2) overall, which does not scale to megapixel images or video.

Correctness argument (informal, but precise). The claim to justify is: the eigenvalue test on M(p)M(p) correctly identifies pixels where the local window's position is uniquely determined by its appearance. The Taylor expansion E(u,v)≈[u v]M[u v]TE(u,v) \approx [u\ v] M [u\ v]^T is a quadratic form; its eigenvectors are the directions of principal curvature of the "cost of moving the window" surface, and its eigenvalues are the curvatures along those directions. A direction dd with eigenvalue λ≈0\lambda \approx 0 means EE is flat along dd — shifting the window along dd produces (to second order) no change in appearance, so the window's position along dd is unrecoverable from local appearance alone; this is a formal restatement of the aperture problem. Only when both eigenvalues are large is E(u,v)E(u,v) bowl-shaped in every direction, meaning the window's appearance changes under any small shift — which is exactly the condition for the local position to be uniquely (locally) determined by intensity. This directly justifies the flat/edge/corner classification as more than a heuristic: it is the correct second-order condition for local invertibility of "shift versus appearance change."

Honest limitations. This is a local, second-order, small-baseline argument: it says a corner is locally distinguishable under small shifts, not that it will survive large viewpoint change, scale change, or illumination change — those robustness properties require additional machinery (scale-space search, orientation normalization, illumination-invariant descriptors) that later detectors add on top of this same structure-tensor foundation. The theory also assumes locally smooth, differentiable intensity, so it degrades under heavy sensor noise unless the gradients are computed from a suitably smoothed image first.

Worked example

Take a small synthetic 9×99\times9 patch representing a dark square occupying the bottom-right of a bright background (a right-angle corner), and compare it against two neighboring 9×99\times9 windows sampled from a pure vertical edge and from a flat sky region of the same image. Suppose (values illustrative but structurally faithful to a real Sobel-gradient computation, gradients scaled to a comparable range) the Gaussian-weighted sums over each window give:

Region∑Ix2\sum I_x^2∑Iy2\sum I_y^2∑IxIy\sum I_x I_yMMEigenvalues (λ1,λ2)(\lambda_1,\lambda_2)
Flat sky0.40.30.05[0.40.050.050.3]\begin{bmatrix}0.4 & 0.05\\0.05 & 0.3\end{bmatrix}(0.42, 0.28)(0.42,\ 0.28) — both tiny
Vertical edge48.00.60.2[48.00.20.20.6]\begin{bmatrix}48.0 & 0.2\\0.2 & 0.6\end{bmatrix}(48.0, 0.59)(48.0,\ 0.59) — one huge, one tiny
Right-angle corner31.027.59.8[31.09.89.827.5]\begin{bmatrix}31.0 & 9.8\\9.8 & 27.5\end{bmatrix}(38.7, 19.8)(38.7,\ 19.8) — both large

Walking through the eigenvalues (using λ=a+d2±(a−d2)2+b2\lambda = \tfrac{a+d}{2} \pm \sqrt{(\tfrac{a-d}{2})^2 + b^2} for M=[abbd]M = \begin{bmatrix}a&b\\b&d\end{bmatrix}):

  • Flat sky: a=0.4,d=0.3,b=0.05⇒λ1,2≈0.42,0.28a=0.4, d=0.3, b=0.05 \Rightarrow \lambda_{1,2} \approx 0.42, 0.28. Both eigenvalues are close to zero (relative to the corner case's ~30–40 scale) — confirms no direction of appearance change, matching intuition: sky pixels look alike wherever you nudge the window. Rejected by any reasonable threshold τ\tau.
  • Vertical edge: a=48.0,d=0.6,b=0.2⇒λ1≈48.0a=48.0, d=0.6, b=0.2 \Rightarrow \lambda_1 \approx 48.0 (across the edge), λ2≈0.59\lambda_2 \approx 0.59 (along the edge). The huge ratio λ1/λ2≈81\lambda_1/\lambda_2 \approx 81 is the numerical signature of the aperture problem — sliding the window vertically along the edge produces almost no change in EE. Rejected as a point feature even though λ1\lambda_1 alone is large — this is precisely why detectors must look at the smaller eigenvalue, not just the total gradient energy.
  • Right-angle corner: λ1≈38.7, λ2≈19.8\lambda_1 \approx 38.7,\ \lambda_2 \approx 19.8. Both eigenvalues are large and of comparable magnitude (λ2/λ1≈0.51\lambda_2/\lambda_1 \approx 0.51), meaning E(u,v)E(u,v) rises sharply in every direction. This window survives both a magnitude threshold (λ2>τ\lambda_2 > \tau) and passes non-maximum suppression if it scores higher than its immediate neighbors (which, being interior to the flat or edge regions, score much lower). This is the point selected as a keypoint.

This trace shows exactly why the minimum eigenvalue (or a proxy for it) is the correct scalar summary of "cornerness" — a criterion the later Harris Corner Detection algorithm turns into an efficient closed-form score avoiding explicit eigendecomposition.

Common pitfalls & traps

PitfallWhy it happensConsequence
Using raw gradient magnitude as the "feature score"Confuses "high gradient" with "well localized"Edges score high but fail the aperture test — false positives
Skipping Gaussian weighting (hard box window)Simpler to implementScore is unstable/discontinuous under sub-pixel shift, hurting repeatability
Omitting non-maximum suppressionTreated as an optional cleanup stepDozens of near-duplicate keypoints per real corner, wasting compute and confusing matching
Fixed window size across scale changesAssumes viewpoint/scale is constantDetector fails to repeat under zoom — motivates scale-space search (leads to SIFT)
Testing only λ1\lambda_1 (max eigenvalue) instead of λ2\lambda_2 (min)Seems like "more structure is better"Edges (large λ1\lambda_1, tiny λ2\lambda_2) get misclassified as corners
Ignoring illumination normalization before computing gradientsAssumes brightness is stable across imagesRepeatability collapses under lighting/exposure change

Pioneers & history

Origins · 1 minHans P. Moravec and how this was discovered
HP
Hans P. Moravec
1948–present · Robotics and early computer vision, Stanford AI Lab

Moravec, working on the Stanford Cart autonomous robot navigation project in the late 1970s, needed a way to track distinctive image points across frames without expensive full-image matching. His 1977–1980 "corner detector" — sliding a small window in several discrete directions and taking the minimum sum-of-squared-differences as the interest score — was the first formalization of the flat/edge/corner distinction described in this article, and the direct ancestor of the structure-tensor formulation used ever since.

History
1977
— Hans Moravec introduces the corner detector for stereo/motion tracking on the Stanford Cart robot.
1988
— Chris Harris and Mike Stephens generalize Moravec's discrete-direction search into a continuous, rotation-invariant structure-tensor formulation.
1994
— Jianbo Shi and Carlo Tomasi propose the min-eigenvalue criterion directly, refining feature selection for tracking (Shi–Tomasi/"good features to track").
1998–2004
— David Lowe develops SIFT, extending corner/blob detection across scale-space with an invariant descriptor, cementing the detect-then-describe paradigm.
2010
s — Learned keypoint detectors (e.g., LIFT, SuperPoint) replace hand-designed scoring functions with trained networks, while keeping repeatability/distinctiveness/locality as evaluation criteria.

Where this matters

Feature detection is the entry point of nearly every classical geometric vision pipeline. Panorama stitching software (as in phone cameras and tools like Photoshop's photomerge) detects features in overlapping photos, matches them, and estimates the homography that aligns the images — none of it works without repeatable, distinctive keypoints. Structure-from-motion and 3D reconstruction systems (e.g., COLMAP, and the pipelines behind photogrammetry and cultural-heritage digitization) detect features across dozens or thousands of photos to recover camera poses and sparse 3D point clouds. Visual SLAM and odometry in robotics and augmented reality (ARKit, ARCore, autonomous drones) track features frame-to-frame in real time, which is precisely why detection must be linear-time and cheaply re-runnable per frame. Image retrieval and object recognition systems, before the deep-learning era, represented images as "bags" of local feature descriptors built on top of detected keypoints. Even in the deep learning era, learned keypoint detectors (SuperPoint, D2-Net) are still evaluated against exactly the same repeatability/distinctiveness/locality criteria introduced here, and are still typically followed by a description-and-matching stage — the conceptual pipeline outlives the specific algorithm. Understanding this foundational vocabulary is the prerequisite for the concrete algorithms that operationalize it: Harris Corner Detection turns the eigenvalue test into an efficient score, and SIFT: Scale-Invariant Features extends the same reasoning across scale and orientation to survive zoom and rotation.

Ask the tutor: How does the Harris detector turn the eigenvalue test into a score without computing eigenvalues explicitly, and why is that faster?

What exactly counts as a "feature" versus just any pixel?

Any pixel is a candidate, but a feature is a pixel (or small region) that a detector has selected because its local neighborhood satisfies specific criteria: repeatability under image change, distinctiveness from surrounding and distant regions, and locality of the support region used to define it. Practically, a feature is the output of running a scoring function (built from local image gradients, as in the structure tensor) over the whole image, thresholding, and applying non-maximum suppression. The vast majority of pixels — flat regions and pure edges — are excluded because their local neighborhoods cannot be reliably relocalized in another image of the same scene.

Why can't we just use every pixel and skip feature detection entirely?

Using every pixel throws away the key insight that most pixels carry no information for localization or matching — flat regions look identical to their neighbors, so matching them is either ambiguous (many equally good matches) or meaningless (any shift produces the same appearance). Feature detection concentrates computation on the small set of locations where matching is actually possible, which also makes downstream stages (correspondence search, geometric estimation via RANSAC-style methods, bundle adjustment) tractable, since they operate on hundreds of keypoints rather than millions of pixels. It is a filtering step that trades a small amount of upfront work for a massive reduction in the search space of every later stage.

How does the structure tensor relate to image gradients directly?

The structure tensor MM is built entirely from the horizontal and vertical image gradients IxI_x and IyI_y inside a small window: its entries are Gaussian-weighted sums of Ix2I_x^2, Iy2I_y^2, and IxIyI_xI_y. It is essentially a local, second-moment summary of the gradient directions present in a neighborhood — if gradients in the window all point in one direction (an edge), MM has one dominant eigenvalue; if gradients point in many directions (a corner or textured blob), MM has two comparable large eigenvalues. This is why understanding image gradients is a strict prerequisite: the entire feature-detection machinery is a structured summary of gradient behavior over a local window.

Are repeatability, distinctiveness, and locality ever in tension with each other?

Yes, and this tension is central to detector design. Increasing the window size used to describe a feature typically increases distinctiveness (more context to disambiguate the patch) but decreases locality (larger support is more sensitive to occlusion, perspective distortion, and background clutter) and can hurt repeatability under viewpoint change (a large planar patch assumption breaks down faster than a small one). Detector and descriptor design is largely an exercise in choosing window sizes, scales, and normalization schemes that balance these three properties for a given application — real-time tracking often favors locality and speed, while wide-baseline stereo matching favors distinctiveness.

Does feature detection still matter now that deep learning dominates computer vision?

Yes — the criteria matter even more than any specific classical algorithm. Modern learned keypoint detectors (SuperPoint, D2-Net, R2D2, and others) are trained end-to-end but are still evaluated by exactly the same yardsticks: do they fire at corresponding locations across viewpoint change (repeatability), do their descriptors distinguish true matches from false ones (distinctiveness), and are they computed from local receptive fields (locality)? Many production pipelines (structure-from-motion tools, AR SDKs, robotics stacks) still use classical detectors like Harris/FAST or hybrids for speed and interpretability, alongside or instead of learned alternatives, especially in resource-constrained or real-time settings.

What is the difference between detecting a feature and describing it?

Detection answers "where are the interesting locations?" — it outputs a set of pixel coordinates (and often a scale/orientation) using a local scoring function like the structure-tensor eigenvalue test. Description answers "what does this location look like, in a form I can compare against another location?" — it outputs a fixed-length vector (a descriptor) summarizing the appearance around the detected point, designed to be similar for true correspondences and different for non-matches. This article covers detection fundamentals; description and matching (as in SIFT's 128-dimensional gradient histogram descriptor) build directly on top of the keypoints that detection produces.

Why does the minimum eigenvalue matter more than the maximum for corner detection?

The maximum eigenvalue λ1\lambda_1 measures how much the window's appearance changes along the most informative direction, which can be large even for a plain edge. The minimum eigenvalue λ2\lambda_2 measures the worst-case direction — the direction in which the window is hardest to localize. A true corner requires that even this worst-case direction shows strong appearance change, since only then is the 2D position of the window fully constrained. This is why the Shi–Tomasi criterion scores features directly by min⁡(λ1,λ2)\min(\lambda_1, \lambda_2), and why Harris's score is designed to penalize exactly the large-ratio, small-λ2\lambda_2 case that characterizes edges.

Before this

Where this leads