为何cv2.NORM_HAMMING计算结果与实际汉明距离不符?
Great question! The key misunderstanding here is how BRISK descriptors are stored and how Hamming distance is computed for them in OpenCV. Let's break this down:
The Core Issue: Hamming Distance Counts Bits, Not Bytes
BRISK is a binary descriptor—each element in your des_1/des_2 arrays is a uint8 (8-bit) integer that packs 8 binary descriptor bits into a single byte.
The true Hamming distance between two binary descriptors is the total number of individual binary bits that differ between them. Your manual implementations are counting something else entirely:
len(np.where(np.abs(des_1 - des_2)>0)[0])counts how many bytes have different values (not bits).sum(el1 != el2 for el1, el2 in zip(des_1, des_2))does the same thing—counting differing bytes, not bits.
OpenCV's cv2.NORM_HAMMING correctly calculates the bit-wise Hamming distance, which is why its result differs from yours.
Let's Verify With Your Example
Take your sample descriptors:
des_1 = [180, 25, 195, 96, 96, 88, 0, 0] des_2 = [244, 27, 195, 96, 96, 192, 0, 0]
Let's compute the bit-wise differences for each differing byte:
- 180 vs 244:
- 180 in binary:
10110100 - 244 in binary:
11110100 - XOR result:
01000000→ 1 differing bit
- 180 in binary:
- 25 vs 27:
- 25 in binary:
00011001 - 27 in binary:
00011011 - XOR result:
00000010→ 1 differing bit
- 25 in binary:
- 88 vs 192:
- 88 in binary:
01011000 - 192 in binary:
11000000 - XOR result:
10011000→ 3 differing bits
- 88 in binary:
Adding these up: 1 + 1 + 3 = 5—which matches OpenCV's result of 5.0. Your manual methods counted the 3 differing bytes, hence the result of 3.
How to Correctly Compute Hamming Distance Manually
If you want to replicate OpenCV's result in pure Python/Numpy, you need to count the number of set bits (1s) in the bit-wise XOR of the two descriptors:
import numpy as np des_1 = np.array([180, 25, 195, 96, 96, 88, 0, 0], dtype=np.uint8) des_2 = np.array([244, 27, 195, 96, 96, 192, 0, 0], dtype=np.uint8) # Compute bit-wise XOR xor_result = np.bitwise_xor(des_1, des_2) # Count total number of 1 bits across all bytes correct_hamming_dist = np.sum(np.unpackbits(xor_result)) print(correct_hamming_dist) # Output: 5
This will give you the same result as cv2.norm(des_1, des_2, cv2.NORM_HAMMING).
Applying This to Your Original Problem
For your first case where OpenCV returned 87.0 and your methods returned 43, the explanation is identical: your code counted 43 differing bytes, while OpenCV counted the total number of differing bits across all those bytes (summing to 87).
内容的提问来源于stack exchange,提问作者Hasnat

