基于感知哈希的相似图片过滤设计

用户屏蔽一张图片后,同一张图片的裁剪版、压缩版或轻微调色版仍可能出现。只按内容编号屏蔽,很难覆盖这些视觉上接近的素材。

本文用一个假设的信息流场景讨论相似图片过滤,不对应特定公司或产品的实现。

把视觉相似变成候选判断

感知哈希将图片映射为固定长度的指纹。与用于文件完整性检查的密码学哈希不同,它希望相似图片的指纹保持接近。

pHash 是一种常见选择。两张图片的指纹可以通过汉明距离比较,即统计不同的二进制位:

hamming_distance(a, b) = popcount(a XOR b)

距离较小只能说明指纹接近,不等于图片在语义上相同。对裁剪、文字叠加或大幅修改的效果,也需要用真实样本验证。

过滤放在哪一层

候选阶段过滤,能减少后续计算,但前提是这一阶段已经有图片粒度的信息。若一个候选包含多张图片,直接丢弃整个候选可能过于粗糙。

素材展开后过滤,可以只移除相似图片,保留其他可用素材。不过需要继续处理“素材全部被移除”的情况,并保证后面的排序流程接受过滤后的集合。

最终选图后过滤改动较小,但可能导致候选数量不足。应明确补位、重新选图或返回更少结果的策略,避免无界重试。

指纹生成与在线查询

指纹适合在素材入库时生成,并记录算法版本。在线请求读取预计算结果,避免重复解码图片。

设一次请求有 C 张候选图片,用户记录中有 B 个屏蔽指纹,直接比较需要约 C×B 次判断。记录较少时可以先采用简单扫描;规模增加后,再考虑支持汉明距离查询的索引。

for candidate in image_candidates:
fingerprint = load_fingerprint(candidate)
if fingerprint is missing:
apply_documented_fallback(candidate)
continue
blocked = any(
hamming_distance(fingerprint, record.fingerprint) <= threshold
for record in compatible_block_records
)
if not blocked:
keep(candidate)

缺失指纹与算法版本不兼容时的行为要写清楚,而不是默认所有记录都可比较。

阈值要用样本选择

阈值过小会漏掉相似图片,过大又会误伤不相干的图片。应建立正负样本集,观察误过滤和漏过滤,同时覆盖不同图片类型。

不要直接照搬其他系统的阈值。指纹长度、预处理方式、素材分布和产品对误伤的容忍度都会影响选择。

验收看哪些指标

除命中量外,还要看用户再次遇到已屏蔽素材的比例、正常素材误过滤率、结果不足率和请求延迟。

可以先做离线回放,再采用影子计算观察差异,最后小范围启用。本文不提供线上收益数字;没有明确实验口径时,过滤次数本身不能证明体验改善。


← Posts