ORB Features

What is ORB?

ORB: Oriented FAST and Rotated BRIEF

Combination:

  • FAST: Corner detection
  • BRIEF: Binary descriptor
  • Additions: Orientation, scale pyramid

Advantages:

  • Very fast (real-time capable)
  • Binary descriptor (fast matching)
  • Free and open-source
  • Good performance

Use case: Mobile devices, embedded systems, real-time applications

ORB Algorithm

Steps:

  1. FAST keypoint detection: Find corners quickly
  2. Harris corner measure: Rank and keep top N
  3. Scale pyramid: Multi-scale detection
  4. Orientation assignment: Intensity centroid method
  5. Rotated BRIEF: Compute binary descriptor aligned with orientation

FAST Detector in ORB

FAST: Features from Accelerated Segment Test

Method:

  • Check 16 pixels in circle around candidate
  • If N consecutive pixels brighter/darker → corner
  • Very fast (simple comparisons)

ORB improvement: Harris measure to rank corners

Orientation Assignment

Problem: BRIEF not rotation invariant

Solution: Compute orientation, rotate BRIEF pattern

Intensity centroid method:

  1. Compute moments: m_pq = Σ x^p × y^q × I(x,y)
  2. Find centroid: C = (m10/m00, m01/m00)
  3. Orientation: θ = atan2(m01, m10)

Result: Rotation-invariant descriptor

BRIEF Descriptor

BRIEF: Binary Robust Independent Elementary Features

Method:

  1. Select pairs of pixels in patch
  2. Compare intensities: I(p1) < I(p2) → 0 or 1
  3. Concatenate bits → binary string

256 bits: 256 pixel pairs → 256 comparisons

Advantage: Very fast to compute and match (XOR + bit count)

ORB Parameters

  1. import cv2
  2. # create ORB detector
  3. #ans: orb = cv2.ORB_create()
  4. # detailed parameters
  5. #ans: orb = cv2.ORB_create(nfeatures=500, scaleFactor=1.2, nlevels=8, edgeThreshold=31, firstLevel=0, WTA_K=2, scoreType=cv2.ORB_HARRIS_SCORE, patchSize=31, fastThreshold=20)
  6. # nfeatures: max keypoints to retain
  7. #ans: 500 strongest features
  8. # scaleFactor: pyramid scale factor
  9. #ans: 1.2 means each level is 1/1.2 = 83% of previous
  10. # nlevels: number of pyramid levels
  11. #ans: 8 levels for multi-scale detection

ORB Detection

  1. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  2. orb = cv2.ORB_create(nfeatures=1000)
  3. # detect keypoints only
  4. #ans: keypoints = orb.detect(gray, None)
  5. # detect and compute descriptors
  6. #ans: keypoints, descriptors = orb.detectAndCompute(gray, None)
  7. # descriptor is binary
  8. #ans: print(descriptors.shape) # (N, 32) - 32 bytes = 256 bits
  9. #ans: print(descriptors.dtype) # uint8

Drawing ORB Keypoints

  1. orb = cv2.ORB_create()
  2. kp, des = orb.detectAndCompute(gray, None)
  3. # simple keypoint drawing
  4. #ans: img_kp = cv2.drawKeypoints(img, kp, None, color=(0, 255, 0))
  5. # rich keypoints (with size and orientation)
  6. #ans: img_kp = cv2.drawKeypoints(img, kp, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
  7. #ans: circles show scale, lines show orientation

ORB Matching

Distance metric: Hamming distance (count differing bits)

Fast matching: XOR operation + bit count

  1. # create ORB matcher (Hamming distance)
  2. #ans: bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
  3. # detect in two images
  4. orb = cv2.ORB_create()
  5. kp1, des1 = orb.detectAndCompute(gray1, None)
  6. kp2, des2 = orb.detectAndCompute(gray2, None)
  7. # match
  8. #ans: matches = bf.match(des1, des2)
  9. #ans: matches = sorted(matches, key=lambda x: x.distance)

ORB vs SIFT

ORB advantages:

  • Speed: 10-100× faster
  • Binary: Fast matching (Hamming)
  • Free: No patent issues
  • Memory: 32 bytes vs 512 bytes (SIFT)

SIFT advantages:

  • Accuracy: More distinctive
  • Robustness: Better invariance
  • Difficult scenes: Performs better

Choice: ORB for speed, SIFT for accuracy

Scale Pyramid

Why pyramid?

  • Detect features at multiple scales
  • Same feature may appear different sizes

ORB pyramid:

nlevels=8, scaleFactor=1.2: 8 scales from 100% to ~23%

WTA_K Parameter

WTA_K: Number of points in BRIEF test

Options:

  • WTA_K=2: Compare 2 points (default, 256 bits)
  • WTA_K=3: Compare 3 points (more robust, 512 bits)
  • WTA_K=4: Compare 4 points (even more robust, 512 bits)

Trade-off: Robustness vs speed/memory

Exercises - Part 1 (Concepts)

  1. # what does ORB stand for?
  2. #ans: Oriented FAST and Rotated BRIEF
  3. # what detector does ORB use?
  4. #ans: FAST corner detector
  5. # what descriptor does ORB use?
  6. #ans: BRIEF binary descriptor (rotated)
  7. # how many bits in ORB descriptor?
  8. #ans: 256 bits (32 bytes)
  9. # what distance metric for ORB?
  10. #ans: Hamming distance (count differing bits)

Exercises - Part 2 (Concepts)

  1. # why ORB is fast?
  2. #ans: binary descriptor, simple comparisons, fast matching
  3. # how does ORB handle rotation?
  4. #ans: assigns orientation using intensity centroid
  5. # what is scaleFactor?
  6. #ans: pyramid scale ratio between levels
  7. # advantage of binary descriptors?
  8. #ans: fast to compute and match (XOR + bit count)
  9. # ORB vs SIFT trade-off?
  10. #ans: ORB faster but less accurate, SIFT slower but more robust

Exercises - Part 3 (Coding)

  1. # create ORB with 2000 features
  2. #ans: orb = cv2.ORB_create(nfeatures=2000)
  3. # detect and compute
  4. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  5. #ans: keypoints, descriptors = orb.detectAndCompute(gray, None)
  6. # check descriptor shape
  7. #ans: print(descriptors.shape) # (N, 32)
  8. # create Hamming matcher
  9. #ans: bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

Exercises - Part 4 (Coding)

  1. # match ORB features
  2. orb = cv2.ORB_create()
  3. kp1, des1 = orb.detectAndCompute(gray1, None)
  4. kp2, des2 = orb.detectAndCompute(gray2, None)
  5. bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
  6. #ans: matches = bf.match(des1, des2)
  7. #ans: matches = sorted(matches, key=lambda x: x.distance)
  8. #ans: img_matches = cv2.drawMatches(img1, kp1, img2, kp2, matches[:50], None, flags=2)

Exercises - Part 5 (Mixed)

  1. # ORB with more pyramid levels
  2. #ans: orb = cv2.ORB_create(nlevels=12, scaleFactor=1.2)
  3. #ans: 12 levels for wider scale range
  4. # draw rich keypoints
  5. orb = cv2.ORB_create()
  6. kp, des = orb.detectAndCompute(gray, None)
  7. #ans: img_kp = cv2.drawKeypoints(img, kp, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
  8. # ORB with WTA_K=3
  9. #ans: orb = cv2.ORB_create(WTA_K=3)
  10. #ans: more robust descriptor, larger size

Google tag (gtag.js)