Aerial Segmentation

Chips of aerial photography in, rasters out: for every square metre, what the ground is and how tall the trees are. This is dense prediction over an area, not a question about one picture, and the API is shaped for that.

How This Differs From Masks

Segmentation with SAM 3 answers a question about one picture: name a thing and get its masks. This answers a different shape of problem. There is no prompt. Every pixel gets a class and a height, and the unit of work is an area rather than an image: a property is thousands of chips and a county is millions.

So the request carries many chips at once, the engine coalesces chips across requests into full passes, and the wire format has no per-chip framing in its fast path. Nothing here is shaped like the OpenAI or Anthropic APIs, because nothing in them is shaped like this.

Sixteen chips go through at a time. One chip on its own therefore takes about as long as sixteen. If you have one image, this is the wrong tool; if you have a county, it is the right one.

What To Send

Ask the server rather than guessing, because the chip geometry is the model's and a wrong one is refused:

curl -s localhost:11540/api/server | jq '{segmenter, segmentation}'
# {
#   "segmenter": "tic-forestry-v1",
#   "segmentation": {
#     "input":  {"size": 512, "bands": ["red","green","blue","nir"],
#                 "dtype": "uint8", "pixel_size_m": 0.5, "chip_bytes": 1048576},
#     "output": {"size": 256, "pixel_size_m": 1.0,
#                 "class_names": [...], "regression": "canopy_height_m"},
#     "epsg": 3006,
#     "chips_per_pass": 16
#   }
# }

Note the input is four bands, not three. The near-infrared band is what separates vegetation from everything that merely looks green, and the model reads it.

Two Ways In

Told apart by Content-Type, and the choice is about volume.

Multipart, for real chips

curl -X POST localhost:11540/v1/segmentations \
  -F 'image=@chip-0001.tif' \
  -F 'image=@chip-0002.tif' \
  -F 'response_format=json'

Each image part is either a georeferenced 4-band GeoTIFF, or a raw block of exactly size x size x bands bytes as unsigned 8-bit HWC in the model's band order. A TIFF is recognised by its magic bytes rather than its file name.

Octet-stream, for bulk

cat chips.raw | curl -X POST --data-binary @- \
  'localhost:11540/v1/segmentations?response_format=binary&logits=false' \
  -H 'Content-Type: application/octet-stream'

The body is N raw blocks back to back, options in the query string. No boundaries to scan and no copies, which is the point when you are feeding it millions.

Two Ways Out

response_formatWhat you get
json (default)The embeddings-shaped list: rasters as base64 of little-endian bytes, the class names, and for chips that arrived as GeoTIFFs, where each output raster sits on the ground.
binaryapplication/octet-stream: per chip the class raster (u8), then the height raster (f32 little-endian), then the logits if asked for (f16 little-endian, pixel-major). Geometry rides x-paddock-* headers.

Binary is what a pipeline that already knows where its chips are wants; JSON is what you want while working out whether this does what you need.

Georeferencing Is Carried, Never Invented

A GeoTIFF's tiepoint and pixel scale come back scaled to the output raster, which is half the input's resolution. A raw block has no position, so it is given none rather than a guessed one.

Nothing is reprojected or resampled here. A chip at the wrong ground sample distance is refused by name, and that refusal is deliberate: the model would accept it without complaint and then be quietly wrong about every hectare, which is worse than an error.

The Model

TIC Forestry v1 is 306M parameters, trained on 2,743 ten-kilometre cells across 17 Swedish counties and scored on four counties it never saw. One pass gives both land cover and canopy height, each at 1 m from 0.5 m imagery.

It is built for Swedish imagery at 0.5 m in SWEREF 99 TM, and it is not a general-purpose aerial model. Its weak classes are deciduous forest and open land, at 0.55 and 0.58 IoU against 0.81 to 0.93 elsewhere, which is worth knowing before trusting a deciduous boundary.

Gated weights. Accept the DINOv3 licence on the model's Hugging Face page, then add your own token under Manager > Settings. Gated models are marked with a lock in the picker, so you find out before you start a download rather than during it. NVIDIA GPUs only.