1. 总体结论
方案整体可行 ,所有组件均有成熟开源实现,无技术卡点。
唯一需要重点决策的是组件许可证(影响商用),以及**以文搜图必须选多模态模型(SigLIP2)而非纯视觉模型(DINOv2)**这两个设计要点。
2. 组件选型与许可证评估(关键风险项)
| 组件 | 选型 | 许可证 | 商用风险 |
|---|---|---|---|
| OCR | PaddleOCR PP-OCRv5(mobile 版) | Apache-2.0 | ✅ 无 |
| 人脸检测/识别 | InsightFace (buffalo_l: RetinaFace/SCRFD + ArcFace 512d) | 代码 MIT;预训练模型仅限非商用研究,商用需向 insightface.ai 申请授权 | ⚠️ 高风险,见 §3.1 |
| 通用目标检测 | Ultralytics YOLOv8/v11 | AGPL-3.0,商用需购买商业授权 | ⚠️ 高风险,见 §3.1 |
| 车牌识别 | PP-OCR + 后处理 | Apache-2.0 | ✅ 无 |
| 多模态嵌入 | SigLIP2 (base/large) | Google 官方权重 Apache-2.0(Keras/HF 渠道确认) | ✅ 无 |
| 视觉嵌入 | DINOv2 | 代码 Apache-2.0;权重授权口径不一(官方 README 称 Apache-2.0,PyPI/模型卡标注 CC-BY-NC),商用前需书面确认 | ⚠️ 中风险 |
| 向量/文本检索 | OpenSearch 2.19.6 (k-NN + 全文) | Apache-2.0 | ✅ 无 |
| 对象存储 | SeaweedFS | Apache-2.0 | ✅ 无 |
3.1 许可证问题的三个决策选项
| 选项 | 做法 | 代价 |
|---|---|---|
| A. 采购授权(推荐商用) | Ultralytics 商业授权 + InsightFace 模型商用授权 | 一次性/年度费用,最省心,用最强模型 |
| B. 全换 Apache 系替代 | 检测换 YOLOX / RT-DETR(Paddle, Apache-2.0) ;人脸换 InsightFace 代码 MIT + 自训检测头,或 buffalo 模型仅内部/非商业使用 | 零授权费,但车牌等垂类精度略降、自训成本上升 |
| C. 混合 | 内部工具/非对外服务 → 直接用现有预训练模型;对外商用功能 → 采购授权 | 需清晰划分使用边界 |
若本项目是内部安全/运维排查用途(不对外提供人脸比对服务),buffalo_l + YOLO 的默认授权在实践中可用,但法务口径需留档。若对外商用,强烈建议选项 A 或 B。
3. 各模块可行性细化
3.1 PaddleOCR 文本识别 ✅
- PP-OCRv5 mobile 版:CPU 单张 1080p 截图 ~200-500ms,GPU 可批量推理,单卡 T4/A10 可达 5-10 张/s/卡。
- 输出:文本 + 行框坐标(后续可存坐标,支持"框选文字定位回原图")。
- 截图场景(UI 文字、小字号)建议:
use_doc_orientation_classify=False关掉方向分类省算力,use_textline_orientation=True。 - 大批量历史截图:worker 池 + Redis 队列,GPU 节点 4 卡约 4 万-10 万张/天。
3.2 InsightFace 人脸 ✅(授权见上)
- buffalo_l:检测(RetinaFace-10GF)+ 识别(ArcFace-ResNet50,512 维特征,L2 归一化)。
- 流程:检测 → 5 点/106 点对齐 → 112×112 对齐脸 → 512d embedding。
- 切图:按检测框外扩 20% 存人脸裁剪图到 SeaweedFS。
- 同图去重/阈值:余弦相似度 > 0.4~0.5(经验值,需按数据标定)判同人。
- CPU 也可跑(onnxruntime),单张多脸 ~100ms;批量建议 GPU。
3.3 YOLO 检测(人体/车辆/车牌)✅
- 基座:COCO 预训练已含
person、car/truck/bus/motorcycle类别,直接可用。 - 车牌不在 COCO 类 ,需自训:
- 数据集:公开集 CCPD(70 万+ 车牌图)/ 车牌数据集 + 自己截图标注;
- 方案:YOLOv8n/s 微调,640 输入,加 1-2 个 P2 小目标头(车牌是小目标);
- 数据量 2k-5k 张标注即可达可用精度(mAP 0.8+),标注工具 LabelImg/LabelStudio。
- 替代:PaddleDetection 自带车牌检测预训练模型(Apache-2.0),可先拿来用再决定自训。
- 切图:车辆/人体框外扩存 SeaweedFS;车牌单独切给 OCR 通道。
- 向量:切图过 DINOv2-ViT-B/14(768d) (细粒度外观特征);车牌图不需要向量,靠 OCR 文本 keyword 精确检索更可靠。
3.4 PP-OCR 车牌识别 + 后处理 ✅
- 车牌切图 → PP-OCR(关方向分类、
use_doc_unwarping=False)→ 后处理:- 正则约束:
[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-Z0-9]{5,6}+ 新能源 8 位; - 混淆字符修正表(O↔0、I↔1、Z↔2、G↔9 按车牌规则纠偏);
- 置信度 < 阈值标
plate_confidence低分标记,检索时降权/提示人工确认; - (可选)车牌颜色/省份分类头辅助纠错。
- 正则约束:
- 准确率预期:正面无遮挡车牌 99%+;斜角/模糊 90-95%。
3.5 向量嵌入 ✅
- SigLIP2 (关键选择):图文同空间 ------ 图片 embedding 和文字 embedding 同模型生成,
以文搜图天然支持 (如"戴安全帽的工人"→搜图),这是 DINOv2 做不到的。- 推荐 siglip2-base-patch16-256(768d)或 large(1024d);截图以 UI/界面为主,base 足够。
- DINOv2-ViT-B/14(768d):车辆/人体细粒度以图搜图(同车、同人衣着)。
- ArcFace(512d):人脸以图搜图/聚类。
- 三套向量、三个语义空间,不可混在同一个 knn 字段(见 §4 索引设计)。
3.6 SeaweedFS 文件存储 ✅
-
原图:
weed filer -s master:8888 -f img.jpg上传,返回 fid(如65539,0123456789)。 -
组织建议:
/raw/{yyyy}/{MM}/{image_id}.jpg # 原图 /crops/{image_id}/face_{i}.jpg # 人脸切图 /crops/{image_id}/vehicle_{i}.jpg # 车辆切图 /crops/{image_id}/plate_{i}.jpg # 车牌切图 -
只存 OpenSearch 中的 fid + 元数据,检索命中后用 fid 拼 URL 回显。
-
集群:master 3 节点 + storage 若干,EC-2/4 纠删码省空间;fid 全局唯一。
3.7 OpenSearch 存储与检索 ✅(2.19.6)
索引设计(3 个索引,向量空间隔离):
shots/ # 截图主索引:文本 + 元数据 + 车牌文本
image_id (keyword) fid (keyword) url (keyword) captured_at (date)
app_name (keyword) ocr_text (text, ik_max_word)
plate_text (keyword) plate_conf (float)
face_count/vehicle_count (int)
faces/ # 人脸索引:每脸一条文档(支持"找这个人出现在哪些截图")
face_id (keyword) shot_fid (keyword) box (scaled_float[4])
embedding (knn_vector, 512d)
embedding (knn_vector, 512d)
face_id (keyword) shot_fid (keyword) box (scaled_float[4])
embedding (knn_vector, 512d)
visual/ # 通用视觉索引:每张切图/原图一条,type 区分语义空间
vis_id (keyword) type (keyword: face|vehicle|person|scene|text)
shot_fid (keyword) model (keyword: dinov2|siglip2)
embedding (knn_vector, 768d)
knn 字段配置示例:
json
"embedding": {
"type": "knn_vector",
"dimension": 768,
"method": {
"engine": "lucene", "name": "hnsw",
"space_type": "cosinesimil",
"parameters": { "m": 16, "ef_construction": 200 }
}
}
三种检索形态:
| 检索 | 实现 |
|---|---|
| 文本搜索 | shots/ocr_text match (ik) + highlight;车牌精确查用 plate_text keyword term |
| 以文搜图 | 查询文本过 SigLIP2 文本塔 → 768d → visual/ k-NN(type=scene) |
| 以图搜图 | 查询图/切图过对应模型 → 人脸查 faces/,车辆查 visual/ (type=vehicle, model=dinov2) |
| 混合 | 文本 + 向量 RRF 融合(2.19 原生支持 rank: rrf) |
规模评估:100 万截图 ≈ 文本索引 ~20-50GB + 每截图 1 个 scene 向量(768d×4B≈3KB) + 人脸均值 0.5 张/图 ≈ 总量 <150GB,3×16C/64G 集群轻松承载;千万级再考虑 int8 量化(Faiss SQ)和冷热分层。
4. 数据流水线架构
截图源 ──► 采集适配器(定时抓取/上传)
│ 原图存 SeaweedFS → 得 fid
▼
Redis/Kafka 队列
▼
┌─────────────────────────────────────────┐
│ GPU Worker 池(Triton / 自写 Python) │
│ 1. PP-OCRv5 → ocr_text │
│ 2. InsightFace → 人脸框 + 512d │
│ 3. YOLO(含车牌头) → 人/车/车牌框 │
│ 4. PP-OCR(车牌切图) → plate_text │
│ 5. SigLIP2 → 原图 scene 768d │
│ 6. DINOv2(车/人切图) → 768d │
│ 7. 切图上传 SeaweedFS │
└─────────────────────────────────────────┘
│ 全部产出
▼
Bulk 写 OpenSearch(shots + faces + visual,500条/batch)
▼
搜索 API 层(FastAPI)
/search/text?kw= → 文本
/search/image?fid= → 以图搜图(自动路由人脸/通用)
/search/text-to-image?q=→ 以文搜图
工程要点:
- 一张图的所有产出一次 bulk 事务写三个索引,失败整图重试(幂等:image_id 做 _id)。
- 模型服务化:Triton 多模型同卡(PP-OCR + YOLO 共享一张 T4 可跑),SigLIP2/DINOv2 放第二张卡;纯 CPU 方案可行但吞吐降 5-10 倍。
- 车牌文本进
shots.plate_text(keyword) + 同时拼进ocr_text副本,一条查询全命中。
5. 检索层竞品对比(OpenSearch vs 其他)
5.1 候选系统总览
| 系统 | 语言/架构 | 许可证 | 全文检索 | 向量检索 | 混合检索(关键词+向量) | 分布式 | 定位 |
|---|---|---|---|---|---|---|---|
| OpenSearch 2.19 | Java/Lucene,分布式集群 | Apache-2.0 | ★★★★★ | ★★★★ (Lucene HNSW + Faiss) | ★★★★ 原生 RRF | ✅ 成熟 | ES 的开源后继,通用搜索+向量一体 |
| Elasticsearch 8.x | Java/Lucene,分布式集群 | AGPL-3.0/SSPL/ELv2 三选 | ★★★★★ | ★★★★ (Lucene 深度优化,官方基准比 OS 快 2-12x) | ★★★★ | ✅ 成熟 | 功能最全,生态最大 |
| Vespa | C++,分布式,AI 原生 | Apache-2.0 | ★★★★ | ★★★★★ (官方称向量吞吐 12.9x ES) | ★★★★★ 内置多阶段排序+ML | ✅ 超大规模 | 千亿级混合检索/推荐 |
| Weaviate | Go,分布式 | BSD-3 | ★★★ | ★★★★★ | ★★★★ 原生 hybrid | ✅ | 向量优先,RAG 集成强 |
| Milvus | C++/Go,分布式 | Apache-2.0 | ★(弱,靠 BM25 插件) | ★★★★★ 专用 | ★★★ | ✅ | 纯向量数据库标杆 |
| Meilisearch | Rust,单节点 | MIT(社区版) | ★★★ | ★★★ | ★★★★ 自动 embedding | ❌ 社区版单节点 | 开发者友好的即时搜索 |
| Typesense | C++,单节点/小集群 | GPL-3.0 | ★★★ | ★★★ | ★★★ | ⚠️ 小规模 | 轻量即时搜索,RAM 内索引 |
| Manticore Search | C++,分布式 | GPL-3.0 | ★★★★ | ★★★ | ★★★★ SQL 协议 | ✅ | 轻量高性能,SQL 接口,内置中文分词 |
| Zinc Search | Go 单二进制 | Apache-2.0 | ★★★ | ★★ | ★★ | ⚠️ 实验性 | 超轻量 ES API 兼容 |
5.2 各项目优缺点
OpenSearch
- 优点:Apache-2.0 最干净;全文+向量+聚合一体;RRF 混合检索、k-NN 多引擎(Lucene/Faiss)、量化(SQ/PQ)、ILM、快照、Security 插件全套生产特性;与 ES 7.x API 高度兼容,客户端生态丰富;AWS 背书+Linux 基金会治理。
- 缺点:JVM 运维成本(堆内存调优、GC);向量检索性能弱于 ES 官方优化版(vendor 基准,参考即可);Dashboards 比 Kibana 弱。
Elasticsearch
- 优点:功能/生态/文档最全;Lucene 向量路径深度优化(int8/BBQ 量化、并发段搜索),向量性能官方基准领先;Kibana 可视化强。
- 缺点:许可证是最大问题------AGPL-3.0/SSPL/ELv2 三选一,商用嵌入/修改分发场景法务风险高(AGPL 的传染性、SSPL 要求开源云服务);向量性能优势部分依赖 8.x 付费特性(如 ELSER 语义模型)。
Vespa
- 优点:混合检索+ML 重排的天花板(内置 tensor/多阶段 ranking);超大规模(千亿文档);Vinted 案例:6 个 ES 集群(120+ 服务器)合并为 60 节点 Vespa,延迟降 2.5x、索引提速 3x。
- 缺点:学习曲线陡(自有配置语言/数据模型);无成熟中文分词方案;社区小、运维资料少;对本项目属于明显 overkill。
Weaviate
- 优点:向量优先设计,内置 vectorizer 模块(可接 OpenAI/HF/本地模型);RAG/Agent 工作流集成好;多租户完善。
- 缺点:全文检索能力弱(无中文分词插件生态);本项目"文本搜索是核心需求之一",短板明显。
Milvus
- 优点:纯向量场景性能/规模第一梯队;GPU 加速;与 SeaweedFS 类对象存储天然搭配。
- 缺点:全文检索是配角(BM25 功能弱、无中文分词),文本搜索仍需另配引擎 → 双系统架构,数据一致性维护成本高。
Meilisearch / Typesense
- 优点:开箱即用、50ms 内响应、拼写容错默认开启、API 极简。
- 缺点:社区版单节点/小规模,不满足分布式+大数据量;中文分词支持弱(Meilisearch 无内置,需预分词);无完整聚合/管道能力,做"截图归档+多路检索"这种数据平台级场景不合适。
Manticore Search
- 优点:极省资源(1C/1GB 可跑);SQL 协议好上手;内置中文分词;向量+全文混合、实时索引、分片复制;GPL-3.0(独立进程部署不触发传染性,实际风险低)。
- 缺点:生态/社区远小于 ES 系;无官方托管;高级功能(k-NN 引擎种类、量化)较少;团队经验积累少。
Zinc Search
- 优点:单二进制、Apache-2.0、ES API 兼容,极轻量。
- 缺点:向量能力弱、集群能力实验性,只适合小项目/边缘场景。
5.3 结合本项目情况的推荐
推荐:OpenSearch 2.19.6(维持原方案)。理由逐条对应项目需求:
| 项目需求 | OpenSearch 匹配度 |
|---|---|
| 文本关键字搜索(中文 UI 文字) | ✅ 全文检索 + analysis-ik 中文分词插件(ES 同样需要第三方 IK,无差异) |
| 以图搜图(3 套向量空间:人脸 512d / DINOv2 768d / SigLIP2 768d) | ✅ 多 knn 索引、Lucene HNSW + Faiss、量化可选 |
| 以文搜图 | ✅ 查询侧算文本 embedding + k-NN,或 ML Commons 托管推理端点 |
| 混合检索(车牌文本 + 图像向量) | ✅ 原生 RRF |
| 数据量(百万~千万级文档、<150GB) | ✅ 3 节点集群富余;无需 Vespa 级能力 |
| 许可证(内部系统,但未来可能产品化) | ✅ Apache-2.0,零法务风险(对比 ES 三选一) |
| 生命周期/备份/安全(截图数据留存策略、RBAC) | ✅ ILM + S3 快照 + Security 插件齐全 |
| 运维 | ⚠️ JVM 运维是唯一成本项,但团队若熟悉 ES 系则无障碍 |
被排除的理由一句话版:
- Elasticsearch:功能不差,但 SSPL/AGPL 许可证在自托管+对外服务场景是持续法务负担,无理由冒险;
- Vespa/Milvus:能力过剩或结构错配(Milvus 全文弱→需双系统);
- Weaviate:中文全文检索短板,与"文本搜索是核心需求"冲突;
- Meilisearch/Typesense/Manticore:规模/生态/高级检索能力不足,Manticore 可作为未来轻量替代的备选项关注(若数据量始终 <500 万且想省运维,值得 PoC 对比);
- Zinc:不满足生产要求。
补充建议:向量规模若未来超过 5000 万条,再评估"OpenSearch 存文本 + Faiss 独立服务存向量"的拆分方案;当前阶段单引擎最简且完全够用。
6. 以图搜图效果评估(大量物体图片:动物/植物/物品)
6.1 结论先行
可以实现,且是 OpenSearch k-NN 的标准用法 (SigLIP2/DINOv2 768d 向量 + HNSW,百万级向量单节点查询 10-50ms,千万级 50-200ms,ef_search 可在线调 recall/延迟)。
但效果取决于你要哪种"相似",三种场景能力差距很大:
| 相似度类型 | 例子 | 零样本效果 | 说明 |
|---|---|---|---|
| ① 同类物体 | 传一张猫 → 找出库内所有猫/狗/汽车/刀具 | 很好,开箱可用 | CLIP 系/DINOv2 天然学的是语义类别,Top-5 正确率通常 90%+;这是 SigLIP2 的设计强项 |
| ② 相似外观 | 传一张红色公路车 → 找出库内外观相近的自行车 | 中等 | 同类的不同实体会聚成一团,排序靠前但不保证;颜色/姿态/背景变化都会扰动排序 |
| ③ 特定实例 | 传一张图 → 找出"这一辆"车/这把刀/这只特定的狗出现在哪些截图 | 零样本偏弱 | 预训练模型区分不了"同一辆 vs 同类的另一辆";需要额外手段(见 6.3) |
6.2 效果预期(工程经验值,需 PoC 实测校准)
- 整图向量(每张图一条 768d):找"图里有什么动物/什么物体"可用;但 Web 截图/复杂场景里小物体被 UI 背景稀释,召回率下降明显。
- 切图向量 (每个检测出的物体各一条):这是效果跃升的关键------YOLO 先把车、人、刀等物体切出来,每个切图单独过 DINOv2/SigLIP2 生成向量,"以图搜图"直接命中单个物体,Top-1 正确率可再提升 10-20 个百分点。本方案已包含此设计(§4 流水线第 6 步),务必启用。
- 量级与性能:100 万 × 768d FP32 向量 ≈ 3GB 索引(HNSW 含图结构约 5-8GB 内存),Lucene 引擎在 32G 堆节点上 P95 < 50ms;5000 万+ 再考虑 Faiss IVF + int8 量化。
- 参考基准:SigLIP2 零样本图-文检索 R@1 约 70(COCO i2t 论文值);DINOv2 kNN 分类 ImageNet 82-84%------同类检索的底层特征质量是够的。
6.3 提升效果的四个手段(按性价比排序)
- 检测切图 + 物体向量(必须做,见上)------把"图里找相似"变成"物体对物体比",消除背景噪声;
- 分类标签做预过滤 (强烈建议):YOLO 已给出类别(car/motorcycle/knife...),查询时
type=vehicle过滤后再 k-NN,既提精度又降延迟(OpenSearch 2.4+ 原生自适应过滤,filter 直接进 HNSW 图内); - 敏感/重点物体走"检测+分类"而非纯向量 :刀具、武器等安防语义类别,纯向量检索容易漏(角度/遮挡/小目标),用 YOLO 自训分类头或轻量分类器打标签,检索时 label 精确匹配兜底,向量只负责排序------双通道,label 保证召回,向量保证顺序;
- 实例级区分(仅场景③需要时做):用自有截图做对比学习微调(triplet/InfoNCE,几百~几千对样本即可),让"同一实体"在向量空间更近、同类不同实体更远;或人脸/车牌这类已有专用编码器的类别直接走专用向量空间(ArcFace/车牌文本),不需要通用模型硬扛。
6.4 已知弱点(PoC 阶段重点验证项)
- 小目标/低分辨率物体(缩略图里的自行车)向量区分度差 → 提高切图最小尺寸阈值,过小的丢弃向量、只留 bbox 元数据;
- 颜色/角度敏感场景("红色的"车):SigLIP2 语义空间对颜色不如对类别敏感,可加 CVAT 式属性标注(color/angle)做 filter 字段;
- 跨模态漂移:以文搜图("摩托车")和以图搜图的向量虽同空间,但文本 query 的召回集合通常比图 query 更泛------产品上预期要管理,别承诺同等精度。
7. 风险与缓解
| 风险 | 等级 | 缓解 |
|---|---|---|
| InsightFace/YOLO 商用授权 | 高(若商用) | §3.1 三选项;或换 Apache 系替代 |
| DINOv2 权重授权口径不一 | 中 | 商用前向 Meta 渠道书面确认,或降级为可选组件(核心依赖 SigLIP2) |
| 小目标车牌漏检 | 中 | 加 P2 head + 输入 1280 + 车牌二阶段精检;置信度门控 |
| 截图分辨率高导致推理慢 | 低 | 统一 resize 到 1280 宽上限;worker 内 batch |
| 人脸合规(个人信息) | 中 | 数据分级:人脸索引单独 RBAC 权限、审计日志;必要时可关闭人脸模块 |
| 向量空间不一致(模型升级) | 低 | 索引带 model 版本 tag,换模型建新索引 + 后台重刷 |
8. PoC 验证计划(2 周)
- W1-D1~2:单机 Docker Compose(OpenSearch 单节点 + SeaweedFS 单节点 + 1 张 T4 或 CPU)
- W1-D3~5:打通单图全链路(OCR→检测→切图→向量→三索引→三类查询),50 张真实截图人工核对
- W1-D6~7:车牌数据 200-500 张标注,YOLO 初版微调,验证车牌 mAP 与 OCR 准确率
- W2 :压测(1 万图灌入 + 查询 P95 延迟)、混合检索 RRF 调参、出 PoC 报告
- 通过标准:文本查询 P95 < 100ms;以图搜图 Top1 正确率 ≥ 90%(同场景测试集);
车牌识别准确率 ≥ 95%(正面无遮挡子集)
- 通过标准:文本查询 P95 < 100ms;以图搜图 Top1 正确率 ≥ 90%(同场景测试集);
9. 衍生方案:InsightFace + OpenSearch 人脸识别搜索系统
从多模态大方案中拆出的独立子项目:纯人脸识别(检测→特征→入库→1:N 搜索),组件仅 3 个,
是原方案中风险最低、见效最快的部分,可独立先落地。
9.1 可行性结论
完全可行,成熟方案 。InsightFace(buffalo_l)负责检测+对齐+512d 特征,OpenSearch k-NN 负责 1:N 向量检索,人脸原图/切图存 SeaweedFS。
该组合在百万~千万人脸规模下是业界常见架构(AWS Rekognition / 商业人脸识别服务内部也是同款思路:ArcFace 类特征 + ANN 索引)。
9.2 架构与数据流
图片/视频帧
│
▼
InsightFace Worker(onnxruntime,CPU 或 GPU)
├─ 检测: SCRFD/RetinaFace(buffalo_l 自带,多脸、侧脸、小脸)
├─ 对齐: 106 关键点 → 112×112 标准脸
├─ 特征: ArcFace-ResNet50 → 512d(L2 归一化)
├─ 属性: 性别/年龄(可选入库)
└─ 质量门控: 检测置信度 ≥0.6、脸宽 ≥48px、模糊/遮挡过滤
│
├─ 人脸切图(带 bbox 原图) → SeaweedFS /crops/face_{id}.jpg
└─ 文档 → OpenSearch `faces` 索引:
face_id (uuid)
embedding (knn_vector 512d, cosinesimil, HNSW)
source_image_fid / bbox / detected_at / app_name / quality_score
索引配置(与主方案 faces 索引一致):
json
"embedding": { "type": "knn_vector", "dimension": 512,
"method": { "engine": "lucene", "name": "hnsw", "space_type": "cosinesimil",
"parameters": { "m": 16, "ef_construction": 200 } } }
512 维 + cosinesimil:InsightFace 官方推荐度量就是余弦,与 OpenSearch cosinesimil 空间天然匹配,score 换算 = 2 - d / 2(d 为 1-cos 距离),直接用 score 阈值判同人。
9.3 三种搜索形态
| 形态 | 实现 | 典型场景 |
|---|---|---|
| 以脸搜脸(1:N) | 查图过 InsightFace 得 512d → knn 查询 top-k | 给定一张脸找库里所有同/疑似同人 |
| 找某人的所有出现 | 已知 face_cluster_id → filter 查询 | "这个人出现在哪些截图/系统里" |
| 聚类归一(1:1 前置) | 入库时新脸与现有簇中心比对:sim ≥ 阈值 → 归簇;否则建新簇 | 库内"人脸去重/建档",是 1:N 搜索精度基础 |
9.4 关键参数与阈值(必须 PoC 标定,不可拍脑袋)
- 同人阈值 :ArcFace 512d 余弦相似度,公开基准经验区间 0.40~0.55(LFW 类正面数据可取 0.4,跨年龄/光照/角度差数据需上调至 0.5+)。做法:构造同人/异人各 200 对,画 ROC 选阈值,FAR/FRR 平衡;
- 检测置信度 ≥ 0.6、最小脸宽 48px(低于此 112 对齐质量骤降);
- ef_search:默认 100 起调,recall@10 目标 ≥ 99% 时记录对应延迟(百万人脸 P95 约 10-30ms,32G 堆单节点);
- HNSW 参数:m=16 / ef_construction=200 起步;千万级人脸可切 Faiss + int8 量化(512 维量化后约 0.5-1GB/千万,recall 损失 <1%)。
9.5 效果预期
| 场景 | 预期精度 | 依据 |
|---|---|---|
| 同库同人检索(同设备/近同期拍摄) | Top-1 ≥ 95% | 同源截图角度光照差异小 |
| 跨设备/跨时间同人(同角度正面) | 90-95% | ArcFace LFW 99.8%,实际数据衰减 |
| 大角度侧脸 (>60°) / 遮挡(口罩) / 低光 | 显著下降,60-80% | ArcFace 弱项;口罩遮挡基本失效,建议质量分过滤后标注"低置信" |
| 双胞胎/极相似个体 | 无法区分 | 任何 512d 通用模型都难,需 1:1 人工确认兜底 |
9.6 风险与合规(人脸专项,比原方案更重)
- 个人信息法 :人脸属敏感个人信息 ,收集需单独告知+单独同意;库内人脸建议:
- 独立索引 + Security 插件 RBAC 单独授权(仅特定角色可查/可比对)
- 全操作审计日志(谁、何时、用哪张脸查了什么)
- 支持按 face_id 一键删除(GDPR/个保法"被遗忘权"),文档
_id用 face_id 保证可删 - 评估"只存向量不存脸图"的降级模式(向量本身也属个人信息,但风险面小)
- 许可证 (沿用 §3 结论):buffalo_l 预训练模型非商用;商用 → 官方授权 或 自训 ArcFace(开源 Glint360K 子集+自有数据可训,2-3 周 GPU 时间)。
- 误识后果:若用于排查/风控,UI 上必须展示"相似度分值 + 人工确认",不得仅凭阈值自动定性。
9.7 与原多模态方案的关系
- 本方案是主方案的子集 :
faces索引、InsightFace worker、SeaweedFS 路径设计完全复用; - 建议实施顺序:先落地人脸识别子项目(3-4 周含标定)→ 验证 OpenSearch k-NN 运维手感 → 再扩展 OCR/YOLO/SigLIP2 全量能力;
- 单独部署资源:1 台 8C/32G(InsightFace CPU 推理 + OpenSearch 单节点)即可支撑百万级人脸,硬件门槛极低。
10. 下一步
- 确认商用边界 → 定许可证选项(A/B/C)
- 确认硬件(有 GPU?几张卡?),定 worker 部署形态
- 确认截图量级(万/百万/千万)与增量速率 → 定集群规格
- 车牌数据来源(CCPD 够不够?需自采多少)
- 确认后即可进入 PoC 环境搭建 + 车牌数据准备