How predictions work
image ──► 1. Decode ──► 2. Detect cat ──► 3. Classify ──► response
│ │
│ └─ only when detection == "detected"
└─ picks the single most confident cat
Detection
A cat detector looks for cats in the image. If there are several, it uses the one it is most confident about. The outcome is reported in detection:
detection |
Detector confidence for the best cat | cat |
prediction |
What to do |
|---|---|---|---|---|
detected |
≥ 0.69 | present | present | Use the prediction. |
low_confidence |
0.5 – < 0.69 | present (best candidate) | null |
Ask the user for a clearer, closer photo. You can use cat.bounding_box to show where the candidate was found. |
not_detected |
no cat at ≥ 0.5 | null |
null |
Tell the user no cat was found. |
All three outcomes are successful requests (HTTP 200). Check detection before reading prediction.
Classification: score, threshold, label
When a cat is detected, the classifier looks at the cropped cat and produces:
score: the probability (0.0–1.0) that the cat shows discomfort.threshold: the cut-off used for this request.label:"discomfort"whenscore > threshold(strictly greater), otherwise"comfort".
Choosing a threshold
- If you omit
threshold, the model's trained default is used. That is currently0.3forbc-v1, but it can change when the model is retrained. Always readprediction.thresholdfrom the response rather than assuming a value. - Lower threshold → more cats flagged as
discomfort(fewer missed cases, more false alarms). Suits triage and screening. - Higher threshold → fewer flags (more certain flags, more missed cases).
- Because
scoreis returned, you can also apply your own threshold on your side without calling the API again.
Bounding box coordinates
cat.bounding_box is in pixels of the image as it was decoded:
- The origin
(0, 0)is the top-left corner.xincreases to the right andyincreases downward. x_min,y_minare the top-left corner of the box.x_max,y_maxare the right and bottom edges.- Values are integers.
image.widthandimage.heightgive the frame they refer to.
To draw the box on a differently sized preview, scale it:
const scaleX = previewWidth / result.image.width;
const scaleY = previewHeight / result.image.height;
const box = result.cat.bounding_box;
drawRect(box.x_min * scaleX, box.y_min * scaleY,
(box.x_max - box.x_min) * scaleX, (box.y_max - box.y_min) * scaleY);
⚠️ Photo orientation (EXIF): the API does not apply EXIF orientation tags. Phone cameras often store images sideways with a "rotate" tag. If you send such a file, coordinates refer to the unrotated pixels. Rotate images upright before sending them (see Image best practices).
Request IDs
Every v2 response includes a request ID in the X-Request-ID response header and in the request_id field of the body. This applies to successes and errors, including 401s.
- You can supply your own ID by sending an
X-Request-IDrequest header. It must be 1–128 characters of letters, digits,.,_,:, or-. - If you don't send one, or yours doesn't match those rules, the API generates one (format
req_<32 hex characters>). An invalid ID never causes a request to fail. - Log the request ID and include it when contacting support.