Implement feature matching using Hamming distance for binary descriptors. This task involves finding the best matches between two sets of binary feature descriptors.
The Hamming distance is a measure of the number of positions at which two binary strings differ, given by dH(a,b)=∑iai⊕bi. It is used to compare the similarity between binary descriptors.
To perform matching:
For each descriptor in set A, find the nearest neighbor in set B
Apply the ratio test: accept if best_dist/second_best_dist<threshold
If desc2 has only one descriptor, there is no second best: always accept the match.
If the second-best distance is 0 (two or more exact matches), the match is ambiguous: reject it.
Return matches as (idx1, idx2, distance) tuples with an integer distance, in the order of desc1.
dH(a,b)=i∑ai⊕bi
This technique is widely used in computer vision for feature matching and object recognition.
desc1 holds 2 descriptors and desc2 holds 3, each a row of D=4 bits. A match pairs a row of desc1 with its closest row of desc2, measured in differing bits.
Descriptor 0, a=[1,0,1,0]: it differs from [1,0,1,1] only in the last bit (dH=1), from [0,0,0,0] in bits 0 and 2 (dH=2), and from [0,1,0,1] in all four (dH=4).
Best is 1 (row 0), second best is 2, so the ratio is 1/2=0.5<0.75 and the match (0, 0, 1) is accepted.
Descriptor 1, a=[0,1,0,1]: the distances are 3, 2 and 0. Best is 0 (row 2), second best is 2, ratio 0/2=0<0.75, giving (1, 2, 0).
Each tuple is (index in desc1, index in desc2, integer bit count), listed in desc1 order.
Notice the ratio test rewards distinctiveness, not just closeness: had descriptor 0's runner-up also been at distance 1, the ratio 1/1=1 would reject it even though a 1-bit match exists.
Constraints
desc1: Binary descriptors from image 1 (N1, D)
desc2: Binary descriptors from image 2 (N2, D)
ratio_threshold: Ratio test threshold (default 0.75)
You’re implementing brute-force feature matching for binary descriptors using Hamming distance plus Lowe’s ratio test. Conceptually, this is exactly how ORB/BRIEF/FREAK descriptors are typically matched in CV libraries: binary descriptors are compared bitwise, and nearest-neighbor matches are accepted only if the best match is clearly better than the second best (ratio test), which helps reject ambiguous or repetitive features.
Binary descriptors encode local image patterns as bit strings (e.g., 256 bits), where each bit is the result of a simple intensity comparison test around a keypoint. Matching then becomes efficient because Hamming distance can be computed with a fast XOR + popcount on machine words. The ratio test, introduced by Lowe in SIFT, generalizes here: even though SIFT uses Euclidean distance and ORB/BRIEF use Hamming, the idea is the same—features that have similarly good multiple matches are unreliable and should be discarded.
1. Background Knowledge
Binary descriptors & Hamming distance
A binary descriptor is a fixed-length bit vector, often represented as an array of bytes/ints. The Hamming distance between two descriptors a and b of the same length is:
dH(a,b)=i∑(ai⊕bi)
where ai⊕bi=1 if bits differ and 0 otherwise, so dH counts differing bits.
Nearest-neighbor matching
Given two sets of descriptors A={a1,…,am} and B = \{b_1,\dots,b_n\},asimplematcherfinds,foreacha_i,the∗∗nearestneighbor∗∗inBw.r.t.Hammingdistance(andalsothesecondnearest).Thisisusuallydoneviaabrute−forcescanoveralldescriptorsinB$.
Lowe’s ratio test for ambiguity
Many keypoints may look similar (e.g., in repetitive textures). If the best and second-best matches have very similar distances, the match is ambiguous. Lowe’s ratio test keeps a match only if:
second_best_distbest_dist<threshold
Typical thresholds are around 0.7–0.8 (problem may specify). This dramatically reduces false matches, at the cost of discarding some good ones.
2. Algorithm / General Approach
The standard pattern for binary descriptor matching with ratio test:
For each descriptor in A, compare it to all descriptors in B.
Compute Hamming distance for each pair using XOR + popcount over all words of the descriptor.
Track the smallest and second smallest distances for that query descriptor.
Apply ratio test: if best_dist / second_best_dist < threshold, accept the pair (index_in_A, index_of_best_in_B) as a match.
Collect all accepted matches into a list.
This is a brute-force O(∣A∣⋅∣B∣) NN search in Hamming space, which is acceptable for typical contest constraints unless the sets are huge.
3. Step-by-Step Strategy
Assume you have:
A: list/array of descriptors, shape [NA][D]
B: list/array of descriptors, shape [NB][D]
Where each descriptor is a binary string stored as bytes/ints (e.g., vector<uint8_t> or vector<uint32_t>).
Step 1: Hamming distance function
Implement a function to compute Hamming distance between two descriptors:
Represent each descriptor as an array of machine words (8-bit/32-bit/64-bit).
For each word index k:
xor_word = a[k] ^ b[k]
count += popcount(xor_word) (use built-in bit-popcount if available).
Return the total count.
Example in C++-like pseudocode:
int hammingDist(const uint8_t* a, const uint8_t* b, int bytes) {
int dist = 0;
for (int i = 0; i < bytes; ++i) {
uint8_t x = a[i] ^ b[i];
dist += __builtin_popcount((unsigned)x); // or custom popcount
}
return dist;
}
PRO
Continue the full explanation
You're reading the free preview. Unlock the complete walkthrough, the code editor, test runner and reference solution with Premium.
PRO
Editor locked
The code editor is locked for Pro problems. It is only available for free problems. Please upgrade to gain access to the code editor for all problems.