Sign in Get started

Auto-annotate

SAM3 single-prompt (point, box, text) and async batch endpoints for AI-generated annotations.

View as Markdown

Pictograph runs SAM3 (Segment Anything Model 3) on T4 GPUs for auto-annotation. Three single-image prompt modes plus an async batch endpoint for many images at once.

Every example below shows the Python SDK call and the equivalent raw REST request. The REST examples authenticate with an X-API-Key header; set PICTOGRAPH_API_KEY in your shell to copy-and-run them.

from pictograph import Client
client = Client()  # reads PICTOGRAPH_API_KEY

point — “click here, segment that”

Best when the user knows the object’s location. Returns one polygon annotation per prompt.

ArgTypeDefaultNotes
dataset_namestrrequiredProject name within your org
image_filenamestrrequiredImage filename (not the UUID)
x, yintrequiredAnchor point in absolute pixels
namestr"object"Class name for the annotation
positive_pointslist[(x,y)]NoneExtra positive anchors
negative_pointslist[(x,y)]NoneExcluded regions
score_thresholdfloat0.75Minimum SAM3 score (0–1)
result = client.auto_annotate.point(
    dataset_name="my-dataset",
    image_filename="img-1.jpg",
    x=320, y=240,
    name="car",
    positive_points=[(310, 250)],   # optional extra positives
    negative_points=[(100, 100)],   # exclude regions
    score_threshold=0.75,
)
# result.annotations[0] is a polygon — call client.annotations.save() to persist.
curl -s -X POST "https://api.pictograph.io/api/v1/developer/auto-annotate/sam3/point" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"dataset_name": "my-dataset", "image_filename": "img-1.jpg", "x": 320, "y": 240, "name": "car", "positive_points": [[310, 250]], "negative_points": [[100, 100]], "score_threshold": 0.75}'

Returns PromptResult with status{"success", "no_detection", "below_threshold"}. On success, annotations[0] is a PolygonAnnotation.

box — “segment everything in this box”

Best when the user has drawn a rough bounding box. return_polygon=False returns only the refined bbox.

ArgTypeDefaultNotes
dataset_namestrrequiredProject name
image_filenamestrrequiredImage filename
box{x,y,w,h}requiredBounding box in absolute pixels
namestrrequiredClass name
confidence_thresholdfloat0.5Minimum SAM3 confidence (0–1)
return_polygonboolTrueAlso include a polygon, not just the bbox
negative_boxeslist[{x,y,w,h}]NoneExclusion zones
result = client.auto_annotate.box(
    dataset_name="my-dataset",
    image_filename="img-1.jpg",
    box={"x": 100, "y": 200, "w": 200, "h": 150},
    name="car",
    return_polygon=True,           # also include polygon (not just bbox)
    confidence_threshold=0.5,
    negative_boxes=[{"x": 50, "y": 50, "w": 30, "h": 30}],
)
curl -s -X POST "https://api.pictograph.io/api/v1/developer/auto-annotate/sam3/box" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"dataset_name": "my-dataset", "image_filename": "img-1.jpg", "box": {"x": 100, "y": 200, "w": 200, "h": 150}, "name": "car", "return_polygon": true, "confidence_threshold": 0.5, "negative_boxes": [{"x": 50, "y": 50, "w": 30, "h": 30}]}'

text — “find all

Open-vocabulary text prompt. Best for many objects in one image.

ArgTypeDefaultNotes
dataset_namestrrequiredProject name
image_filenamestrrequiredImage filename
text_promptstrrequiredNatural language description
output_typestr"polygon""polygon" or "bbox"
confidence_thresholdfloat0.3Minimum confidence (0–1)
max_detectionsint50Cap on result count (1–100)
result = client.auto_annotate.text(
    dataset_name="my-dataset",
    image_filename="img-1.jpg",
    text_prompt="red cars",
    output_type="polygon",         # or "bbox"
    confidence_threshold=0.3,
    max_detections=50,
)
curl -s -X POST "https://api.pictograph.io/api/v1/developer/auto-annotate/sam3/text" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"dataset_name": "my-dataset", "image_filename": "img-1.jpg", "text_prompt": "red cars", "output_type": "polygon", "confidence_threshold": 0.3, "max_detections": 50}'

batch — async, many images

Use for >10 images. Kicks off one job; polls until terminal status. SAM3 jobs (model_id omitted) need at least one class; trained-model jobs (model_id=<uuid>) accept empty classes for classification models. On the REST wire, SAHI is opted in with sahi_enabled / sahi_slice_size.

ArgTypeDefaultNotes
dataset_namestrrequiredProject name
image_filenameslist[str]requiredFilenames to process
classeslist[BatchClass]required for SAM3{name, output_type} per class
confidence_thresholdfloat0.5Minimum confidence
model_idstr | NoneNoneTrained-model UUID; None routes to SAM3
top_kint1Classifier-only — tags per image
waitboolTruePoll until terminal
from pictograph import BatchClass

job = client.auto_annotate.batch(
    dataset_name="my-dataset",
    image_filenames=["img-1.jpg", "img-2.jpg", "..."],
    classes=[
        BatchClass(name="car", output_type="polygon"),
        BatchClass(name="person", output_type="bbox"),
    ],
    confidence_threshold=0.5,
    wait=True,
    poll_interval=5.0,
    timeout=1800.0,                # 30 min default
)
print(job.status, job.processed_images, job.total_annotations_added)
curl -s -X POST "https://api.pictograph.io/api/v1/developer/auto-annotate/batch" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"dataset_name": "my-dataset", "image_filenames": ["img-1.jpg", "img-2.jpg"], "classes": [{"name": "car", "output_type": "polygon"}, {"name": "person", "output_type": "bbox"}], "confidence_threshold": 0.5}'

wait=False returns the job immediately — poll later, or cancel:

job = client.auto_annotate.get_batch(job.job_id)
job = client.auto_annotate.wait_for_batch(job.job_id, timeout=600.0)
client.auto_annotate.cancel_batch(job.job_id)
# Poll batch progress.
curl -s "https://api.pictograph.io/api/v1/developer/auto-annotate/batch/{job_id}" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY"

# Cancel a pending or running batch.
curl -s -X POST "https://api.pictograph.io/api/v1/developer/auto-annotate/batch/{job_id}/cancel" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY"

SAHI sliced inference (small objects)

For high-resolution images with small objects (drone shots, wide industrial scenes, litter detection), enable SAHI. Each image is sliced into overlapping tiles, every tile runs at near-native resolution alongside one full-image pass, and tile fragments are merged back into whole instances server-side:

job = client.auto_annotate.batch(
    dataset_name="my-dataset",
    image_filenames=["site-4k.jpg"],
    classes=[BatchClass(name="person", output_type="polygon")],
    sahi=True,
    sahi_slice_size=640,           # tile edge in px, 256-1024
)
curl -s -X POST "https://api.pictograph.io/api/v1/developer/auto-annotate/batch" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"dataset_name": "my-dataset", "image_filenames": ["site-4k.jpg"], "classes": [{"name": "person", "output_type": "polygon"}], "sahi_enabled": true, "sahi_slice_size": 640}'

SAHI is SAM3-only (a trained-model job with SAHI enabled is rejected with a 400). Smaller slices find smaller objects but run more passes; cost scales with each image’s tile count, which the API computes exactly from stored image dimensions. CLI equivalent: pictograph auto-annotate batch ... --sahi --sahi-slice-size 640.

auto_annotate_dataset workflow

Higher-level helper that paginates a dataset’s image list, runs batch or text mode, and returns a per-image report:

from pictograph.pipelines import auto_annotate_dataset

report = auto_annotate_dataset(
    client,
    "my-dataset",
    classes=[("car", "polygon"), ("person", "bbox")],
    mode="batch",                  # "batch" | "text"
    confidence_threshold=0.5,
    overwrite=False,               # skip already-annotated images
    max_images=None,               # None = all
)
print(report.images_processed, report.annotations_added, len(report.failures))

Choosing a mode

ScenarioMode
User clicks one spotpoint
User drags a rough boxbox
Many images, known classesbatch (or text per image for small datasets)
Single image, multiple objectstext

Cost

SAM3 auto-annotation draws on your USD compute credit (available on every tier). Point and box prompts share one image embedding per session, so follow-up prompts on the same image are near-free; batch is priced per image processed. Prices are USD-denominated — call

client.credits.estimate("sam3_auto_annotation", quantity=N)

for the live cost, and read PaymentRequiredError.required on rejection for the exact ask. Amounts are integer micro-USD (1 USD = 1,000,000 µUSD).

Common errors

StatusExceptionCause
402PaymentRequiredErrorOut of credits
404NotFoundErrorDataset or image missing
408PollTimeoutErrorBatch job didn’t finish within timeout (job keeps running on the backend)

See also

Copied to clipboard