Generated banner for Tao Generate Image Grounding
Generated logo for Tao Generate Image Grounding

Tao Generate Image Grounding

NVIDIAOfficialCreated by NVIDIA Corporation

  • Skill
  • Workflow
  • Data and AI
  • Apache-2.0
  • Medium risk

From the author

Two-step image grounding pipeline: extracts referring expressions from (image, caption) pairs and grounds them to pixel-space bounding boxes via a VLM. Use when the user wants to ground captions to bboxes, generate phrase-grounded annotations, auto-label images for grounding, or run the image_grounding pipeline. Triggers include 'image grounding', 'phrase grounding', 'ground captions', 'auto-label image grounding', 'image_grounding'.
— the description by NVIDIA Corporation

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

The tao-generate-image-grounding skill provides a structured workflow for generating phrase-grounded training data. It utilizes a vision-language model (VLM) to perform a two-step process: first, it cleans captions and extracts referring expressions with character spans; second, it predicts pixel-space bounding boxes for those expressions. The pipeline supports various VLM backends, including Gemini and OpenAI-compatible endpoints like NIM or vLLM, and includes built-in checkpointing to allow for efficient, resumable processing of large image datasets.

What it does

  • Extracts referring expressions and character spans from image captions.
  • Generates pixel-space bounding boxes for identified expressions.
  • Supports multiple VLM backends including Gemini and OpenAI-compatible services.
  • Provides per-sample checkpointing for resumable, fault-tolerant processing.
  • Allows for flexible pipeline execution, enabling step-by-step or full-run processing.
  • Outputs structured JSONL annotations suitable for training grounding models.

When to use it

  • When you need to create phrase-grounded training datasets from existing image-caption pairs.
  • When you want to auto-label images with bounding boxes for object detection or grounding tasks.
  • When you need to validate or refine caption-to-image alignment using a VLM.
  • When you have a large dataset and require a resumable, automated annotation workflow.

Advantages

  • Automates labor-intensive manual annotation tasks using powerful VLM teacher models.
  • Highly configurable with support for various self-hosted or cloud-based VLM endpoints.
  • Resilient workflow design with built-in checkpointing to prevent data loss during long runs.
  • Flexible execution allows for inspecting intermediate results before full-scale processing.

Usage examples

“Run the image grounding pipeline on my dataset of images and captions.”
The agent will guide you through setting up the input JSONL, selecting your VLM backend (e.g., Gemini or a local vLLM server), and executing the two-step extraction and grounding process.
“I need to extract referring expressions from my captions but not ground them yet.”
The agent will configure the workflow to run only step 0, producing a JSONL file containing cleaned captions and identified expressions with character spans.
“How do I re-run the grounding step after fixing my configuration?”
The agent will instruct you to set workflow.force_reprocess to true to ignore existing checkpoints and re-run the pipeline from scratch.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/nvidia/tao-generate-image-grounding/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip tao-generate-image-grounding.zip -d .agents/skills

Documentation by NVIDIA Corporation

Image Grounding Pipeline

Standalone install? If this session was not initialized by the TAO skill bank plugin, run the tao-setup skill first (host preflight, credentials, cross-skill discovery).

Turn (image, caption) pairs into per-image grounded annotations: cleaned captions, referring expressions with character spans, and pixel-space bounding boxes for each expression. A single VLM (Gemini or any OpenAI-compatible endpoint) handles both steps.

Purpose

Generate phrase-grounded training data for referring-expression and grounding models. The VLM acts as a "teacher" annotator: Step 0 extracts referring expressions from the caption while looking at the image; Step 1 returns one bbox set per expression for each image.

Pipeline Architecture

Step 0: Expression extraction  → VLM cleans caption, extracts referring expressions + char spans
Step 1: Phrase grounding       → VLM returns pixel bboxes + scores per expression

Steps are individually selectable via workflow.steps. Each step writes a per-sample checkpoint to step_<N>_*/.ckpt/<sample_id>.json and skips already-processed records on re-run. Set workflow.force_reprocess: true to ignore checkpoints and reprocess from scratch.

Instructions

Initial setup

When a user wants to run this pipeline, walk through these steps:

  1. Input JSONL: Ask for the JSONL path. Each line must be one object like {"image_path": "...", "caption": "..."}. image_path can be absolute or relative.

  2. Image root: If any image_path values are relative, set data.image_root to the directory they should resolve from.

  3. API access: Ask the user which VLM endpoint they want to use. Present these five options and act on the choice:

    1. Gemini — set vlm.backend: "gemini"; require GOOGLE_API_KEY (env var or vlm.gemini.api_key).

    2. NIM (e.g. https://inference-api.nvidia.com/v1) — set vlm.backend: "openai"; collect base_url, model_name, and api_key.

    3. TAO inference microservice (self-hosted, OpenAI-compatible). Confirm whether the server is already running:

      • Running — collect base_url, model_name, and (optionally) api_key; set vlm.backend: "openai".

      • Not running — guide the user through the skills/applications/tao-run-inference-service skill, which stands up a local TAO inference microservice with an OpenAI-compatible API. Before promising a specific model, check skills/applications/tao-run-inference-service/references/service.yaml for valid_network_arch_config_basenames. Once the server is up, collect base_url, model_name, and (optionally) api_key; set vlm.backend: "openai".

    4. vLLM (self-hosted, OpenAI-compatible). Confirm whether the server is already running:

      • Running — collect base_url, model_name, and (optionally) api_key; set vlm.backend: "openai".

      • Not running — follow references/vllm_server.md to install and launch a vLLM server, then collect base_url, model_name, and (optionally) api_key; set vlm.backend: "openai".

    5. Custom (any other OpenAI-compatible endpoint) — set vlm.backend: "openai"; collect base_url, model_name, and (optionally) api_key.

    If the user has no endpoint and does not want to set one up, stop and help resolve API access first.

  4. Workflow steps: Choose one of:

    • Full pipeline: ["0", "1"]

    • Expression extraction only: ["0"]

    • Grounding only: ["1"], which requires existing step-0 output at results_dir/step_0_expression_extraction/annotations.jsonl

  5. Resume vs fresh run: By default, the workflow reuses checkpoints and skips completed records. To reprocess everything, set image_grounding.workflow.force_reprocess=true.

Running the pipeline

The pipeline runs inside the TAO Toolkit container via the auto_label CLI:

auto_label generate -e /path/to/spec.yaml \
    results_dir=/results \
    image_grounding.data.input_jsonl=/data/captions.jsonl \
    image_grounding.data.image_root=/data/images \
    image_grounding.vlm.gemini.api_key=$GOOGLE_API_KEY

Generate a default spec: auto_label default_specs results_dir=/results module_name=auto_label, then set autolabel_type: "image_grounding". All fields support Hydra dot-notation overrides on the command line.

See references/configuration.md for the full YAML structure, all parameters, model/endpoint setup, and error patterns.

  1. Run on 5-10 images with both steps

  2. Inspect step_0_expression_extraction/annotations.jsonl — are cleaned_caption and expressions[] accurate? Are the right noun phrases captured?

  3. Inspect step_1_grounding/annotations.jsonl — do the bboxes in expressions[].instances[] look right? Are confidence scores reasonable?

  4. If quality is insufficient, switch the VLM to a stronger model (e.g. gemini-2.5-pro) or raise media_resolution/max_output_tokens, then re-run with force_reprocess=true.

  5. Scale to the full dataset once satisfied.

Configuration

Key configuration fields (full reference in references/configuration.md):

FieldDefaultDescription
workflow.steps["0","1"]Which pipeline steps to execute ("0" = expressions, "1" = grounding)
workflow.max_workers4Parallel threads per step (watch API rate limits)
workflow.force_reprocessfalseIgnore per-sample checkpoints and reprocess from scratch
vlm.backend"gemini""gemini" or "openai" (OpenAI-compatible endpoint)
data.input_jsonlrequiredPath to input JSONL with image_path + caption per line
data.image_root""Optional prefix for resolving relative image_path entries

Inputs

A single JSONL file at data.input_jsonl. One JSON object per line:

FieldRequiredDescription
image_pathyesAbsolute path, or relative path resolved against data.image_root
captionyesFree-text caption for the image
image_idnoStable identifier; auto-derived from the filename if missing
width, heightnoImage dimensions in pixels; default to 1920×1080 for bbox clamping if missing

Outputs

All outputs go to results_dir/:

  • step_0_expression_extraction/annotations.jsonl — per-record output enriched with cleaned_caption and expressions[] (each with text, expression_id, char_span, noun_chunk, empty instances[]).

  • step_1_grounding/annotations.jsonl — same records with expressions[].instances[] filled in (each instance has bbox: [x1,y1,x2,y2] in pixel space, score in [0.0, 1.0], and bbox_id).

  • results_dir/annotations.jsonl — copy of the last step's output for convenience.

  • step_<N>_*/.ckpt/<sample_id>.json — per-sample checkpoints used for resume.

Prerequisites

  • Container: nvcr.io/nvidia/tao/tao-toolkit:7.3.0-pyt <!-- versions-key: images.tao_toolkit.pyt -->

  • API access: At least one VLM endpoint (Gemini API key or OpenAI-compatible endpoint capable of image input)

Files

references/configuration.md

Image Grounding — Full Configuration Reference

Use this reference only when the parent SKILL.md points here for the current task. If this file conflicts with current SKILL.md, skill_info.yaml, schemas, or platform/model skills, the current authoritative source wins.

Contents

  • Complete YAML Structure

  • Key Configuration Decisions

  • Model / Endpoint Configuration

    • Gemini (default)

    • OpenAI-compatible endpoints

  • All Parameters

  • Input JSONL Schema

  • Output Layout

  • Error Patterns

Complete YAML Structure

Generate a default experiment spec with auto_label default_specs results_dir=/results module_name=auto_label, then set autolabel_type: "image_grounding".

results_dir: ???                        # Required — output directory
autolabel_type: "image_grounding"

image_grounding:
  # --- VLM (vision-language model, used for both steps) ---
  vlm:
    backend: "gemini"                   # "gemini" or "openai"
    gemini:
      api_key: ""                       # Or set GOOGLE_API_KEY env var
      model: "gemini-3.1-flash-lite-preview"
      media_resolution: "MEDIA_RESOLUTION_HIGH"   # LOW / MEDIUM / HIGH
      temperature: 0.3
      max_output_tokens: 8192
      timeout: 120
    openai:                             # For OpenAI-compatible endpoints (NIM, vLLM, etc.)
      api_key: ""
      base_url: ""                      # e.g. "https://inference-api.nvidia.com/v1" — no /chat/completions suffix
      model_name: ""                    # e.g. "Qwen/Qwen3-VL-235B-A22B-Instruct"
      temperature: 0.7
      max_tokens: 4096
      timeout: 60

  # --- Workflow ---
  workflow:
    steps: ["0", "1"]                   # "0" = expression extraction, "1" = phrase grounding
    max_workers: 4                      # Parallel threads per step
    force_reprocess: false              # Ignore cached per-sample checkpoints

  # --- Input data ---
  data:
    input_jsonl: ???                    # Path to input JSONL (image_path + caption per line)
    image_root: ""                      # Optional prefix for relative image_path entries

Key Configuration Decisions

DecisionConfig fieldGuidance
Which steps to runworkflow.stepsStart with both (["0","1"]). Drop "1" to inspect extracted expressions before grounding; drop "0" to re-ground using existing step-0 output
VLM providervlm.backend"gemini" for Google Gemini models, "openai" for any OpenAI-compatible endpoint (NIM, vLLM, etc.)
Parallelismworkflow.max_workersHigher = faster but watch API rate limits. Start with 4, drop to 1-2 if you hit 429s
Resume vs restartworkflow.force_reprocessfalse reuses per-sample checkpoints under step_<N>_*/.ckpt/. Set true to redo everything
Image path resolutiondata.image_rootLeave empty if image_path entries are absolute. Otherwise set to the directory the relative paths are anchored to
Bounding box qualityvlm.gemini.media_resolutionUse MEDIA_RESOLUTION_HIGH for accurate pixel-space bboxes. Lower resolutions are cheaper but degrade localization
Output truncationvlm.gemini.max_output_tokens / vlm.openai.max_tokensIf you see "could not parse response" warnings, raise this — Step 1 returns one bbox dict per expression and can be long

Model / Endpoint Configuration

Gemini (default)

Set the API key via environment variable or config:

export GOOGLE_API_KEY=your_key_here

Or in the YAML: image_grounding.vlm.gemini.api_key: "your_key".

Recommended model assignments:

  • For both steps: gemini-2.5-flash (fast, good enough for most images) or gemini-2.5-pro (better localization on small/cluttered objects).

Temperature guidance:

  • Expression extraction (Step 0): 0.2-0.3 for stable, factual phrases.

  • Phrase grounding (Step 1): 0.2-0.3 — bbox prediction should be deterministic.

OpenAI-compatible endpoints

For self-hosted models, the pipeline accepts any endpoint that speaks the OpenAI chat-completions API. Two common ways to provision one:

  1. skills/applications/tao-run-inference-service skill — workflow for standing up a TAO inference microservice locally. Should support Cosmos, Qwen, and Gemma. Check that skill's references/service.yaml valid_network_arch_config_basenames for the current model list.

  2. Bring-your-own deployment — vLLM, NIM, or any other OpenAI-compatible server.

image_grounding:
  vlm:
    backend: "openai"
    openai:
      base_url: "http://your-endpoint:8000/v1"
      model_name: "Qwen/Qwen3-VL-235B-A22B-Instruct"
      api_key: "EMPTY"
      temperature: 0.3
      max_tokens: 8192

All Parameters

ParameterDefaultDescription
workflow.steps["0","1"]Pipeline steps to execute ("0" = expression extraction, "1" = phrase grounding)
workflow.max_workers4Thread pool size for parallel API calls
workflow.force_reprocessfalseIgnore per-sample checkpoints and reprocess from scratch
vlm.backend"gemini"VLM backend: "gemini" or "openai"
vlm.gemini.api_key""Gemini API key (or set GOOGLE_API_KEY env var)
vlm.gemini.model"gemini-3.1-flash-lite-preview"Gemini model name
vlm.gemini.media_resolution"MEDIA_RESOLUTION_HIGH"Image resolution sent to Gemini (LOW/MEDIUM/HIGH)
vlm.gemini.temperature0.3VLM sampling temperature
vlm.gemini.max_output_tokens8192Maximum tokens in Gemini response
vlm.gemini.timeout120Request timeout in seconds
vlm.openai.api_key""API key for OpenAI-compatible endpoint
vlm.openai.base_url""Base URL of the OpenAI-compatible endpoint (no /chat/completions suffix)
vlm.openai.model_name""Model name to send in the OpenAI request
vlm.openai.temperature0.7OpenAI-compatible sampling temperature
vlm.openai.max_tokens4096Maximum tokens in the OpenAI-compatible response
vlm.openai.timeout60Request timeout in seconds
data.input_jsonl(required)Path to input JSONL with image_path + caption fields
data.image_root""Optional prefix used to resolve relative image_path entries

Input JSONL Schema

One JSON object per line. Required and optional fields:

FieldRequiredDescription
image_pathyesAbsolute path or relative path resolved against data.image_root
captionyesFree-text caption used as the basis for expression extraction
image_idnoStable identifier; auto-derived from the filename when missing
width, heightnoImage dimensions in pixels; default to 1920×1080 for bbox clamping when missing

Any additional fields are passed through unchanged to the output records.

Output Layout

results_dir/
├── annotations.jsonl                          # copy of the last step's output
├── step_0_expression_extraction/
│   ├── annotations.jsonl                      # cleaned_caption + expressions[]
│   └── .ckpt/<sample_id>.json                 # per-sample resume checkpoints
└── step_1_grounding/
    ├── annotations.jsonl                      # expressions[].instances[] filled in
    └── .ckpt/<sample_id>.json

Each output record carries:

  • cleaned_caption — the caption after Step 0 normalizes "we can see...", "there is...", etc.

  • expressions[] — one entry per referring expression, with text, expression_id, char_span: [start, end], noun_chunk, and instances[].

  • expressions[].instances[] — populated in Step 1 with bbox: [x1, y1, x2, y2] (pixel-space, clamped to image dims), score in [0.0, 1.0], and bbox_id.

  • pipeline_steps[] — list of step names that have processed this record.

  • source — set to "image_grounding".

Error Patterns

ErrorCauseFix
GOOGLE_API_KEY not setGemini API key missingexport GOOGLE_API_KEY=your_key or set image_grounding.vlm.gemini.api_key in the YAML
429 / rate limit errorsToo many parallel API callsReduce workflow.max_workers (try 1 or 2)
Could not parse response for <id>VLM returned non-JSON or truncated outputRaise vlm.gemini.max_output_tokens / vlm.openai.max_tokens; lower temperature; for very long expression lists, split the input or use a stronger model
Step 0: no input records at <path>data.input_jsonl is empty or unreachableVerify the path; check the JSONL has at least one valid line
Step 1: no step-0 output at <path>Re-ran with only ["1"] but step 0 was never runRun with ["0","1"] first, or supply an existing step_0_expression_extraction/annotations.jsonl
Empty instances[] for every expressionImage not found at image_path, or VLM cannot localizeConfirm data.image_root resolves; test the image path manually; raise media_resolution to MEDIA_RESOLUTION_HIGH
Bboxes look correct but are clipped to 1920×1080width/height missing in input JSONLAdd the true width and height fields to each input record
Re-runs skip everythingPer-sample checkpoints exist under .ckpt/Set image_grounding.workflow.force_reprocess=true to ignore them
Unknown autolabel_typeYAML missing or wrong autolabel_typeSet autolabel_type: "image_grounding" at the top of the spec

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Declares allowed tools, Needs an API key

The author says: Requires docker + nvidia-container-toolkit + at least one VLM endpoint (Gemini API key or OpenAI-compatible).

Security

What our scanner noticed· Medium risk

  • Large base64-encoded blobs
  • Instructions that use the network

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
NVIDIA Corporation
Publisher
NVIDIA (Official)
Source
NVIDIA/skills · skills/tao-generate-image-grounding · commit fce3cca
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE-APACHE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by NVIDIA Corporation or NVIDIA.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download tao-generate-image-grounding.zip