使用average_hash计算图片相似出现大量欧氏距离为0误识别求助
核心问题根源
你出现大量误判的核心原因是对存储为字符串的哈希值直接执行了数值运算逻辑,具体问题如下:
- 你在表中将
photo_hash定义为TEXT类型,存储的是十六进制格式的字符串。而MySQL的^异或运算符、BIT_COUNT函数都是针对数值类型生效的,执行运算时会自动将字符串尝试转为十进制整数:你的哈希字符串以0f开头,遇到字母f时转换直接截断,最终得到的数值为0,所有哈希运算后结果都为0,自然会出现海量距离为0的误判。 - 平均哈希(average_hash)本身抗干扰性较弱,图片缩放、轻微亮度调整都可能导致哈希偏差,本身也更容易出现碰撞。
修复步骤
1. 调整表结构
average_hash生成的是64位哈希值,完全可以用UNSIGNED BIGINT类型存储,替代原有的TEXT类型,既节省空间也符合运算要求:
ALTER TABLE photos MODIFY COLUMN photo_hash BIGINT UNSIGNED NOT NULL;
如果后续要换用更长的感知哈希(比如128位phash),可以改用BINARY(16)类型存储。
2. 调整插入逻辑
插入前先将十六进制格式的哈希字符串转为整数再存入数据库,Python端修改代码如下:
# 把十六进制哈希转成整数再插入 hash_int = int(str(result_image_recognition['photo_hash']), 16) cur.execute('''INSERT INTO photos(id_photo, photo_hash) VALUES(%s, %s)''', (id, hash_int))
3. 调整查询逻辑
查询时先将待匹配的哈希字符串转为无符号整数,再执行距离计算:
SELECT id_photo, BIT_COUNT(photo_hash ^ CAST(CONV('0f3f2764ecc482c2', 16, 10) AS UNSIGNED)) AS hamming_distance FROM photos;
注意:这里的距离是汉明距离,不是欧氏距离,汉明距离小于等于5通常可以判定为相似图片
额外优化建议
如果想要进一步降低碰撞概率,可以做如下调整:
- 替换平均哈希为精度更高的感知哈希(phash)或者差异哈希(dhash),相同误判率下识别准确率更高
- 同时存储两种不同的哈希值,只有两种哈希的汉明距离都低于阈值时才判定为相似,可将碰撞概率降低几个数量级
内容的提问来源于stack exchange,提问作者user3391185
相关产品推荐
相关产品推荐

