This tutorial demonstrates local feature detection and matching techniques using OpenCV - fundamental operations in visual SLAM systems.
Local features are distinct, repeatable patterns in images that can be detected and matched across different viewpoints. In SLAM, they are used for:
- Visual Odometry: Tracking camera motion between consecutive frames
- Loop Closure Detection: Recognizing previously visited locations
- Place Recognition: Matching images to a pre-built map
- Stereo Matching: Finding correspondences between stereo image pairs
Type: Corner detector (no descriptor)
FAST is an extremely efficient corner detector designed for real-time applications.
How it works:
- For each pixel p, examine 16 pixels in a circle of radius 3
- If N contiguous pixels are all brighter (or darker) than p by threshold t, p is a corner
- Common variants: FAST-9 (N=9), FAST-12 (N=12)
Characteristics:
- Very fast (suitable for real-time SLAM)
- High repeatability
- No orientation or scale information
- Typically combined with other descriptors (e.g., ORB uses FAST + BRIEF)
SLAM Usage: ORB-SLAM, PTAM, LSD-SLAM (for initialization)
Type: Detector + Binary descriptor
ORB combines FAST keypoint detection with BRIEF descriptors, adding rotation invariance.
How it works:
- Detect keypoints using FAST at multiple scales (image pyramid)
- Compute orientation using intensity centroid
- Compute rotation-invariant BRIEF descriptor (256-bit binary)
Characteristics:
- Fast computation (real-time capable)
- Rotation invariant
- Scale invariant (via pyramid)
- Binary descriptor - fast matching with Hamming distance
- Free and patent-unencumbered
SLAM Usage: ORB-SLAM, ORB-SLAM2, ORB-SLAM3 (primary feature)
Type: Detector + Float descriptor
SIFT detects blob-like features and computes a highly distinctive 128-dimensional descriptor.
How it works:
- Build scale-space using Difference of Gaussians (DoG)
- Detect extrema in scale-space
- Refine keypoint location and reject low-contrast/edge points
- Assign orientation based on gradient histogram
- Compute 128-dim descriptor from gradient orientations
Characteristics:
- Highly distinctive descriptors
- Scale and rotation invariant
- Robust to illumination changes
- Slower than binary descriptors
- Higher memory usage (128 floats per keypoint)
SLAM Usage: Structure-from-Motion, offline 3D reconstruction, loop closure
Type: Binary descriptor (requires separate detector like FAST)
TEBLID uses machine learning to select optimal binary tests, achieving better accuracy than hand-crafted binary descriptors like BRIEF/ORB.
How it works:
- Use FAST or other detector for keypoints
- Extract patch around each keypoint
- Apply learned binary tests (boosting-selected)
- Output 256-bit or 512-bit binary descriptor
Characteristics:
- Binary descriptor - fast Hamming distance matching
- Better accuracy than ORB's BRIEF descriptor
- Approaches SIFT-like matching quality
- Requires OpenCV contrib modules (xfeatures2d)
SLAM Usage: Real-time SLAM where ORB accuracy is insufficient but SIFT is too slow
The simplest matching approach - compares each descriptor in set A with every descriptor in set B.
Distance Metrics:
NORM_L2: Euclidean distance (for float descriptors like SIFT)NORM_HAMMING: Hamming distance (for binary descriptors like ORB, BRIEF)
Complexity: O(N * M) where N, M are the number of descriptors
FLANN uses spatial data structures for efficient approximate matching.
For float descriptors (SIFT):
- Uses KD-trees for fast nearest neighbor search
- Configurable accuracy/speed trade-off
For binary descriptors (ORB):
- Uses LSH (Locality Sensitive Hashing)
- Parameters: table_number, key_size, multi_probe_level
Complexity: O(N * log(M)) average case
Match each descriptor to its nearest neighbor. Fast but prone to false matches.
Compare distance to best match vs second-best match:
if (best_distance < ratio * second_best_distance):
accept match
Typical ratio: 0.7-0.8. Rejects ambiguous matches.
A matches B AND B matches A. Ensures mutual consistency.
Demonstrates FAST, ORB, and SIFT feature detection on synthetic images. Compares:
- Number of keypoints detected
- Detection time
- Keypoint distribution
Demonstrates feature matching between image pairs using:
- BFMatcher with distance threshold
- BFMatcher with ratio test
- FLANN-based matching
- Cross-check matching
Comprehensive profiling comparing ORB, SIFT, and FAST+TEBLID using easy_profiler:
- Detailed timing breakdown (Create, Detect, Compute, Match, Visualize)
- Matching quality comparison
- Saves profiling data to
feature_profiling.prof(view withprofiler_gui) - Generates visualization images for each method
Dependencies: OpenCV 4.x with contrib, easy_profiler (included in base image)
mkdir build && cd build
cmake ..
make -j4# Build base image first (from SLAM_zero_to_hero root)
docker build . -t slam:base
# Build this tutorial
cd 2_3
docker build . -t slam_zero_to_hero:2_3# Feature detection demo
./build/feature_detection
# Feature matching demo (uses synthetic images)
./build/feature_matching
# Feature profiling (ORB vs SIFT vs FAST+TEBLID)
./build/feature_profiling
# With custom images (optional)
./build/feature_matching /path/to/image1.png /path/to/image2.png
./build/feature_profiling /path/to/image1.png /path/to/image2.png# Run with X11 forwarding for visualization
docker run -it --rm \
--env DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix:ro \
slam_zero_to_hero:2_3
# Inside container
./feature_detection
./feature_matching
./feature_profiling// Feature detectors
cv::Ptr<cv::FastFeatureDetector> fast = cv::FastFeatureDetector::create(threshold);
cv::Ptr<cv::ORB> orb = cv::ORB::create(nfeatures);
cv::Ptr<cv::SIFT> sift = cv::SIFT::create();
// Detection
detector->detect(image, keypoints);
detector->detectAndCompute(image, mask, keypoints, descriptors);
// Matchers
cv::Ptr<cv::BFMatcher> bf = cv::BFMatcher::create(cv::NORM_HAMMING); // For ORB
cv::Ptr<cv::BFMatcher> bf = cv::BFMatcher::create(cv::NORM_L2); // For SIFT
// FLANN for ORB (LSH)
cv::FlannBasedMatcher flann(cv::makePtr<cv::flann::LshIndexParams>(12, 20, 2));
// FLANN for SIFT (KD-Tree)
cv::FlannBasedMatcher flann(cv::makePtr<cv::flann::KDTreeIndexParams>(5));
// Matching
matcher->match(desc1, desc2, matches); // Simple match
matcher->knnMatch(desc1, desc2, knn_matches, 2); // KNN for ratio test- Prefer ORB/FAST for real-time visual odometry (30+ FPS)
- SIFT acceptable for offline processing or loop closure
- Use grid-based detection or adaptive thresholds
- Ensure features cover entire image (not clustered in one region)
After matching, use geometric verification:
- RANSAC with fundamental/essential matrix
- Epipolar constraint checking
- Binary descriptors (ORB): 32 bytes per keypoint
- Float descriptors (SIFT): 512 bytes per keypoint
- Consider memory for large-scale mapping
| Feature | Detection Speed | Descriptor Size | Matching Speed | Distinctiveness |
|---|---|---|---|---|
| FAST | Very Fast | N/A | N/A | Low |
| ORB | Fast | 32 bytes | Fast (Hamming) | Medium |
| FAST+TEBLID | Fast | 32 bytes | Fast (Hamming) | Medium-High |
| SIFT | Slow | 512 bytes | Slower (L2) | High |
Note: FAST+TEBLID combines the speed of binary descriptors with improved matching accuracy, making it an excellent choice for real-time SLAM applications where ORB's accuracy is insufficient.
- ORB-SLAM Paper
- SIFT Paper (Lowe, 2004)
- FAST Paper
- TEBLID Paper - Boosted Local Image Descriptors
- OpenCV Feature Detection Tutorial
- OpenCV xfeatures2d (contrib)