跳到主要内容

LocateAnything-3B

· 阅读需 7 分钟
otqsoft
Front And Rear End Engineers @ gitee

LocateAnything 是一种视觉-语言模型,用于实现快速且高质量的视觉定位,能够在企业智能(Enterprise Intelligence)和物理人工智能(Physical AI)等多个领域中进行精确的目标定位、密集检测和基于点的定位。该模型采用通用设计,支持指代表达定位、多目标检测、GUI 元素定位和文本定位等任务,并在复杂和杂乱场景中表现出色。其核心创新——并行边界框解码(Parallel Box Decoding, PBD)——通过单次并行步骤预测完整的边界框坐标,而非采用自回归方式逐个生成标记(token),从而在保持几何一致性的同时提升了效率。与先前方法相比,吞吐量最高可提升 2.5 倍。

该模型在一个大规模多领域数据集上训练而成(包含 1200 万张图像、1.38 亿+ 查询和 7.85 亿个边界框),涵盖自然场景、机器人、自动驾驶、GUI 交互和文档理解等领域。它作为通用多模态感知的基础模型,已被集成到 NVIDIA 最新一代的生产级视觉-语言模型中,例如 Nemotron 3 Nano Omni,用于支持定位、GUI 理解和多模态智能体能力。

1. 模型概览

特性描述
模型架构基于 Transformer 的视觉-语言模型 (VLM)
参数量30 亿 (3B)
视觉编码器MoonViT
语言模型Qwen2.5-3B-Instruct
核心优势并行解码,吞吐量比传统方法提升最高 2.5 倍
支持分辨率生产环境最高支持 2.5K 分辨率

2. 环境配置与安装

在开始之前,请确保你的环境中已安装 PyTorch(需匹配你的 CUDA 版本)。

基础依赖安装:

pip install opencv-python-headless==4.11.0.86 transformers==4.57.1 numpy==1.25.0 Pillow==11.1.0 peft torchvision decord==0.6.0 lmdb==1.7.5

可选加速(推荐 Hopper/Blackwell GPU 用户):

为了获得更快的推理速度,可以安装 MagiAttention:

git clone https://github.com/SandAI-org/MagiAttention.git
cd MagiAttention
git checkout v1.0.5
git submodule update --init --recursive
pip install -r requirements.txt
pip install --no-build-isolation .

3. 快速开始:Python 代码示例

以下是一个封装好的 LocateAnythingWorker 类,用于加载模型并执行推理。

import re
import torch
from PIL import Image
from modelscope import AutoModel, AutoTokenizer, AutoProcessor

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", "slow", "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

# --- 任务便捷方法 ---
def detect(self, image: Image.Image, categories: list[str], **kwargs) -> dict:
"""目标检测 / 文档布局分析"""
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:
"""短语定位 - 单个实例"""
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:
"""短语定位 - 多个实例"""
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:
"""文本定位"""
prompt = f"Please locate the text referred as {phrase}."
return self.predict(image, prompt, **kwargs)

def detect_text(self, image: Image.Image, **kwargs) -> dict:
"""场景文本检测"""
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 定位 (框或点)"""
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:
"""指向任务"""
prompt = f"Point to: {phrase}."
return self.predict(image, prompt, **kwargs)

# --- 结果解析工具 ---
@staticmethod
def parse_boxes(answer: str, image_width: int, image_height: int) -> list[dict]:
"""解析模型输出为像素坐标的边界框"""
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]:
"""解析模型输出为像素坐标的点"""
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

4. 任务支持矩阵

下表列出了模型支持的具体任务及其对应的调用方法和提示词模板:

任务类型调用方法提示词模板 (Prompt Template)
目标检测worker.detect(img, ["cat", "dog"])Locate all the instances that matches the following description: [CATEGORIES].
短语定位 (单)worker.ground_single(img, "red car")Locate a single instance that matches the following description: [PHRASE].
短语定位 (多)worker.ground_multi(img, "people")Locate all the instances that match the following description: [PHRASE].
文本定位worker.ground_text(img, "title")Please locate the text referred as [PHRASE].
场景文本检测worker.detect_text(img)Detect all the text in box format.
GUI 定位 (框)worker.ground_gui(img, "btn", "box")Locate the region that matches the following description: [PHRASE].
GUI 定位 (点)worker.ground_gui(img, "btn", "point")Point to: [PHRASE].
指向任务worker.point(img, "traffic light")Point to: [PHRASE].

5. 推理模式说明

模型支持三种生成模式,你可以通过 generation_mode 参数进行切换:

  • fast (最快): 仅使用 MTP(多 token 预测),不回退到自回归。适用于简单场景,速度最快。
  • slow (最稳): 纯自回归解码。速度最慢,但鲁棒性最高。
  • hybrid (默认/推荐): 混合模式。先尝试 MTP,在遇到不确定的边界框时回退到自回归,并在结束后切回 MTP。在速度和准确性之间取得了最佳平衡。

6. 使用示例

# 初始化工作器
worker = LocateAnythingWorker("nv-community/LocateAnything-3B")

# 加载图片
img = Image.open("example.jpg").convert("RGB")

# 1. 目标检测
result = worker.detect(img, ["person", "car", "bicycle"])
print("Detection Result:", result["answer"])

# 2. 短语定位 (多个)
result = worker.ground_multi(img, "people wearing red shirts")
print("Grounding Result:", result["answer"])

# 3. 场景文本检测
result = worker.detect_text(img)
print("Text Detection:", result["answer"])

# 4. 指向任务
result = worker.point(img, "the traffic light")
print("Pointing Result:", result["answer"])

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

# 6. 解析输出为像素坐标
w, h = img.size
boxes = LocateAnythingWorker.parse_boxes(result["answer"], w, h)
points = LocateAnythingWorker.parse_points(result["answer"], w, h)

7. 许可与限制

  • 许可协议: NVIDIA License。
  • 使用范围: 仅限学术和非营利性研究目的
  • 商业限制: 禁止商业用途,除非获得 NVIDIA 及其关联公司的明确授权。
  • 免责声明: 模型按“原样”提供,不提供任何形式的担保。
最后更新时间: --|访问次数: 0|备案图标豫ICP备2025159864号|