海海艺思创

首页/ AI绘图教程/ 图片相似度去重:批量出图如何筛查并人工保留

AI绘图教程

图片相似度去重:批量出图如何筛查并人工保留

批量出图后,不同文件可能画面近似,同一主体也可能包含值得保留的不同方案。先检索候选,再对照原图作人工判断,比直接按分数清理更稳妥。本文提供索引字段、特征提取接口示意、候选筛查代码和复核模板;资料包只有官方博客索引,具体模型与提取接口仍需补充…

图片相似度去重:批量出图如何筛查并人工保留

先准备只读素材库与索引字段

这套流程解决的是:如何从一批图片中找出值得成对比较的素材,而不是让模型决定哪些文件应被删除。建议先用素材副本建立小规模样本库,原始目录保持只读,筛查结果写到单独目录。将完全相同、视觉近似和同主体不同方案分开记录,不要合并成一个含糊的重复标签。

现有 Hugging Face Blog 索引收录了 Image Similarity with Hugging Face Datasets and Transformers,日期为 2023 年 1 月 16 日。资料包没有提供该文章正文、模型标识、输出字段或当前检索接口,不能据此给出已核验的安装命令与模型调用代码。下面的字段与流程属于本文建议的原型设计,不是官方接口说明。

字段填写内容用途
image_id入库时分配且不随排序变化的唯一编号关联候选和保留记录
relative_path相对素材根目录的文件路径找回具体文件,不能只写文件名
file_sha256文件内容摘要登记字节级一致的候选与文件变化
width、height、format原图规格辅助判断可用版本
project_id、batch_id所属项目与出图批次限制比较范围
feature_version模型修订、预处理、输出层与汇聚方式的组合版本防止不同特征混用
embedding一张图片对应的一维有限数值向量生成视觉候选
feature_status、error成功、失败及失败原因避免把漏处理当作无重复

同内容文件也应有各自的 image_id,摘要不要代替文件实例编号。只按文件摘要查找无法完成视觉近似筛查;而向量分数也不能代替对原始图片、用途和细节的判断。

用成对样本定义哪些差异必须保留

先由设计负责人定义“可互相替代”的范围,再准备阈值测试样本。以下是样本构造方案,不是已经得到的模型结果,表内不预填相似分数。

样本对如何准备人工预期
A 与 A_copy同一原文件的副本完全重复对照
A 与 A_export同一画面的另一次导出按用途判断是否可替代,记录规格差异
A 与 A_crop原画面与局部取景版本若承担不同版式用途,保留两张
B_front 与 B_side同一产品的正面与侧面方案非重复难例,保留两张
C_red 与 C_green构图相近但关键配色不同的方案若颜色是交付要求,保留两张
D 与 E主体与构图都不同的图片非重复对照

标注表建议使用 pair_id、left_id、right_id、label、reason;label 取 duplicate、distinct 或 uncertain。拿不准的样本留给复核,不要为了方便统计强行标为重复。阈值调节样本与最终验收样本应分开,同一原图衍生的多张导出图不要跨到两组里。

从索引定位资料,再接入特征提取

  1. 在官方博客索引中查找上述 Image Similarity 条目,随后补充读取文章正文。先确认示例采用的模型、预处理和相似度定义,不能只看标题选择代码。
  2. 对照拟使用版本的说明,登记模型修订、依赖版本、输入图片要求、图像输出字段与汇聚方式。确认得到的是每张图片的向量,而不是类别标签或一串未处理的局部特征。
  3. 固定图像方向、颜色通道和透明背景处理规则,预处理只作用于读取后的输入副本,不覆盖原文件。
  4. 先处理样本库,每个向量与 image_id 一起保存;读取失败、输出为空或存在非有限数值时,将该图记为失败并保留错误原因。
  5. 同一索引仅接收相同 feature_version 的特征。改变模型或预处理后重建对应索引,再重新标定阈值。

下面只展示业务适配关系。read_image、prepare、encode_image 与 pool_to_vector 都是待实现的业务适配函数,不是 Datasets 或 Transformers 的已确认函数名;资料补齐前不能把它当作可直接运行的提取程序。

FOR each item IN image_index:
    image = read_image(item.relative_path)
    prepared = prepare(image, fixed_preprocess_config)
    output = encode_image(prepared, verified_model_revision)
    vector = pool_to_vector(output, verified_output_contract)
    validate_finite_nonzero_vector(vector)
    save_feature(item.image_id, feature_version, vector)

素材量较大时,可在接口核对后再选用数据集容器与向量索引工具。先用小样本确认编号、向量与原图对应关系,比一开始追求全库吞吐更重要。

建立只输出候选的最小筛查原型

下面是独立于模型接口的 Python 标准库示例,只读取已有向量,不提取图片特征,也不移动、覆盖或删除原图。它按余弦相似度从高到低输出每张图的前 k 个候选,排除自身并合并反向重复对。分数表示本例定义的向量相近程度,不是“重复概率”。代码未执行验证,只适合小规模核对,计算量随图片数近似平方增长。

输入文件 features.json 是对象数组,每项必须包含 image_id、feature_version、embedding。这里不提供虚构的图像向量;请使用核对过的提取流程产出数据。先在单一项目范围运行,避免不同项目素材混在一起。

import csv
import json
import math
import sys

input_path, output_path = sys.argv[1:3]
k = int(sys.argv[3])
threshold = float(sys.argv[4])
if k < 1 or not math.isfinite(threshold) or not -1 <= threshold <= 1:
    raise ValueError('Invalid k or threshold')
with open(input_path, encoding='utf-8') as f:
    rows = json.load(f)
if not rows:
    raise ValueError('No features')
ids = [r['image_id'] for r in rows]
if len(set(ids)) != len(ids):
    raise ValueError('Duplicate image_id')
versions = {r['feature_version'] for r in rows}
if len(versions) != 1 or not next(iter(versions)):
    raise ValueError('Mixed or missing feature_version')
vectors = []
dim = None
for row in rows:
    v = [float(x) for x in row['embedding']]
    if not v or not all(math.isfinite(x) for x in v):
        raise ValueError('Invalid vector')
    if dim is None:
        dim = len(v)
    if len(v) != dim:
        raise ValueError('Dimension mismatch')
    norm = math.hypot(*v)
    if not math.isfinite(norm) or norm == 0:
        raise ValueError('Invalid vector norm')
    vectors.append([x / norm for x in v])
pairs = {}
for i, v in enumerate(vectors):
    ranked = []
    for j, w in enumerate(vectors):
        if i == j:
            continue
        score = sum(a * b for a, b in zip(v, w))
        ranked.append((j, max(-1.0, min(1.0, score))))
    ranked.sort(key=lambda item: (-item[1], item[0]))
    for j, score in ranked[:k]:
        if score >= threshold:
            pairs[tuple(sorted((i, j)))] = score
with open(output_path, 'x', newline='', encoding='utf-8') as f:
    writer = csv.writer(f)
    writer.writerow(['left_id', 'right_id', 'score',
                     'feature_version', 'review_status'])
    for (i, j), score in sorted(pairs.items()):
        writer.writerow([ids[i], ids[j], score,
                         rows[i]['feature_version'], 'pending'])

调用格式为 python screen_pairs.py features.json candidates.csv 10 -1。这里的 10 只是候选数量示例,-1 用于先观察前 k 个候选,不是生产阈值。输出文件采用排他创建,已存在时会报错,避免覆盖已有复核结果。后续用选定阈值和新的输出文件名重新运行。

top-k 之外的图片对不会输出,即使分数也超过阈值。因此,空候选不能证明全库没有重复;在小样本标定时,可把 k 设置为样本图片数减一,检查全部非自身图片对。不要把 A 接近 B、B 接近 C 自动推断为 A 与 C 可互相替代。

标定阈值后填写人工保留记录

  1. 先在标注样本上生成候选,逐对记录实际分数与人工标签。确认样本是否出现在候选中,未被召回的重复对也要登记。
  2. 围绕已观察到的分数分布比较多个候选阈值,分别统计命中的重复对、误报的非重复对和漏掉的重复对。不要借用别的模型阈值。
  3. 同时调整 k 并记录变化。只比较已命中的候选会漏看召回失败,应以全部已标注重复对为分母检查召回情况。
  4. 锁定特征版本、k 和阈值后,用独立验收样本复核;结果不满足团队约定标准时,继续保持人工小范围使用。
  5. 并排打开原图,比较画面、规格、授权、交付用途与已引用情况,然后选择保留两张、保留其中一张或暂缓。

保留理由可参考图片方案成对对比的记录方法,但“更喜欢某张”不能单独证明另一张是重复素材。用于不同画幅、渠道或设计方案的文件,即使画面相近,也可能都要保留。

pair_id,left_id,right_id,decision,keep_id,cleanup_candidate_id,reason,reviewer,reviewed_at,feature_version,run_id
P001,IMG001,IMG002,keep_both,NA,NA,different_delivery_use,reviewer_a,TO_FILL,TO_FILL,TO_FILL
P002,IMG003,IMG004,pending,NA,NA,needs_original_comparison,TO_FILL,TO_FILL,TO_FILL,TO_FILL

以上仅为记录格式示例。确认近重复且允许清理时,decision 可填 confirmed_duplicate,同时填写 keep_id、cleanup_candidate_id、人员、时间和理由。导出前必须检查保留编号不在任何待清理项中,冲突、缺字段及 pending 项一律暂停导出。待清理清单仅供后续授权处理,不附带自动删除动作;还应关联原路径和文件摘要,防止文件后来被替换。

候选异常时按原因修正

常见故障可能原因修正动作
同主体的不同方案大量命中特征偏向主体语义,或阈值不适合当前素材补入不同视角、配色和版式难例,重新标定;保留人工判断
重复导出图没有进入候选图片漏处理、k 太小或预处理不一致先核对成功入库数量,再扩大 k,并检查同一原图的输入处理记录
分数排序与预期相反把距离当成相似度,或混用不同度量登记接口返回语义;本例仅对余弦相似度降序排列,不直接套用到距离接口
更换模型后结果跳变旧向量、旧阈值仍在使用按 feature_version 重建索引,并重新运行标注样本
候选重复或总是出现自身未排除相同编号,未统一无序图片对按 image_id 排除自身,并将反向对合并,不能按文件名去重
输出文件已存在原型拒绝覆盖旧结果使用新的批次文件名,保留旧复核记录,不盲目覆盖
同一文件既被保留又被标为待清理多组复核决定互相冲突暂停该批导出,重新确认最终保留版本及全部关联图片对

发布筛查工具前逐项验收

  • 已补充核对模型正文与当前接口;仅有索引时,提取部分明确标为待接入,不能标注完整模型流程已验证。
  • 索引总数、特征成功数和失败数能对应,每个编号都能找回原图。
  • 同一运行仅使用一致的特征版本,向量维度、有限数值和非零长度检查全部通过。
  • 完全重复、近似导出、同主体不同方案和明显不同图片均有样本,另有独立验收集。
  • 阈值、k、样本版本与误报漏报记录齐全,没有把候选分数当成重复概率。
  • 候选排除了自身与反向重复对,没有使用相似关系自动传播清理决定。
  • 每个待清理项均有人工确认、保留版本、理由与文件摘要,不含未决项及冲突项。
  • 原图目录未被写入,原型没有删除、移动或覆盖图片的功能。

现阶段可先完成索引表、样本标注和复核约定;补齐模型与接口资料后,再接入特征提取并验证候选结果。最终交付应包括素材索引、特征版本记录、候选表、阈值对照表和人工确认的待清理清单,而不只是一个分数阈值。

下一步

把这篇的方法练一遍

提示词和步骤可以带到创作里直接试做一版。

去创作 看同栏目更多