OpenCV中计算汉明距离最直接方式是cv::norm配合NORM_HAMMING,要求输入为CV_8UC1类型且长度相等;NORM_HAMMING2适用于16位数据但极少使用;手写循环通常比优化后的cv::norm慢3–5倍。

OpenCV里用cv::norm算汉明距离最直接
汉明距离只适用于二进制向量(每个元素是0或1),OpenCV不提供独立的cv::hammingDistance函数,但cv::norm支持NORM_HAMMING和NORM_HAMMING2两种模式,这是官方推荐且性能最优的方式。
注意:输入必须是CV_8U类型(即uchar),不能是float或int;长度必须相等,否则cv::norm会崩溃或返回错误结果。
-
NORM_HAMMING:适用于8位字节,逐字节异或后数1的个数(即每个字节最多贡献8) -
NORM_HAMMING2:适用于16位(如cv::Mat类型为CV_8UC2),每两个字节打包成一个16位单元再计算,实际使用极少 - 如果特征向量来自
cv::ORB或cv::BRIEF,默认输出就是CV_8UC1,可直接用NORM_HAMMING
cv::Mat desc1 = ...; // e.g., ORB descriptor, size: 1x32, type: CV_8UC1 cv::Mat desc2 = ...; double dist = cv::norm(desc1, desc2, cv::NORM_HAMMING);
手写循环实现能控制细节,但别轻易替代cv::norm
手动遍历+异或+查表(popcount)在特定场景下有用,比如你想跳过某些维度、加mask、或调试中间过程。但OpenCV的cv::norm底层用了SSE/AVX优化,自己写的循环通常慢3–5倍。
常见翻车点:
- 用
int或unsigned char*指针遍历时没确认step和连续性(isContinuous()),导致越界读取 - 误把
CV_32F描述子强转为uchar*——数值会被截断,结果完全不可信 - 查表法用256项
int popcount[256]是对的,但有人写成char数组导致溢出
真要手写,确保:
cv::norm
- 用
cv::BFMatcher(cv::NORM_HAMMING),传入CV_8UC1描述子,比手写双循环快5–10倍 -
match()返回的是std::vector<:dmatch>,其中DMatch::distance就是汉明距离 - 如果只需最近邻,开
crossCheck=true;如果要k近邻,用knnMatch()
cv::BFMatcher matcher(cv::NORM_HAMMING); std::vector<:dmatch> matches; matcher.match(desc_query, desc_train, matches); // matches[0].distance 是第一个匹配的汉明距离 </:dmatch>
容易被忽略的类型与内存布局陷阱
汉明距离计算对数据布局极其敏感。最常被忽略的是:
-
cv::Mat可能不是连续内存(例如从ROI创建),cv::norm内部会自动处理,但手写循环必须检查isContinuous()或用reshape(1,1)展平 - Python OpenCV(cv2)中
cv2.NORM_HAMMING行为一致,但numpy array若为np.int32类型,传给cv2.norm会静默转成uint8,导致结果错乱 - ORB默认描述子长度是32字节(256维),但如果你用
scoreType=ORB::HARRIS_SCORE并设了nfeatures=10,描述子矩阵是10x32,而单个描述子需取row(i)而非col(i)——行优先布局别搞反
验证是否正确最简单的方法:用两个全零和一个单比特不同的向量做单元测试,看结果是不是1。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











