Skip to content
Tenzro
← All tutorials
Tutorial · Inference and training

Detect objects with RF-DETR

Run NMS-free object detection on Tenzro Network 1 with RF-DETR or D-FINE, from the CLI, the HTTP API or JSON-RPC.

Beginner10 min

RF-DETR is a permissively licensed, NMS-free detection family that covers the 90 COCO classes. The same detection runtime also serves D-FINE for the closed 80-class COCO set. In this tutorial you load a detector on a node you run, call it from the CLI, and then call a network provider through the HTTP API and JSON-RPC. Every call is metered and settled per use.

Prerequisites

  • The tenzro CLI installed. See Getting started.
  • A sample image, for example image.jpg.
  • To call the public endpoint: an API key (header X-Tenzro-Api-Key) or a wallet that can pay per request over HTTP 402. See API keys and x402.
  • To load a model yourself: a node you operate with the ai role. See Model serving.

1. Browse the detection catalog

The catalog lists RF-DETR in six sizes (rf-detr-nano, rf-detr-small, rf-detr-medium, rf-detr-base, rf-detr-large, rf-detr-2xl) and D-FINE in three (d-fine-s, d-fine-m, d-fine-l). Small is a good starting point.

bash
tenzro detect catalog

To see which detectors providers already serve on the network, list the models behind the public endpoint:

bash
curl -s https://rpc.tenzro.xyz/v1/models | jq '.data[].id'

2. Load the detector on your node

Loading a model is an operator action, so run it against a node you control (the CLI talks to http://127.0.0.1:8545 by default). --path is where the ONNX graph already sits on the node. --catalog-id inherits the input resolution, class count and decoder layout from the catalog entry and applies its licence tier. --model is the id callers will use.

bash
tenzro detect load \
  --model det \
  --path /models/rf-detr-small.onnx \
  --catalog-id rf-detr-small

Confirm it is registered:

bash
tenzro detect list

3. Run detection from the CLI

The result is a list of boxes in input-image pixel coordinates (x0, y0, x1, y1), each with a class index and a confidence in [0, 1]. The default score threshold is 0.25.

bash
tenzro detect run \
  --model det \
  --image image.jpg \
  --score-threshold 0.3

Expected output (abridged):

json
{
  "detections": [
    { "bbox": [412.1, 88.6, 640.0, 471.3], "label_id": 1, "score": 0.91 },
    { "bbox": [23.4, 301.0, 198.7, 455.2], "label_id": 3, "score": 0.47 }
  ],
  "generation_time_ms": 38,
  "units": { "...": "..." },
  "cost_wei": "…",
  "settlement": { "status": "settled", "via": "transfer", "...": "..." }
}

When the detector was loaded with a labels file, each detection also carries a label string.

4. Switch to D-FINE for closed-class COCO

D-FINE returns sorted, post-sigmoid boxes that are already in pixel space, so there is less to do on the client.

bash
tenzro detect load \
  --model dfine \
  --path /models/d-fine-s.onnx \
  --catalog-id d-fine-s

tenzro detect run --model dfine --image image.jpg --score-threshold 0.4

5. Call a provider over HTTP

Detection has no OpenAI equivalent, so it lives under the Tenzro namespace at POST /v1/tenzro/detections. Send the image as base64.

bash
IMG=$(base64 < image.jpg | tr -d '\n')

curl -s https://rpc.tenzro.xyz/v1/tenzro/detections \
  -H 'content-type: application/json' \
  -H "X-Tenzro-Api-Key: $TENZRO_API_KEY" \
  -d "{\"model\":\"det\",\"image_base64\":\"$IMG\",\"score_threshold\":0.3}"

The response has object: "detection", the detections array, and the metered units and cost_wei for the call. Without an API key the route answers 402 Payment Required with a challenge you can pay over x402 or MPP.

6. Call it over JSON-RPC

tenzro_detect takes the same fields, keyed model_id, and returns the same shape plus a settlement object that records how the call was paid.

bash
curl -s https://rpc.tenzro.xyz \
  -H 'content-type: application/json' \
  -H "X-Tenzro-Api-Key: $TENZRO_API_KEY" \
  -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tenzro_detect\",\"params\":{\"model_id\":\"det\",\"image_base64\":\"$IMG\",\"score_threshold\":0.3}}"

Detection is billed on the image's size in image tokens plus the number of boxes returned, so a higher threshold returns fewer boxes and costs less.

Next steps