ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Transformers 零样本目标检测实战:基于 OWL-ViT 的开放词表物体检测指南

Transformers 零样本目标检测实战:基于 OWL-ViT 的开放词表物体检测指南 Transformers 零样本目标检测实战基于 OWL-ViT 的开放词表物体检测指南【免费下载链接】transformers Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers零样本目标检测Zero-shot object detection是计算机视觉中无需针对目标类别进行任何标注训练即可在图像中定位并识别物体的任务。本文以 Transformers 仓库中的 docs/source/ja/tasks/zero_shot_object_detection.md 任务指南为骨架系统讲解如何基于 OWL-ViT 模型完成文本提示检测、批量检测与图像引导检测三类实战场景并结合仓库内 OWL-ViT 的模型、处理器与 pipeline 源码深入说明其内部工作原理与后处理细节。读完本文你将掌握从一行代码调用 pipeline 到手工组装推理全流程的完整技能。从传统检测到零样本检测为什么需要开放词表传统目标检测模型通常依赖带标注的图像数据集进行训练因此只能检测训练数据中出现过的类别集合一旦目标类别不在训练集中模型便无能为力。零样本目标检测采用完全不同的思路模型接收一张图像和一组候选类别以自由文本形式给出直接输出物体所在位置的边界框bounding box与类别标签整个过程不需要针对这些类别做任何微调。实现这一能力的关键模型就是OWL-ViTVision Transformer for Open-World Localization一个开放词表open-vocabulary目标检测器。从仓库源码可以看出 OWL-ViT 的开放词表能力来源它的配置类由OwlViTTextConfig与OwlViTVisionConfig两个子配置组成视觉侧采用 ViT 风格的 Transformer 提取图像特征文本侧采用类 CLIP 的文本编码器模型将多模态表征与轻量级物体分类头OwlViTClassPredictionHead、定位头OwlViTBoxPredictionHead组合实现开放词表检测见 modeling_owlvit.py。检测时先用 CLIP 文本编码器把自由文本查询嵌入成向量再将其作为分类与定位头的输入与图像 patch 特征做相似度匹配。作者先从头训练 CLIP再使用标准检测数据集通过二部匹配损失bipartite matching loss对 OWL-ViT 进行端到端微调。借助这一方案模型无需在标注数据集上预先训练即可根据文本描述检测任意物体。开始动手前请先确认已安装必要依赖pip install -q transformers使用 pipeline 完成零样本目标检测用 OWL-ViT 做推理最简单的方式是通过 Transformers 的pipeline。在transformers.pipelines中任务标识zero-shot-object-detection对应ZeroShotObjectDetectionPipeline见 zero_shot_object_detection.py其模型白名单由 modeling_auto.py 中的MODEL_FOR_ZERO_SHOT_OBJECT_DETECTION_MAPPING_NAMES定义当前包括grounding-dino、owlv2、owlvit等架构本文以经典的google/owlvit-base-patch32检查点为例。 from transformers import pipeline checkpoint google/owlvit-base-patch32 detector pipeline(modelcheckpoint, taskzero-shot-object-detection)接着选择一张要检测物体的图像。这里以 NASA Great Images 数据集中的宇航员 Eileen Collins 照片为例使用skimage加载内置示例图 import skimage import numpy as np from PIL import Image image skimage.data.astronaut() image Image.fromarray(np.uint8(image)).convert(RGB) image把图像和希望查找的候选物体标签一起传给 pipeline。图像可以直接传 PIL 对象也支持本地路径或图片 URL同时传入所有需要查询的文本描述 predictions detector( ... image, ... candidate_labels[human face, rocket, nasa badge, star-spangled banner], ... ) predictions [{score: 0.3571370542049408, label: human face, box: {xmin: 180, ymin: 71, xmax: 271, ymax: 178}}, {score: 0.28099656105041504, label: nasa badge, box: {xmin: 129, ymin: 348, xmax: 206, ymax: 427}}, {score: 0.2110239565372467, label: rocket, box: {xmin: 350, ymin: -1, xmax: 468, ymax: 288}}, {score: 0.13790413737297058, label: star-spangled banner, box: {xmin: 1, ymin: 1, xmax: 105, ymax: 509}}, {score: 0.11950037628412247, label: nasa badge, box: {xmin: 277, ymin: 338, xmax: 327, ymax: 380}}, {score: 0.10649408400058746, label: rocket, box: {xmin: 358, ymin: 64, xmax: 424, ymax: 280}}]用 PIL 的ImageDraw把预测结果可视化 from PIL import ImageDraw draw ImageDraw.Draw(image) for prediction in predictions: ... box prediction[box] ... label prediction[label] ... score prediction[score] ... xmin, ymin, xmax, ymax box.values() ... draw.rectangle((xmin, ymin, xmax, ymax), outlinered, width1) ... draw.text((xmin, ymin), f{label}: {round(score,2)}, fillwhite) image从源码看 pipeline 内部的工作方式ZeroShotObjectDetectionPipeline继承ChunkPipeline在preprocess阶段对每个候选标签分别调用 tokenizer 与 image processor在_forward阶段逐标签前向推理在postprocess阶段调用image_processor.post_process_object_detection过滤低分框、转换为(xmin, ymin, xmax, ymax)格式的字典最后按分数降序排序支持threshold、top_k、timeout等参数见 zero_shot_object_detection.py。手工实现文本提示的零样本目标检测了解 pipeline 的用法后下面手动复现同样的结果以便理解每个环节。首先从 Hub 加载模型和对应的处理器processor。OwlViTProcessor把图像处理器与 CLIP tokenizer 封装为单一实例见 processing_owlvit.py图像处理器负责缩放、归一化图像tokenizer 负责编码文本输入 from transformers import AutoProcessor, AutoModelForZeroShotObjectDetection model AutoModelForZeroShotObjectDetection.from_pretrained(checkpoint) processor AutoProcessor.from_pretrained(checkpoint)换个场景取一张海滩照片 import requests url https://unsplash.com/photos/oj0zeY2Ltk4/download?ixidMnwxMjA3fDB8MXxzZWFyY2h8MTR8fHBpY25pY3xlbnwwfHx8fDE2Nzc0OTE1NDkforcetruew640 im Image.open(requests.get(url, streamTrue).raw) im用处理器准备模型输入。processor内部通过CLIPTokenizer处理文本、通过图像处理器对图像做 resize 与 normalize text_queries [hat, book, sunglasses, camera] inputs processor(texttext_queries, imagesim, return_tensorspt)将输入送入模型、做后处理并可视化结果。由于图像处理器在喂给模型前已对图像做了缩放必须调用post_process_object_detection方法把预测的归一化边界框映射回原图坐标系 import torch with torch.no_grad(): ... outputs model(**inputs) ... target_sizes torch.tensor([im.size[::-1]]) ... results processor.post_process_object_detection(outputs, threshold0.1, target_sizestarget_sizes)[0] draw ImageDraw.Draw(im) scores results[scores].tolist() labels results[labels].tolist() boxes results[boxes].tolist() for box, score, label in zip(boxes, scores, labels): ... xmin, ymin, xmax, ymax box ... draw.rectangle((xmin, ymin, xmax, ymax), outlinered, width1) ... draw.text((xmin, ymin), f{text_queries[label]}: {round(score,2)}, fillwhite) im这段代码的背后逻辑值得展开。OwlViTProcessor在__call__中把文本编码为input_ids与attention_mask把图像编码为pixel_valuesprocessing_owlvit.py。模型的forward流程modeling_owlvit.py依次为image_text_embedder同时计算文本与图像嵌入将图像特征重排为(batch_size, num_patches_height, num_patches_width, hidden_dim)的二维特征图再展平为 patch 序列class_predictor用文本查询嵌入与图像特征做点积相似度得到每个 patch 相对每个查询的 logits分类头还会应用可学习的 logit shift/scalebox_predictor输出每个 patch 中心化的边界框并加上基于特征网格位置计算的 box bias 后经 sigmoid 归一化。后处理时post_process_object_detectionimage_processing_owlvit.py对每个 patch 取 logits 最大值、经 sigmoid 得到置信度把中心格式cxcywh转为角点格式x0y0x1y1再按target_sizes缩放为原图绝对坐标最后用threshold默认 0.1过滤低分预测。注意target_sizes的元素顺序是(height, width)因此用im.size[::-1]把 PIL 的(width, height)反转。另外仓库的OwlViTProcessor还提供post_process_grounded_object_detection便捷方法processing_owlvit.py它内部调用图像处理器的post_process_object_detection并额外根据text_labels把预测的类别索引映射回可读的文本标签输出键包含scores、labels、boxes与text_labels。批量处理一次检测多张图像可以同时传入多组图像与文本查询在多张图像中搜索不同或相同的物体。把宇航员图像与海滩图像组合起来批量处理时文本查询要以嵌套列表形式传给处理器图像则以 PIL 图像、PyTorch 张量或 NumPy 数组的列表形式传入。 images [image, im] text_queries [ ... [human face, rocket, nasa badge, star-spangled banner], ... [hat, book, sunglasses, camera], ... ] inputs processor(texttext_queries, imagesimages, return_tensorspt)处理器对嵌套文本列表的处理逻辑在 processing_owlvit.py 中先计算批次内最大的查询数量不足的样本用空白字符串补齐到相同长度再统一编码后沿 batch 维拼接保证input_ids形状对齐。后处理时此前单张图像用张量传尺寸这里可以传元组多张图像则传元组列表。为两个样本生成预测并可视化第二个样本image_idx 1 with torch.no_grad(): ... outputs model(**inputs) ... target_sizes [x.size[::-1] for x in images] ... results processor.post_process_object_detection(outputs, threshold0.1, target_sizestarget_sizes) image_idx 1 draw ImageDraw.Draw(images[image_idx]) scores results[image_idx][scores].tolist() labels results[image_idx][labels].tolist() boxes results[image_idx][boxes].tolist() for box, score, label in zip(boxes, scores, labels): ... xmin, ymin, xmax, ymax box ... draw.rectangle((xmin, ymin, xmax, ymax), outlinered, width1) ... draw.text((xmin, ymin), f{text_queries[image_idx][label]}: {round(score,2)}, fillwhite) images[image_idx]post_process_object_detection的返回值是列表每个元素对应该批次中的一张图像包含scores、labels、boxes三个键。若target_sizes的数量与 batch 不一致实现会直接抛出ValueError提示image_processing_owlvit.py因此批量场景下务必为每张图像都提供目标尺寸。图像引导的目标检测除了文本查询OWL-ViT 还支持图像引导image-guided检测用一个示例图像作为查询在目标图像中寻找与之相似的物体。与文本查询不同图像引导场景只允许一个示例图像作为查询。取一张沙发上两只猫的图像作为目标图像另取一张单只猫的图像作为查询 url http://images.cocodataset.org/val2017/000000039769.jpg image_target Image.open(requests.get(url, streamTrue).raw) query_url http://images.cocodataset.org/val2017/000000524280.jpg query_image Image.open(requests.get(query_url, streamTrue).raw)先快速查看这两张图像 import matplotlib.pyplot as plt fig, ax plt.subplots(1, 2) ax[0].imshow(image_target) ax[1].imshow(query_image)预处理阶段不再传文本查询而是改用query_images参数 inputs processor(imagesimage_target, query_imagesquery_image, return_tensorspt)此时处理器内部会把查询图像编码为query_pixel_values见 processing_owlvit.py并且查询图像会覆盖文本提示模型执行的是图像到图像的匹配而非文本到图像匹配。预测阶段不再把输入直接传给模型而是传给image_guided_detection方法modeling_owlvit.py绘制预测框的方式与之前相同只是没有标签 with torch.no_grad(): ... outputs model.image_guided_detection(**inputs) ... target_sizes torch.tensor([image_target.size[::-1]]) ... results processor.post_process_image_guided_detection(outputsoutputs, target_sizestarget_sizes)[0] draw ImageDraw.Draw(image_target) scores results[scores].tolist() boxes results[boxes].tolist() for box, score, label in zip(boxes, scores, labels): ... xmin, ymin, xmax, ymax box ... draw.rectangle((xmin, ymin, xmax, ymax), outlinewhite, width4) image_target图像引导检测的底层原理可以从源码中看到全貌。image_guided_detection依次执行分别对查询图像和目标图像调用image_embedder提取特征图embed_image_querymodeling_owlvit.py对查询图像先做一次分类与定位预测选出与整张查询图 IoU 最高的候选框区域聚合出最能代表查询对象的 class embedding 作为视觉查询向量用该视觉查询向量对目标图像执行与文本查询相同的分类与定位预测。对应的后处理方法是post_process_image_guided_detectionimage_processing_owlvit.py它比文本版本多了NMS非极大值抑制步骤按分数从高到低遍历预测框抑制与高置信度框 IoU 超过nms_threshold默认 0.3的重复框再按threshold默认 0.0过滤。返回值中labels一律为None因为该场景是单次one-shot检测没有类别标签。交互式体验与延伸阅读如果想交互式地体验 OWL-ViT 推理可以运行huggingface_hub上的 OWL-ViT Space 演示应用。此外仓库中还提供了更深入的资料可供继续探索OWL-ViT 模型总览与使用技巧docs/source/en/model_doc/owlvit.md其中包含OwlViTProcessorOwlViTForObjectDetection的完整示例模型配置文本/视觉子配置与默认超参configuration_owlvit.py模型前向、图像引导检测与各类预测头实现modeling_owlvit.py处理器与后处理方法processing_owlvit.py、image_processing_owlvit.pypipeline 封装与参数说明zero_shot_object_detection.py模型测试用例验证前向、后处理与批处理行为tests/models/owlvitCLIP 多模态骨干网络文档docs/source/ja/model_doc/clip.md。实际部署时需要注意几点其一pipeline 支持传入图片 URL、本地路径与 PIL 对象批量检测可直接传图像列表与对应标签列表zero_shot_object_detection.py其二手工推理务必传入正确的target_sizes(height, width)顺序否则边界框坐标会错位其三文本查询数量在批次内会被自动补齐最终预测分数可通过调整threshold与 NMS 相关参数平衡召回率与精确率。【免费下载链接】transformers Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进