Computer Vision Chapter 13

ORB

ORB (Oriented FAST and Rotated BRIEF) combines fast corner detection with a binary descriptor that is steered using a dominant orientation—giving rotation awareness while staying efficient. Descriptors are matched with Hamming distance (XOR + bit count). ORB is a practical default for real-time SLAM demos, AR overlays, and embedded vision when SIFT is too heavy.

What ORB builds on

  • FAST: compares pixels on a circle around the candidate—very fast corner score.
  • Orientation: intensity centroid offset gives a main angle per keypoint.
  • rBRIEF: pairwise intensity tests in a rotated pattern → fixed-length binary string (often 256 bits = 32 bytes in OpenCV).

ORB_create parameters

import cv2

orb = cv2.ORB_create(
    nfeatures=1000,
    scaleFactor=1.2,
    nlevels=8,
    edgeThreshold=31,
    firstLevel=0,
    WTA_K=2,
    scoreType=0,
    patchSize=31,
    fastThreshold=20,
)

scaleFactor, nlevels

Pyramid decimation between levels; more levels → wider scale coverage, more compute.

fastThreshold

FAST intensity difference threshold; lower → more corners (noisier).

Two detector score modes

# scoreType: 0 = HARRIS_SCORE (default), 1 = FAST_SCORE
orb_harris = cv2.ORB_create(scoreType=0)
orb_fast = cv2.ORB_create(scoreType=1)

Harris scoring re-ranks FAST corners for stability; FAST-only is a bit cheaper.

Detect, compute, Hamming match

import cv2

g1 = cv2.imread("view1.jpg", cv2.IMREAD_GRAYSCALE)
g2 = cv2.imread("view2.jpg", cv2.IMREAD_GRAYSCALE)
orb = cv2.ORB_create(800)
k1, d1 = orb.detectAndCompute(g1, None)
k2, d2 = orb.detectAndCompute(g2, None)

bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = sorted(bf.match(d1, d2), key=lambda m: m.distance)
vis = cv2.drawMatches(g1, k1, g2, k2, matches[:60], None, flags=2)

kNN + ratio (often stronger than crossCheck alone)

bf2 = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=False)
pairs = bf2.knnMatch(d1, d2, k=2)
good = [m for m, n in pairs if m.distance < 0.75 * n.distance]

Homography from ORB matches

After matching, use RANSAC to estimate a plane-to-plane map—starter for panoramas or planar object detection.

import cv2
import numpy as np

if len(good) >= 4:
    pts1 = np.float32([k1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
    pts2 = np.float32([k2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
    H, mask = cv2.findHomography(pts1, pts2, cv2.RANSAC, 5.0)
    # H maps points from image 1 to image 2 (convention: check OpenCV docs)

ORB vs SIFT (quick)

ORB: integer-friendly, smaller memory, Hamming match, faster. SIFT: float 128-D, usually more repeatable under hard viewpoint/scale changes, slower. Pick ORB for speed-first; fall back to SIFT when recall matters more.

Takeaways

  • Always match ORB with NORM_HAMMING (or NORM_HAMMING2 if using WTA_K=3 or 4).
  • Tune fastThreshold and nfeatures together for density vs speed.
  • Combine ratio test + findHomography RANSAC for geometrically consistent matches.

Quick FAQ

FAST is sensitive to ordering and noise; JPEG artifacts and exposure shifts move scores. For repeatability tests, use the same decode path and mild blur.

Convert to grayscale before detectAndCompute unless you use a custom pipeline; ORB in OpenCV expects single-channel input.