LocateAnything解读

目录

一、核心任务定义与行业背景

[二、LocateAnything 整体框架架构](#二、LocateAnything 整体框架架构)

[三、核心创新 1:并行框解码(PBD)深度解析](#三、核心创新 1:并行框解码(PBD)深度解析)

[四、核心创新 2:LocateAnything-Data 大规模数据集](#四、核心创新 2:LocateAnything-Data 大规模数据集)

五、实验评测与核心量化结果

六、论文五大核心贡献

七、主流方案横向对比

八、细分应用场景(产业落地方向)

九、工作局限性与现存问题

十、未来研究拓展方向

十一、全文总结

十二、代码实测


论文《LocateAnything: Fast and High-Quality Vision-Language Grounding with Parallel Box Decoding》超详细解读

论文链接2605.27365 LocateAnything: Fast and High-Quality Vision-Language Grounding with Parallel Box Decoding

版本信息:v1 提交于 2026 年 5 月 26 日,v2 修订版发布于 2026 年 5 月 27 日;DOI:10.48550/arXiv.2605.27365

所属领域:计算机视觉与模式识别 (cs.CV)、人工智能 (cs.AI)、机器学习 (cs.LG)、机器人学 (cs.RO)

作者团队:由 NVIDIA 联合香港理工大学、普林斯顿大学、南京大学等多所高校与企业研究者共同完成,核心作者包含 Shihao Wang、Shilong Liu、Zhiding Yu 等,是视觉语言模型(VLM)领域顶尖联合团队。

开源状态 :已开源轻量化版本 LocateAnything-3B(30 亿参数),支持主流部署框架,可覆盖多类视觉定位落地场景。

https://huggingface.co/nvidia/LocateAnything-3B

一、核心任务定义与行业背景

1. 核心任务界定

本文聚焦统一视觉几何定位任务,一套框架同时支持六大细分场景,覆盖当下工业界主流视觉定位需求:

  1. 视觉语言定位(Vision-Language Grounding):输入图像 + 自然语言指令,在图中定位文本描述的目标(如 "找出图中的红色水杯");
  2. 开放词汇目标检测:无固定类别限制,识别图像内所有目标并输出边界框;
  3. GUI 界面定位:智能体自动识别软件界面按钮、输入框等交互元素;
  4. 文档解析定位:定位文档内表格、文字、图片等版式元素;
  5. OCR 文本定位:精准框选图像中的文本区域;
  6. 图像 / 视频指点定位:基于视觉指向信号完成目标框选。

这类任务是机器人具身智能、自动驾驶、智能办公、视频安防、移动端 AI 交互的核心底层能力 ,对推理速度定位精度(尤其是高 IoU 精细定位) 均有严苛要求。

2. 现有主流技术路线与通用痛点

当前绝大多数视觉语言模型(如 Qwen-VL、LLaVA、Ferret 等)均采用坐标 Token 串行自回归解码方案,也是本文重点批判的技术范式。

(1)传统范式工作原理

模型将表征目标的二维边界框(x ₁,y ₁,x ₂,y ₂) 拆解为多个独立一维坐标 Token,按照固定时序逐一生成:<bbox_start> → x₁ → y₁ → x₂ → y₂ → <bbox_end>。每一个 Token 的生成严格依赖前序所有 Token,属于典型的串行自回归逻辑。

行业内现有方案分为两类,但缺陷高度一致:

  • 原生 Token 方案:复用大语言模型词表生成坐标,改造成本低,但解码速度慢、易出现幻觉;
  • 新增专用 Token 方案:引入额外视觉定位 Token,精度略有提升,但仍无法摆脱串行时序依赖,且需要大规模重训。

(2)两大根本性瓶颈(论文核心切入点)

1.几何结构失配,高 IoU 定位精度差

边界框的四个坐标是强耦合几何单元 (天然满足x₂>x₁、y₂>y₁的空间约束),但逐 Token 独立学习、解码会割裂坐标间的关联。模型难以隐式学习几何规则,极易生成畸形框、坐标错位、非法边界框,在高 IoU(交并比)精细定位场景(如机器人抓取、医疗影像)误差尤为突出。

2.串行生成导致推理吞吐量瓶颈

自回归解码的时间复杂度为 O(K*N)(K为单目标框的 Token 数量,N为图像内目标总数)。目标越多,解码步数线性膨胀,推理时延急剧升高。该问题直接限制模型在实时机器人、海量视频流、端侧设备等低时延场景的落地。

简单类比:传统串行解码如同逐字念电话号码 ,必须按顺序逐个输出数字;而本文方案则是一次性输出完整号码,从底层重构解码逻辑。

二、LocateAnything 整体框架架构

LocateAnything 是一套生成式统一视觉定位与检测框架,基于现有主流 VLM 架构轻量化改造,核心仅替换解码层为并行框解码(PBD),兼容现有视觉编码器、跨模态融合模块,迁移成本极低。整体流水线分为 5 个模块,全链路支持上述六大定位任务:

  1. 多模态输入分支
    • 视觉语言定位 / GUI / 文档任务:输入图像 + 自然语言 Prompt
    • 纯目标检测 / OCR 任务:仅输入图像,搭配内置任务指令。
  2. 视觉编码器

沿用成熟图像特征提取主干,输出图像全局与局部视觉特征,保证视觉表征能力的延续性。

3.跨模态融合层

融合视觉特征与文本特征(纯检测任务可跳过文本分支),生成统一多模态特征,送入解码模块。

4.核心解码层:Parallel Box Decoding(PBD,并行框解码)

框架核心创新模块,替代传统串行 Token 解码器,将边界框、关键点等几何元素作为原子单元单步解码

5.后处理校验层

对 PBD 输出的坐标做简单规则校验(过滤x₂<x₁等非法框),最终输出目标边界框、对应文本 / 类别标签,完成全流程推理。

架构核心优势:一套框架兼容多类视觉定位任务,无需为不同场景设计独立分支,工程部署效率高。

三、核心创新 1:并行框解码(PBD)深度解析

Parallel Box Decoding(PBD)是论文最核心的技术贡献,也是突破传统范式的关键。该方案借鉴多 Token 预测(MTP) 思想,并针对视觉几何任务做定制化改造,是业内首次将块级并行解码系统性落地于 VLM 视觉定位任务。

1. 核心设计理念

摒弃 "拆分坐标 + 逐 Token 串行生成" 的思路,定义视觉几何原子单元 :将完整 2D 边界框、图像关键点视为不可拆分的基础解码单元。模型在单次前向传播中直接预测整个几何单元的所有坐标,无时序依赖、无需分步解码。

2. 工作机制与时间复杂度优化

  1. 单框解码逻辑:一个边界框(4 个坐标)被封装为一个固定长度的原子 Token 块,模型一步输出(x₁,y₁,x₂,y₂)全部坐标,解码步数从 4 步压缩为 1 步;
  2. 多目标并行逻辑:当图像内存在多个目标框时,所有几何原子单元可并行解码,互不等待;
  3. 复杂度变化:解码时间复杂度从传统串行的 O(K*N) 降至 O(N),极端批量场景下可接近 O(1),吞吐量实现质的飞跃。

3. 两大核心价值

  1. 保全几何一致性,提升高 IoU 精度

由于模型直接学习完整边界框的特征,天然建模四个坐标的空间约束关系,从根源减少畸形框、坐标偏移问题。实验证明,该设计对高 IoU(IoU>0.8、IoU>0.9)精细定位的提升效果最为显著。

2.释放并行算力,彻底解决推理时延瓶颈

消除自回归的时序依赖,硬件算力可被充分利用。在批量图像处理、密集目标检测场景下,解码吞吐量远高于传统串行方案,完美适配实时交互场景。

4. 三种自适应推理模式(落地关键设计)

为兼顾极致速度极限精度,团队针对不同业务场景设计三类解码模式,可动态切换:

  1. Fast Mode(快速模式)

纯 PBD 并行解码,优先保障吞吐量与低时延。适配机器人实时抓取、GUI 自动化、实时监控等强实时场景。

2.Slow Mode(高精度模式)

保留部分串行校验逻辑,牺牲少量速度换取极致定位精度。适配离线图像标注、医疗影像定位、工业质检等对时延无要求、但精度要求极高的场景。

3.Hybrid Mode(混合模式,默认模式)

智能自适应切换:常规场景使用 PBD 并行解码;当检测到格式异常、空间歧义、目标遮挡严重时,自动切回传统串行解码兜底。平衡速度与鲁棒性,是通用场景最优选择。

5. 解码范式横向对比

解码范式 生成逻辑 几何一致性 推理速度 适用场景
传统逐 Token 串行解码 逐个生成坐标 Token,强时序依赖 差,易出现畸形框 慢,目标越多越卡顿 离线高精度评测(老旧方案)
通用多 Token 预测 (MTP) 单步预测多个文本 Token 无几何约束,不适配视觉框 较快 纯文本生成任务
本文 PBD 并行框解码 完整边界框 / 关键点作为原子单元单步输出 优,天然匹配几何约束 极快,支持多目标并行 全场景视觉定位、检测

四、核心创新 2:LocateAnything-Data 大规模数据集

仅靠解码范式优化无法充分挖掘模型性能上限,团队配套搭建可扩展数据引擎,并构建了业内规模领先的视觉定位数据集 LocateAnything-Data,与 PBD 形成互补增益。

1. 数据集核心参数

  • 总训练样本:超 1.38 亿条
  • 独立原图数量:1200 万张;
  • 标注边界框总量:7.85 亿个;
  • 覆盖任务:六大类视觉定位子任务(视觉语言定位、目标检测、GUI 定位、文档解析、OCR、指点定位)。

2. 可扩展数据引擎作用

自研流水线支持海量数据爬取、清洗、去重、标注对齐、格式统一,解决了亿级数据集构建过程中的效率、噪声、格式不统一三大工程难题,保障数据集质量与迭代能力。

3. 数据多样性设计(精度提升核心支撑)

传统视觉定位数据集普遍存在场景单一、小目标 / 遮挡目标样本不足、图文配对匮乏等问题。该数据集从 5 个维度强化多样性:

  1. 场景多样性:覆盖自然场景、室内家居、工业车间、交通路况、办公文档、软件界面等全行业场景;
  2. 目标多样性:包含常规大目标、极小目标、遮挡目标、低分辨率模糊目标、细粒度相似目标;
  3. 模态配对多样性:海量图文配对样本,强化图像特征与自然语言的关联能力;
  4. 标注多样性:统一边界框标注规范,同时兼容检测、定位两类任务的标注逻辑;
  5. 成像多样性:包含不同光照、角度、画质的图像,提升模型复杂工况下的鲁棒性。

4. 数据集与 PBD 的协同关系

论文通过消融实验证实二者具备强互补性

  1. 仅使用 PBD + 传统小规模数据集:推理速度大幅提升,但高精度定位能力受数据限制,上限较低;
  2. 仅使用串行解码 + LocateAnything-Data 大数据集:精度小幅提升,但串行解码的速度瓶颈无法解决;
  3. PBD + LocateAnything-Data 组合:同时实现速度暴涨高 IoU 精度跃升,达到最优综合性能。

五、实验评测与核心量化结果

团队在COCO、LVIS、DocLayNet、ScreenSpot-Pro等 7 个业内主流基准数据集上完成全维度评测,同时对比数十款主流 VLM 与专用定位模型,核心结果如下:

1. 核心评测指标

  • 速度指标:解码吞吐量(samples/second,单位时间处理样本数)、单样本推理时延;
  • 精度指标:高 IoU 定位准确率、LVIS mean F1、mAP(目标检测通用指标)、GUI / 文档任务专项精度。

2. 关键量化结论

  1. 推理速度突破

相比主流基线模型 Qwen3-VL,解码吞吐量最高提升 11.5 倍;综合场景下平均吞吐提升 2.5 倍以上。3B 轻量化模型即可实现远超 30B 大模型的推理速度,端侧落地优势显著。

  1. 定位精度全面领先
    • LVIS 数据集 mean F1 指标相比基线提升3.8%
    • 所有基准数据集上,高 IoU 定位质量实现碾压式提升,畸形框、坐标错误大幅减少;
    • 轻量化 3B 版本在 GUI 定位任务中,性能超越 Qwen3-VL-30B、专用模型 GUI-Owl-32B 等百亿级大模型,实现 "小模型打大模型"。
  2. 速度 - 精度权衡被打破

传统视觉定位模型普遍存在 "提速必降精度、提精度必降速度" 的矛盾。LocateAnything 首次在通用视觉定位领域推进了速度 - 精度前沿(speed-accuracy frontier),做到 "速度、精度双提升"。

2.多任务泛化能力优异

在文档解析、OCR、视频定位等细分任务上均取得 SOTA(当前最优)结果,证明框架具备极强的通用泛化能力,并非针对单一数据集过拟合。

3. 消融实验核心结论

  1. PBD 并行解码是速度提升的核心因素,同时直接改善框的几何合理性;
  2. 1.38 亿规模的 LocateAnything-Data 是高精度、强泛化能力的核心支撑;
  3. 两大模块缺一不可,组合使用才能发挥最大价值,验证了论文 "并行解码 + 大规模数据" 的核心思路。

六、论文五大核心贡献

结合学术创新、技术落地、工程价值三个维度,可将本文贡献分为五类:

1. 范式创新(学术层面)

打破生成式 VLM 领域 "坐标 Token 串行自回归解码" 的主流范式,首次将几何原子单元并行解码系统性应用于视觉定位与检测任务。证明 "贴合视觉任务几何特性的解码逻辑",远优于通用文本式逐 Token 解码,为领域提供全新建模思路。

2. 技术模块创新(算法层面)

设计通用型PBD 并行框解码模块,轻量化、即插即用,可无缝嵌入绝大多数现有生成式视觉语言模型,改造成本低、复用性强;同时原生支持边界框、关键点两类几何元素,具备向其他视觉几何任务拓展的潜力。

3. 统一框架创新(工程层面)

搭建 LocateAnything 统一生成式框架,一套架构兼容 6 大类视觉定位子任务,简化多场景部署流程,降低工业界落地成本。

4. 数据集贡献(资源层面)

发布超 1.38 亿样本的 LocateAnything-Data 数据集,并开源可扩展数据引擎方案。海量多样化数据补齐了高精度视觉定位的数据短板,为后续同领域研究提供高质量公共资源。

5. 落地工程创新(产业层面)

设计 Fast/Slow/Hybrid 三类自适应推理模式,兼顾实时场景与高精度场景需求;开源 3B 轻量化模型,让高性能视觉定位能力可下沉至端侧设备、小型机器人,推动技术从实验室走向产业落地。

七、主流方案横向对比

技术方案 代表模型 优势 核心缺陷 本文 LocateAnything 优势
传统 CNN/Transformer 检测器(非生成式) YOLO、Faster R-CNN 推理速度快、检测精度稳定 无法原生融合自然语言,不支持视觉语言定位任务 保留多模态能力,速度持平甚至超越传统检测器
串行 Token 解码生成式 VLM Qwen-VL、LLaVA 统一架构、多模态能力强 速度慢、高 IoU 定位精度差 PBD 解码提速 10 倍以上,同时优化精细定位精度
专用视觉定位大模型 GUI-Owl、RefCOCO 专项模型 细分任务精度高 通用性差、模型体积庞大、推理时延高 3B 小模型性能超越百亿级专用模型,全场景通用

八、细分应用场景(产业落地方向)

依托 "高速 + 高精度 + 多任务通用" 三大特性,LocateAnything 可覆盖全行业视觉定位需求,核心落地场景如下:

  1. 机器人具身智能(核心场景)
  • 场景:服务机器人语音指令抓取、工业机器人工件定位、机器人导航避障;
  • 需求匹配:Fast 模式低时延满足实时交互,PBD 高 IoU 精度保障抓取、作业的准确性。
  1. 智能 GUI 自动化与办公文档解析
  • 场景:AI 智能体操作软件、自动化办公、PDF / 纸质文档版式解析;
  • 需求匹配:兼容 GUI 定位、文档解析双任务,混合模式平衡速度与歧义处理能力。
  1. 自动驾驶与车载感知
  • 场景:车外行人、车辆、路障精细化定位,车内交互界面识别;
  • 需求匹配:高 IoU 精度保障行车安全,低时延适配车载实时感知系统。
  1. 智能安防与视频大数据分析
  • 场景:海量监控视频目标检索、异常行为目标定位;
  • 需求匹配:高并行解码吞吐,可批量处理视频流,亿级数据集保障复杂场景泛化性。
  1. 移动端与嵌入式端 AI
  • 场景:手机智能识图、图文搜图、AR 交互、嵌入式视觉设备;
  • 需求匹配:3B 轻量化模型算力消耗低,适配端侧有限硬件资源。
  1. 医疗影像辅助诊断(拓展场景)
  • 场景:CT、X 光片病灶区域定位(结合文本病灶描述);
  • 需求匹配:Slow 模式极致高 IoU 精度,满足医疗影像精细标注需求。

九、工作局限性与现存问题

基于论文原文及公开评测信息,该工作仍存在部分待优化点,也是后续研究的切入点:

  1. 复杂几何任务拓展不足

目前 PBD 仅验证了边界框、关键点两类简单几何单元,尚未针对语义分割、实例分割、3D 视觉框等复杂几何结构做适配,向分割、3D 视觉领域拓展的有效性仍需验证。

2.极端工况鲁棒性待补充

公开实验未重点测试极小黑目标、完全遮挡、全模糊图像、极端光照等极限场景,模型在恶劣工况下的稳定性有待进一步验证。

3.数据集细节未完全公开

仅披露数据集规模与任务覆盖范围,未公开数据来源、类别分布、偏见检测结果,后续研究者使用时需自行校验数据公平性与噪声情况。

4.混合模式歧义处理仍有优化空间

当图像内目标高度重叠、语义模糊时,混合模式切换串行解码的频率升高,小幅损失整体吞吐量。

十、未来研究拓展方向

结合本文核心思路与行业痛点,后续研究可从技术拓展、模型优化、数据迭代、落地优化四大方向推进:

1. 技术模块拓展(短期)

  1. 将 PBD 并行解码拓展至语义分割、人体姿态估计、实例分割等视觉几何任务;
  2. 基于 PBD 设计 3D 边界框并行解码方案,拓展至 3D 视觉定位、3D 目标检测。

2. 模型轻量化与架构优化(工程向)

  1. 针对微型嵌入式设备做模型蒸馏、量化、剪枝,进一步降低端侧算力消耗;
  2. 设计动态块解码策略,根据目标复杂度自适应调整并行块大小,进一步优化速度 - 精度平衡。

3. 数据集迭代与优化(数据向)

  1. 对 LocateAnything-Data 做去偏、去噪处理,构建医疗、自动驾驶等细分领域专用子集;
  2. 结合弱监督、自监督技术,降低亿级数据集的人工标注成本。

4. 多模态与视频场景升级(中长期)

  1. 结合大语言模型(LLM)实现 "逻辑推理 + 视觉定位" 端到端联动,支持复杂多轮指令定位;
  2. 将 PBD 拓展至视频领域,实现帧间目标跟踪 + 定位的时空联合并行解码。

5. 落地部署优化

针对云端集群、边缘设备做算子优化、推理引擎适配,结合动态批处理技术,进一步放大 PBD 的并行吞吐优势。

十一、全文总结

1. 核心逻辑复盘

传统视觉语言定位模型:二维边界框拆分→一维坐标 Token→串行逐步解码 → 几何割裂 + 推理卡顿;

本文 LocateAnything:边界框 / 关键点作为几何原子单元→PBD 单步并行解码 (保全几何一致性 + 提速)+ 1.38 亿大规模数据集(提升泛化与精度)→ 打破速度 - 精度权衡,实现双维度突破。

2. 论文核心价值总结

  1. 算法层面:用 PBD 并行框解码重构了 VLM 视觉定位的解码范式,从底层解决串行解码的两大历史痛点;
  2. 数据层面:构建亿级多任务数据集,拉高了高精度视觉定位的训练数据门槛;
  3. 产业层面:轻量化模型 + 多自适应推理模式,让高速、高精度视觉定位技术全面走向端侧、机器人、安防等落地场景;
  4. 领域引领:为后续视觉几何任务、多模态大模型解码设计提供了全新思路,推动视觉语言定位领域进入 "并行解码" 新阶段。

整体而言,LocateAnything 是一篇理论创新扎实、工程落地完善、产业价值突出的标杆性工作,也是 2026 年视觉语言模型领域针对视觉定位任务的代表性成果。

十二、代码实测

测试代码,

复制代码
#locate.py
import re
import torch
from PIL import Image
from transformers import AutoModel, AutoTokenizer, AutoProcessor
from PIL import Image, ImageDraw, ImageFont

class LocateAnythingWorker:
    """Stateful worker that loads the model once and serves perception queries."""

    def __init__(self, model_path: str, device: str = "cuda", dtype=torch.bfloat16):
        self.device = device
        self.dtype = dtype

        self.tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
        self.processor = AutoProcessor.from_pretrained(model_path, trust_remote_code=True)
        self.model = AutoModel.from_pretrained(
            model_path,
            torch_dtype=dtype,
            trust_remote_code=True,
        ).to(device).eval()

    @torch.no_grad()
    def predict(
        self,
        image: Image.Image,
        question: str,
        generation_mode: str = "hybrid",   # "fast" (MTP) | "slow" (NTP/AR) | "hybrid"
        max_new_tokens: int = 2048,
        temperature: float = 0.7,
        verbose: bool = True,
    ) -> dict:
        messages = [
            {"role": "user", "content": [
                {"type": "image", "image": image},
                {"type": "text", "text": question},
            ]}
        ]

        text = self.processor.py_apply_chat_template(
            messages, tokenize=False, add_generation_prompt=True
        )
        images, videos = self.processor.process_vision_info(messages)
        inputs = self.processor(
            text=[text], images=images, videos=videos, return_tensors="pt"
        ).to(self.device)

        pixel_values = inputs["pixel_values"].to(self.dtype)
        input_ids = inputs["input_ids"]
        image_grid_hws = inputs.get("image_grid_hws", None)

        response = self.model.generate(
            pixel_values=pixel_values,
            input_ids=input_ids,
            attention_mask=inputs["attention_mask"],
            image_grid_hws=image_grid_hws,
            tokenizer=self.tokenizer,
            max_new_tokens=max_new_tokens,
            use_cache=True,
            generation_mode=generation_mode,
            temperature=temperature,
            do_sample=True,
            top_p=0.9,
            repetition_penalty=1.1,
            verbose=verbose,
        )

        result = {"answer": response[0] if isinstance(response, tuple) else response}
        if isinstance(response, tuple) and len(response) >= 3:
            result["history"] = response[1]
            result["stats"] = response[2]
        return result

    # ---- Convenience methods for each task ----

    def detect(self, image: Image.Image, categories: list[str], **kwargs) -> dict:
        """Object detection / document layout analysis."""
        cats = "</c>".join(categories)
        prompt = f"Locate all the instances that matches the following description: {cats}."
        return self.predict(image, prompt, **kwargs)

    def ground_single(self, image: Image.Image, phrase: str, **kwargs) -> dict:
        """Phrase grounding --- single instance."""
        prompt = f"Locate a single instance that matches the following description: {phrase}."
        return self.predict(image, prompt, **kwargs)

    def ground_multi(self, image: Image.Image, phrase: str, **kwargs) -> dict:
        """Phrase grounding --- multiple instances."""
        prompt = f"Locate all the instances that match the following description: {phrase}."
        return self.predict(image, prompt, **kwargs)

    def ground_text(self, image: Image.Image, phrase: str, **kwargs) -> dict:
        """Text grounding."""
        prompt = f"Please locate the text referred as {phrase}."
        return self.predict(image, prompt, **kwargs)

    def detect_text(self, image: Image.Image, **kwargs) -> dict:
        """Scene text detection."""
        prompt = "Detect all the text in box format."
        return self.predict(image, prompt, **kwargs)

    def ground_gui(self, image: Image.Image, phrase: str, output_type: str = "box", **kwargs) -> dict:
        """GUI grounding (box or point)."""
        if output_type == "point":
            prompt = f"Point to: {phrase}."
        else:
            prompt = f"Locate the region that matches the following description: {phrase}."
        return self.predict(image, prompt, **kwargs)

    def point(self, image: Image.Image, phrase: str, **kwargs) -> dict:
        """Pointing."""
        prompt = f"Point to: {phrase}."
        return self.predict(image, prompt, **kwargs)

    # ---- Utility: parse model output ----

    @staticmethod
    def parse_boxes(answer: str, image_width: int, image_height: int) -> list[dict]:
        """Parse model output into pixel-coordinate bounding boxes.

        Coordinates in model output are normalized integers in [0, 1000].
        """
        boxes = []
        for m in re.finditer(r"<box><(\d+)><(\d+)><(\d+)><(\d+)></box>", answer):
            x1, y1, x2, y2 = [int(g) for g in m.groups()]
            boxes.append({
                "x1": x1 / 1000 * image_width,
                "y1": y1 / 1000 * image_height,
                "x2": x2 / 1000 * image_width,
                "y2": y2 / 1000 * image_height,
            })
        return boxes

    @staticmethod
    def parse_points(answer: str, image_width: int, image_height: int) -> list[dict]:
        """Parse model output into pixel-coordinate points."""
        points = []
        for m in re.finditer(r"<box><(\d+)><(\d+)></box>", answer):
            x, y = int(m.group(1)), int(m.group(2))
            points.append({
                "x": x / 1000 * image_width,
                "y": y / 1000 * image_height,
            })
        return points



# ---- NEW: visualize detection result on image ----

    @staticmethod
    def visualize(image: Image.Image, answer: str, output_path: str = "detection_output.jpg"):
        """Parse detection answer and draw boxes/labels on the image, then save.

        Output format in terminal:
            Detection: <ref>person</ref><box><0><512><98><807></box>...
        """
        img = image.copy()
        draw = ImageDraw.Draw(img)
        w, h = img.size

        # Color palette for different categories
        colors = [
            (255, 0, 0),    # red
            (0, 255, 0),    # green
            (0, 0, 255),    # blue
            (255, 255, 0),  # yellow
            (255, 0, 255),  # magenta
            (0, 255, 255),  # cyan
            (255, 128, 0),  # orange
            (128, 0, 255),  # purple
        ]

        # Try to load a decent font; fallback to default if unavailable
        try:
            font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 20)
        except Exception:
            try:
                font = ImageFont.truetype("DejaVuSans.ttf", 20)
            except Exception:
                font = ImageFont.load_default()

        ref_re = re.compile(r'<ref>(.*?)</ref>')
        box_re = re.compile(r'<box>(.*?)</box>')
        coord_re = re.compile(r'<(\d+)>')

        refs = list(ref_re.finditer(answer))
        color_idx = 0

        for i, ref_m in enumerate(refs):
            label = ref_m.group(1)
            start = ref_m.end()
            end = refs[i + 1].start() if i + 1 < len(refs) else len(answer)
            segment = answer[start:end]

            color = colors[color_idx % len(colors)]
            color_idx += 1

            for box_m in box_re.finditer(segment):
                content = box_m.group(1).strip()
                if content == "None" or not content:
                    continue

                nums = coord_re.findall(content)
                if len(nums) != 4:
                    continue

                x1, y1, x2, y2 = [int(n) for n in nums]
                px1 = x1 / 1000 * w
                py1 = y1 / 1000 * h
                px2 = x2 / 1000 * w
                py2 = y2 / 1000 * h

                # Draw bounding box
                draw.rectangle([px1, py1, px2, py2], outline=color, width=3)

                # Draw label background
                text = label
                bbox = draw.textbbox((0, 0), text, font=font)
                tw, th = bbox[2] - bbox[0], bbox[3] - bbox[1]

                ty1 = max(0, py1 - th - 4)
                ty2 = py1
                draw.rectangle([px1, ty1, px1 + tw + 4, ty2], fill=color)
                draw.text((px1 + 2, ty1), text, fill=(255, 255, 255), font=font)

        img.save(output_path)
        print(f"Image saved to: {output_path}")
        print("Detection:", answer)
        return output_path




if __name__=="__main__":
    worker = LocateAnythingWorker("./LocateAnything-3B")
    img = Image.open("bus.jpg").convert("RGB")

    # Object Detection
    result = worker.detect(img, ["person", "car", "bicycle", "bus", "window", "glasses", "hand", "shoes"])
    print("Detection:", result["answer"])
    # >>> 新增:可视化并保存 <<<
    worker.visualize(img, result["answer"], output_path="bus_detection.jpg")

    # Phrase Grounding (multiple)
    result = worker.ground_multi(img, "people wearing red shirts")
    print("Grounding:", result["answer"])

    # Scene Text Detection
    result = worker.detect_text(img)
    print("Text Detection:", result["answer"])

    # Pointing
    result = worker.point(img, "the traffic light")
    print("Pointing:", result["answer"])

    # GUI Grounding (point)
    result = worker.ground_gui(img, "the search button", output_type="point")
    print("GUI Point:", result["answer"])

    # Parse structured output into pixel coordinates
    w, h = img.size
    boxes = LocateAnythingWorker.parse_boxes(result["answer"], w, h)
    points = LocateAnythingWorker.parse_points(result["answer"], w, h)

个人感觉主流的目标检测大类都可以识别,效果也非常好,对于细分领域的小众类别无法识别。比如识别煤矿的球磨机、钩子等就识别不出。

相关推荐
FrameNotWork3 小时前
HarmonyOS6.1 从图像分类到目标检测的扩展实现
人工智能·harmonyos
智联物联3 小时前
办公楼转型养老公寓,边缘计算网关实现全场景智慧监护
人工智能·边缘计算·物联网解决方案·工业网关·智慧养老·数采网关·边缘盒子
库拉大叔3 小时前
工具调用效率对比实测:GPT-5.5与Gemini 3.5 Flash性能评估
java·前端·人工智能
智讯天下3 小时前
专业的高端智能照明品牌哪家好?从光学技术、系统稳定性、设计认证、服务保障四个维度看
人工智能·智能手机
xiami_world3 小时前
2026年UI/UX设计工具私有化部署方案深度解析
人工智能·ui·ai·产品经理·ux
无忧智库4 小时前
基于C4ISR与数据链的智慧应急体系:从“透明战场”到“透明城市”的数字化指挥解决方案(170页PPT)
大数据·人工智能·智慧城市
罗小罗同学4 小时前
哈佛团队在Nat Med发表医学AI模型,可以在任务推理阶段实时调整推理方式,无需重新训练
人工智能·医学图像处理·医工交叉·医学ai
杭州默安科技4 小时前
AI挖掘0day漏洞常态化,企业网络防御该如何破局?
人工智能·网络安全