城市动物管理局的老周,经营着一家毛孩子走失招领中心。曾经,墙上挂满上千张寻猫照片,主人来问「见过我家咪咪吗」,大家只能眼巴巴地翻照片墙,找得头晕眼花。后来中心引进了一套「数码指纹」系统:每只登记进门的毛孩子先拍照片,再被压成一行 0/1 组成的小码——这串码就是图像的「视觉指纹」。主人再来寻猫时,只要递上照片,系统几秒钟就能从档案库里捞出一串候选。墙上的照片墙,就这样变成了一个轻快的翻卡片游戏。故事背后的技术,就是「视觉特征哈希」:用感知哈希或深度哈希把图像压成一小段哈希码,再用汉明距离快速比较两张图像的相似程度。这篇文章从毛孩子登记处的特征速写讲起,一路聊到指纹仪、AI 画师、汉明尺和碰撞消歧,最后给你一整套以图搜图的工程实现思路。

岗位关联

以图搜图是电商、内容社区、版权治理里最高频的多模态检索需求之一。掌握视觉特征哈希,意味着你能在亿级图像库上做出毫秒级相似检索系统,这是检索与推荐方向 AI 工程师的核心硬技能之一。

目录
  1. 可视化演示
  2. 图像特征提取:从速写卡到 AI 画师
  3. 感知哈希原理:把照片压成指纹条码
  4. 深度哈希学习:AI 画师定制指纹
  5. 汉明距离检索:老警官的汉明尺
  6. 碰撞消歧策略:指纹撞车怎么办
  7. 系统实现方案:搭一座寻亲服务大厅
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示以图搜图三大核心:pHash感知哈希生成(图像缩放DCT变换中位数阈值二值化生成64bit指纹)、汉明距离检索(查询哈希与数据库哈希XOR比较popcount统计按距离排序)、深度哈希与碰撞处理(CNN特征提取Multi-probe LSH多探针Re-rank重排),三模式切换理解以图搜图全流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

'+C1+'

图像特征提取:从速写卡到 AI 画师

招领中心的每个毛孩子进门登记,管理员都会在「特征速写卡」上快速记几笔:通体橘色、虎斑条纹、竖耳、粗尾。这些速写不是照片,却抓住了找猫时最常用的线索。计算机想「看懂」一张图,同样要先做这种速写——这就是图像特征提取。

最早的速写员是「颜色直方图」:它把整张图拆成一堆调色盒,统计每种颜色占多少比例。橘猫多还是白猫多,一数便知。但它只记颜色占比,完全不记颜色长在哪里,光照一变化,同一只猫的「色卡」就漂移了。接着出现「纹理特征」,用花纹的疏密、方向、重复模式来描线,比如虎斑的走向、毛发的卷曲度,可比单纯数颜色更抗造一些。

这些手写特征面对真实世界还是太脆弱。后来人们使用卷积神经网络(CNN),让网络从海量图库中自己学出「AI 画师速写」——深度特征向量。一张图通过 CNN 后变成一个几百维的浮点向量,每一维都隐含着「有没有球状物」「有没有竖条纹」这类语义信号。它不再描述具体像素,而是描述「图像大概是什么」。

速写卡决定了管理员好不好找猫;同理,特征决定了以图搜图的天花板。但一张卡密密麻麻写一百个特征太慢,后面我们会看到,招领中心真正用的不是「速写卡」,而是把速写再压成一行指纹条码。

H(c)=1N∑i=1N1[pixeli=c]\displaystyle H(c)=\frac{1}{N}\sum_{i=1}^{N}\mathbb{1}[\text{pixel}_i=c]
这个公式就是颜色直方图的「数颜色比例」操作:统计整张图里颜色 c 占多大比重。
  1. 总像素数 NN 是图像所有像素的个数,作为归一化基准。
    N\displaystyle N
  2. 指示函数\mathbb{1}[\text{pixel}_i=c] 是数学里的「开关」:第 i 个像素颜色恰好等于 c 时取 1,否则取 0。
    1[pixeli=c]\displaystyle \mathbb{1}[\text{pixel}_i=c]
  3. 累加求和\sum_{i=1}^{N} 把所有「命中 c」的像素逐个累加起来,得到颜色 c 出现的总次数。
    ∑i=1N\displaystyle \sum_{i=1}^{N}
  4. 归一化比例\frac{1}{N} 把次数换算成占比,得到颜色 c 在整图中的频率。
    1N\displaystyle \frac{1}{N}

感知哈希原理:把照片压成指纹条码

速写卡好用,但比对时还是太慢。老周决定给每张登记照做一张「简化指纹条码」——这就是感知哈希的直觉:把图像压成一小串 0/1,只保留「长得像不像」的最粗线条。

感知哈希最常见的三个变体是均值哈希(aHash)、差值哈希(dHash)和感知哈希(pHash)。以 aHash 为例,它先不管色彩细节,把任意尺寸的照片塞进 8×8 的灰色小格子(压缩采样),然后求 64 个灰度的平均值,再逐个格子与平均值比较:比均值亮记 1,比均值暗记 0。最终得到一串 64 位 0/1 码——这就是视觉指纹。dHash 则是比较相邻列的亮度差:右边比左边亮记 1,否则记 0;pHash 先把图像做离散余弦变换(DCT),再在频域里做同样的均值比较。三者都遵循同一个哲学:丢掉高频细节,只留明暗分布骨架。

这串指纹对缩放、轻微裁剪、调亮度、轻压缩都不太敏感——它丢掉了高频细节,只留「明暗分布骨架」。两段指纹的汉明距离若很小,就说明两张图「骨架一致」。但固定模板也有局限:猫换个角度、换个姿势,指纹就变了。于是招领中心决定培训一批「AI 画师」。

μ=164∑i=164Ii,hi={1,Ii>μ0,Ii≤μ\displaystyle \mu=\frac{1}{64}\sum_{i=1}^{64}I_i,\qquad h_i=\begin{cases}1,& I_i>\mu\\0,& I_i\le\mu\end{cases}
平均哈希的核心就两件事:先算 64 个格子的平均亮度,再逐格比较「亮于均值」还是「暗于均值」。
  1. 灰度像素张量I_i 是缩小到 8×8 后第 i 个格子的灰度值。
    Ii\displaystyle I_i
  2. 全图均值\mu=\frac{1}{64}\sum_{i=1}^{64}I_i 求 64 个灰度的平均值,作为亮度门槛。
    μ=164∑i=164Ii\displaystyle \mu=\frac{1}{64}\sum_{i=1}^{64}I_i
  3. 逐位二值化\begin{cases}1,& I_i>\mu\\0,& I_i\le\mu\end{cases} 把每个格子分为「亮于均值」与「不亮于均值」两类。
    {1,Ii>μ0,Ii≤μ\displaystyle \begin{cases}1,& I_i>\mu\\0,& I_i\le\mu\end{cases}
  4. 拼接指纹将 64 个 h_i 按顺序串起来,形成 64 位视觉指纹。
    hi\displaystyle h_i

深度哈希学习:AI 画师定制指纹

固定模板指纹仪(感知哈希)胜在轻巧,但扛不住大姿态变化。老周请来一位「AI 画师」——它不再是按固定规则画指纹,而是看遍全城百万张猫片后,自己琢磨出哪些细节最该留在指纹里。

深度哈希的做法是:用 CNN 把图像映射成 K 维连续向量,再用一个 sign 符号函数把向量劈成正负两半,输出 K 位二值哈希码(+1/-1)。训练过程中,损失函数会同时拉近相似图像的哈希码、推远不相似图像的哈希码——这个过程叫做「语义保持」,保证哈希码之间的汉明距离能近似反映图像语义上的相似度。

AI 画师的指纹比固定模板更「懂事」:它会把猫的耳形、花色组合等语义线索揉进指纹,同一只猫不同角度的照片也能得到相近的指纹。老周的档案室终于能应对实战了。

L=∑i,j(Sij∥bi−bj∥22+(1−Sij)max⁡(0,m−∥bi−bj∥22))\displaystyle L=\sum_{i,j}\Big(S_{ij}\|\boldsymbol b_i-\boldsymbol b_j\|_2^2+(1-S_{ij})\max(0,m-\|\boldsymbol b_i-\boldsymbol b_j\|_2^2)\Big)
这个公式是深度哈希的训练目标:相似图像对尽量靠近,不相似图像对至少隔开一个安全距离 m。
  1. 网络映射CNN 把图片 \boldsymbol x_k 编码成连续向量,画师先「看」再下笔。
    f(xk)\displaystyle \boldsymbol f(\boldsymbol x_k)
  2. 符号二值化\text{sign}(\cdot) 把连续向量的每个分量变成 +1 或 -1,形成二值码。
    bk=sign(f(xk))\displaystyle \boldsymbol b_k=\text{sign}(\boldsymbol f(\boldsymbol x_k))
  3. 相似项拉近当 S_{ij}=1 时,让两图哈希码的欧氏距离平方尽量小。
    Sij∥bi−bj∥22\displaystyle S_{ij}\|\boldsymbol b_i-\boldsymbol b_j\|_2^2
  4. 不相似项推远当 S_{ij}=0 时,若距离小于安全边界 m 就产生惩罚,逼它们分开。
    (1−Sij)max⁡(0,m−∥bi−bj∥22)\displaystyle (1-S_{ij})\max(0,m-\|\boldsymbol b_i-\boldsymbol b_j\|_2^2)
  5. 总损失求和对所有训练样本对求和,画师在最小化总损失的过程中学会画指纹。
    L=∑i,j(⋯)\displaystyle L=\sum_{i,j}\Big(\cdots\Big)

汉明距离检索:老警官的汉明尺

指纹档案越来越多,管理员比对时从不把两张照片铺开肉眼细看。老周发给他们每人一把「汉明尺」:量两个指纹有几处不同。

汉明距离的定义很简单:两个等长哈希码逐位对比,有多少位不一样。比如 a=10110、b=10101,第一位相同、第二位相同、第三位相同、第四位不同、第五位不同,距离就是 2。距离越小说明两张图越像,距离为 0 则表示指纹完全一致。

为什么用汉明尺而不用欧氏距离?因为哈希码是 0/1 串,直接异或后数 1 就是距离;在 CPU 上一条 POPCNT 指令就能统计 64 位,比浮点向量做余弦相似度快一个量级。这也是「近似检索」能扛万亿级数据的根因。

dH(a,b)=∑k=1K1[ak≠bk]=popcount(a⊕b)\displaystyle d_H(\boldsymbol a,\boldsymbol b)=\sum_{k=1}^{K}\mathbb{1}[a_k\ne b_k]=\text{popcount}(\boldsymbol a\oplus\boldsymbol b)
汉明距离 = 两个哈希码异或后数 1 的个数;1 的数量越少,图像越相似。
  1. 逐位不等计数\mathbb{1}[a_k\ne b_k] 表示第 k 位不同记 1、相同记 0,把所有位求和。
    1[ak≠bk]\displaystyle \mathbb{1}[a_k\ne b_k]
  2. 异或运算\boldsymbol a\oplus\boldsymbol b 是两个等长二进制串按位异或,同 0 异 1。
    a⊕b\displaystyle \boldsymbol a\oplus\boldsymbol b
  3. popcount 统计\text{popcount}(\cdot) 统计二进制串中 1 的个数,与「不同位数」完全等价。
    popcount(a⊕b)\displaystyle \text{popcount}(\boldsymbol a\oplus\boldsymbol b)
  4. 阈值判定设定 d_H\le\tau 视为相似候选,比如 64 位指纹距离小于 8 就进候选池。
    dH≤τ\displaystyle d_H\le\tau

碰撞消歧策略:指纹撞车怎么办

有一天,老周在候选列表里看到两只完全不同的猫却贴着同一串指纹——就像两个身份证号相同,档案室炸了锅。这就是哈希碰撞:不同图像的哈希码意外相同。

碰撞并非 bug,而是数学上不可避免的宿命。哈希函数把高维图像空间压缩到 K 位码空间,库大了总会有两把钥匙开一把锁。N 个指纹均匀分布在 2^K 个桶里时,平均碰撞对数量大约如下:

工程上不会因为怕碰撞就不敢用哈希,而是加多道保险。第一道是多表索引:用多组独立哈希函数分别建表,查询时多表同时召回,撞车概率指数下降。第二道是二级精排:召回候选后,不再看指纹,而是对原始特征(如深度向量、SIFT 等)重算精确距离,把假阳性过滤掉。第三道是适当加长码长:K 从 32 提到 64 或 128,碰撞空间呈指数扩大。

E[C]≈N22K+1\displaystyle E[C]\approx\frac{N^2}{2^{K+1}}
指纹库越大、哈希码越短,碰撞对就越多;K 每加 1,碰撞概率大约减半。
  1. 库中指纹数 NN 是图像库中的哈希码总数,库越大碰撞越多。
    N\displaystyle N
  2. 码位数 KK 是哈希码长度(如 64),决定指纹空间的粗细粒度。
    K\displaystyle K
  3. 桶空间规模2^{K+1} 是码空间可以容纳的指纹种类数,约等于「有多少把不同的锁」。
    2K+1\displaystyle 2^{K+1}
  4. 碰撞对期望E[C] 表示库中大约有多少对图像会共享同一个指纹。
    N22K+1\displaystyle \frac{N^2}{2^{K+1}}

系统实现方案:搭一座寻亲服务大厅

这一切最终要组装成一个「寻亲服务大厅」:主人递上照片,几秒内给出 Top-K 候选。

工程上分成离线和在线两条流水线。离线阶段:全库图像统一生成哈希码(感知哈希或深度哈希),码相同的图进入同一个桶,构建倒排索引,顺便存一份原始特征用于精排。在线阶段:查询图先生成查询码 h_q,先按码桶召回一串候选,再用汉明距离从小到大精排,取 Top-K 返回。

为了毫秒级响应,码桶用位运算加速,距离排序用堆维护 Top-K;索引更新采用「双缓冲」:新库先构建快照,切换原子完成,避免线上服务中断。高并发时再加一层 LRU 缓存,重复查询直接命中。寻亲服务大厅就这样运转起来:主人递照片、指纹仪出码、汉明尺召回、确认窗口弹出几只候选毛孩子。从像素到指纹,从碰撞到精排,以图搜图把一个巨大的「眼力活」变成了轻快的「翻卡片活」。

C={c∈D∣dH(hq,hc)≤τ},TopK(q)=arg⁡min⁡c∈C(K)dH(hq,hc)\displaystyle \mathcal C=\{c\in\mathcal D\mid d_H(h_q,h_c)\le\tau\},\qquad \text{Top}K(q)=\mathop{\arg\min}_{c\in\mathcal C}^{(K)}d_H(h_q,h_c)
检索链路 = 先用阈值召回一批候选,再用汉明距离精排出 Top-K。
  1. 候选集合\mathcal C 是所有与查询码距离不超过阈值的库图像集合。
    C={c∈D∣dH(hq,hc)≤τ}\displaystyle \mathcal C=\{c\in\mathcal D\mid d_H(h_q,h_c)\le\tau\}
  2. 召回阈值\tau 控制召回范围:太小漏检,太大噪声多。
    τ\displaystyle \tau
  3. Top-K 精排\mathop{\arg\min}_{c\in\mathcal C}^{(K)} 从候选中挑出汉明距离最小的 K 个。
    arg⁡min⁡c∈C(K)dH(hq,hc)\displaystyle \mathop{\arg\min}_{c\in\mathcal C}^{(K)}d_H(h_q,h_c)
  4. 全链路召回 → 精排 → 返回,保证「找回得快、排得准」。
    TopK(q)\displaystyle \text{Top}K(q)

AI 应用场景

电商拍立淘:把商品照片变成检索入口

阶段:离线索引构建 + 在线召回排序

解决的问题:用户看到一件商品想知道哪里买,传统方式靠文字搜索,但经常「只可意会」说不清关键词。以图搜图把商品图转成哈希指纹,在千万级商品库中毫秒召回相似款,按汉明距离精排后返回同款或相似款。就像主人递上毛孩子照片,系统自动淘出最像的几只候选。

具体案例:某服装电商后台维护 2000 万 SKU 图库,用 64 位深度哈希码建倒排索引,查询平均耗时 15ms,Top-10 准确率 87%。每天晚上增量更新当日新增商品码,凌晨切换索引快照,确保用户永远搜得到新品。

版权图库查重:给素材库做指纹去重

阶段:全库哈希去重 + 碰撞精排

解决的问题:素材平台每天涌入大量盗版、重复上传的图片,人工审核不现实。用感知哈希给每张图生成指纹,凡汉明距离小于阈值的图自动进入疑似重复队列,再由深度特征精排复核。就像档案室里两只花纹极像的猫,先靠指纹粗筛归堆,再请资深管理员细看。

具体案例:某图片社区每天新增 50 万张投稿,系统先用 aHash 粗筛把相似图聚成簇,再用深度哈希细排,重复率从 12% 压到 0.8%,审核人力节省 70%。

Python 演示

python49 行
"""以图搜图演示:感知哈希 + 汉明距离检索运行前准备一个 images/ 文件夹,里面放若干 jpg/png 图片。"""import osfrom PIL import Imageimport numpy as np  def average_hash(img, hash_size=8):    """平均哈希:缩放 -> 灰度 -> 均值 -> 二值码"""    img = img.resize((hash_size, hash_size), Image.LANCZOS).convert("L")    pixels = np.asarray(img, dtype=np.float32)    mean = pixels.mean()    return (pixels > mean).astype(np.uint8).flatten()  def difference_hash(img, hash_size=8):    """差值哈希:比较相邻列亮度,得到 8x8 位码"""    img = img.resize((hash_size + 1, hash_size), Image.LANCZOS).convert("L")    pixels = np.asarray(img, dtype=np.float32)    diff = pixels[:, 1:] > pixels[:, :-1]    return diff.flatten().astype(np.uint8)  def hamming_distance(a, b):    return int(np.count_nonzero(a != b))  def build_index(image_dir):    index = []    for name in sorted(os.listdir(image_dir)):        if not name.lower().endswith((".jpg", ".png", ".jpeg")):            continue        img = Image.open(os.path.join(image_dir, name)).convert("RGB")        index.append((name, average_hash(img)))    return index  def search(query_path, index, top_k=3):    query_img = Image.open(query_path).convert("RGB")    query_code = average_hash(query_img)    ranked = sorted(index, key=lambda item: hamming_distance(query_code, item[1]))    return [(name, hamming_distance(query_code, code)) for name, code in ranked[:top_k]]  if __name__ == "__main__":    db = build_index("images")    for name, dist in search("query.jpg", db):        print(f"{name}: {dist}")
目的:构建一个微型「以图搜图」系统——离线给图库生成感知哈希指纹,在线用汉明距离检索出最相似的 Top-K 图片。
  1. def average_hash(img, hash_size=8):平均哈希入口,统一把图缩到 8×8,把照片变成 64 位指纹。
  2. pixels = np.asarray(img, dtype=np.float32)拿到灰度像素矩阵,后续才能做数值比较。
  3. mean = pixels.mean()算整张缩略图的平均亮度,作为二值化门槛。
  4. return (pixels > mean).astype(np.uint8).flatten()逐个像素与均值比较,得到 64 位 0/1 指纹码。
  5. diff = pixels[:, 1:] > pixels[:, :-1]相邻列亮度比较,生成差值哈希的每一位。
  6. hamming_distance(a, b)数一数两串指纹有几位不同,这就是汉明距离。
  7. build_index(image_dir)全库离线生成指纹索引,相当于给每只毛孩子建指纹卡。
  8. ranked = sorted(index, key=lambda item: hamming_distance(query_code, item[1]))用汉明距离升序排序,把最像的图排到最前面。

常见误区

误区我一直以为以图搜图的哈希码就是图像的深度特征向量,反正都是把图变成一个数组。

正解两者完全不同。深度特征向量是浮点连续向量(如 256 维 float),用于精确相似度计算;哈希码是把高维特征压缩成几十位 0/1 串,本质是近似索引。哈希码丢了大量信息,换来了极快的汉明距离计算和压缩存储,通常配合「哈希粗召回 + 原始特征精排」使用。想象速写卡(浮点特征)是详细档案,指纹条码(哈希码)是检索用编号,二者用途不同。

为何常见:两者都由神经网络或特征提取产生,且都叫「特征」,概念边界容易被混淆。

误区哈希位数越多越好,最好用 1024 位,信息足就不会误判。

正解位数增加会让碰撞减少、召回更准,但代价是存储翻倍、位运算变慢、短码的索引结构效率下降。64 位哈希在绝大多数业务场景已经足够,码长选择要按库的规模和召回指标做实验。就像指纹卡做太精细,翻卡片的动作会被细节拖垮。

为何常见:直觉上觉得信息越多越准,忽略了工程成本与收益曲线。

误区汉明距离小就是相似,距离大就是不相似,直接拿来做最终结论。

正解汉明距离衡量的是哈希码层面的差异,而哈希码只是图像的一种「有损摘要」。两张完全不同的图可能因压缩到低位空间而距离很小(碰撞),两个几乎相似的图也可能因翻转、噪声导致哈希码抖动。所以要召回后做二级精排,用原始特征确认。

为何常见:把「近似检索的距离」误当成「精确语义距离」,忽略了哈希是有损压缩的事实。

误区2^64 那么大,真实库里根本不可能有两张图指纹一样。

正解指纹空间确实巨大,但碰撞概率随库中指纹数的平方增长,而且深度哈希码并非均匀分布——语义相近的图会聚簇,让碰撞概率远高于均匀假设。当库规模达到千万级以上,碰撞对数量已非零,工程上仍需多表索引和精排兜底。

为何常见:只按理想均匀分布估算,忽略了真实特征存在聚簇和长尾。

误区只有哈希码完全相同的图才返回,否则结果不可信。

正解实际工业系统几乎都采用「近似检索」:先粗召回可能相似的候选,再精排确认。精确匹配要求哈希码逐位全同,会漏掉大量因压缩、滤镜、角度变化导致码位翻转的相似图,召回率极低。合理的做法是阈值召回 + Top-K 精排,保证「快」和「准」的平衡。

为何常见:把传统数据库等值查询的思维搬到了向量检索上,忽略了图像相似是连续语义而非离散相等。

面试题

Q1. 感知哈希输出的数据形式是什么?

单选题 · easy

  • A.1024维浮点向量
  • B.一段定长二进制串← 正确答案
  • C.一棵决策树结构
  • D.一组哈里斯角点

答案:B。感知哈希(aHash/dHash/pHash)最终把图像压缩成定长二进制串,例如 64 位 0/1 码。浮点向量是深度特征,决策树是分类模型,哈里斯角点是传统关键点,都不是哈希输出。

Q2. 两个哈希码进行汉明距离计算的基础运算是?

单选题 · easy

  • A.按位与 AND
  • B.按位异或 XOR← 正确答案
  • C.按位或 OR
  • D.按位取反 NOT

答案:B。汉明距离等于两个等长二进制串异或后数 1 的个数。XOR 同 0 异 1,再配合 popcount 统计,一条 CPU 指令即可完成 64 位计数。AND/OR/NOT 无法直接得到「不同位的个数」。

Q3. 平均哈希 aHash 常用的图像缩放宽高是?

单选题 · easy

  • A.64×64像素缩略图
  • B.224×224标准化图
  • C.8×8像素缩略图← 正确答案
  • D.512×512高清晰图

答案:C。aHash 第一步把图像缩放到 8×8 灰度图,得到 64 个像素值,再与均值比较生成 64 位码。224×224 是 CNN 常用输入尺寸,SIFT 等特征才在原分辨率上提取。

Q4. 深度哈希用 sign 函数输出二值码时,它的梯度特性是?

单选题 · mid

  • A.处处可导梯度为常数
  • B.非零点处梯度等于一
  • C.零点不可导且梯度为零← 正确答案
  • D.梯度恒等于零值

答案:C。符号函数在零点不可导,且除零点外导数几乎处处为 0,因此训练时无法直接回传梯度。工程上常用 tanh 或 straight-through estimator 做近似,把梯度「抄」过符号门。

Q5. 哈希碰撞的本质原因是?

单选题 · mid

  • A.磁盘存储容量太小
  • B.高维特征映射到低维← 正确答案
  • C.图像分辨率不够高
  • D.汉明距离阈值设置过大

答案:B。高维图像特征被压缩到 K 位低维码空间,信息必然丢失,不同图像就可能落到同一个桶。磁盘容量、分辨率、阈值设置都是诱因,但不是本质原因。

Q6. 下面哪种方式最适合处理哈希碰撞?

单选题 · mid

  • A.放弃哈希改线性扫描
  • B.仅保留一张表并加大阈值
  • C.多表召回加二次精排← 正确答案
  • D.把哈希码位数降到16

答案:C。工程上用多哈希表分别建索引来降低碰撞概率,召回后用原始特征二次精排,把「误入」的候选过滤掉。放弃哈希太慢;降位数会加剧碰撞;只加大阈值会让召回噪声爆炸。

Q7. 工业级以图搜图系统最常见的做法是?

单选题 · mid

  • A.在线逐张计算全部特征
  • B.离线索引加在线精排← 正确答案
  • C.用生成模型重建图库
  • D.用关系库做模糊匹配

答案:B。工业系统普遍采用「离线构建索引、在线召回精排」:全库图像先算好哈希码并建倒排索引,查询时只访问相关码桶,再用汉明距离精排取 Top-K。在线逐张全库计算不可扩展;生成模型和模糊匹配都不是相似检索的正确方案。

Q8. 下列哪些属于感知哈希家族的常见变体?

多选题 · mid

  • A.平均哈希编码← 正确答案
  • B.差值哈希编码← 正确答案
  • C.感知哈希编码← 正确答案
  • D.尺度不变特征转换

答案:ABC。aHash(平均哈希)、dHash(差值哈希)、pHash(感知哈希)是三个常见变体,都是把图像压缩成二值码。SIFT 属于传统局部特征,输出浮点描述子,不产生二进制哈希码。

Q9. 减轻哈希碰撞可以采用的工程策略有哪些?

多选题 · hard

  • A.多表索引桶← 正确答案
  • B.二级精排重检← 正确答案
  • C.增加码位长度← 正确答案
  • D.固定单阈值检索

答案:ABC。多表索引用独立哈希函数分散碰撞;二级精排用原始特征重算相似度过滤假阳性;加长码位能扩大码空间、降低碰撞概率。固定单阈值不做消歧,会让碰撞结果直接污染输出。

Q10. 关于汉明距离检索加速的说法正确的有?

多选题 · extreme

  • A.用POPCNT指令统计← 正确答案
  • B.对哈希码做按位异或← 正确答案
  • C.预构建码桶倒排索引← 正确答案
  • D.必须依赖大模型显存

答案:ABC。汉明距离可用「XOR + popcount」实现,CPU 的 POPCNT 指令可一次统计 64 位中 1 的个数;倒排索引按码桶组织数据,检索时只访问少数桶,都是常用加速手段。GPU 并非必需,纯 CPU 也能跑得非常快。