Skip to main content

Region profiles

A region profile defines what counts as a region of interest inside an item: which detector and segmenter find candidates, how many boxes an item may carry, which items get the region stage, and whether text is read from the region. A car crop with wheels, a plate on a vehicle, a defect on a part: each is one profile. The configuration is data, not code. It is editable per project, versioned and revertible.

API=http://localhost:4603 and project cars are assumed.

Concepts​

  • Item and region. An item is a crop from the primary detector. The region stage looks for sub-regions inside an item. With no active profile, region detection is off.
  • Legs. Candidates come from a detector leg (a Triton model named by detector_model) and a segmenter leg (a text prompt for the segmenter, segmenter_text_prompt). A profile needs at least one. With the segmenter as the only leg, the prompt is mandatory.
  • Scope. parent_classes lists the item class names that get the region stage. Empty means every item.
  • Count. max_regions_per_item (1 to 64) is the most boxes kept per item after selection. The default 1 is single-box. See Multi-box regions.
  • Text. text_reader is none (a text-free region), vlm, ocr, vlm_then_ocr (OCR when the VLM read nothing) or both (store both readings and flag a disagreement). The text_* fields tune normalization and validity rules.
  • Display. display_name and display_name_singular are the labels a frontend shows ("Wheels", "Wheel"). region_class_name is the registry class name the profile's detections are treated as.
  • Sources and revisions. Same model as prompt packs: builtin, file (from OP_REGION_PROFILE_PATH), template (shipped under examples/region_profiles/) and stored. Only stored profiles are editable. Each save is a numbered revision.
  • Activation. One profile is active per project, and it can be switched off. Activation passes a gate that pairs it with the active prompt pack and VLM. Activation never rewrites existing items. The impact route counts what is stale and suggests an explicit reprocess.

Routes​

CallPurpose
GET /curation/projects/{project}/region_profilesList profiles; include_templates=true adds shipped templates
POST /curation/projects/{project}/region_profilesCreate a stored profile
GET /curation/projects/{project}/region_profiles/schemaField list with ranges and choice sources
POST /curation/projects/{project}/region_profiles/validateValidate a draft; never writes
POST /curation/projects/{project}/region_profiles/validate_segmenter_promptCheck one segmenter prompt
POST /curation/projects/{project}/region_profiles/testDry run on a crop, see Test on a crop
GET /curation/projects/{project}/region_profiles/activeThe active profile and what workers applied
GET /curation/projects/{project}/region_profiles/active/impactWhat activation means for existing items
POST /curation/projects/{project}/region_profiles/active/rollbackRe-activate the previous profile
POST /curation/projects/{project}/region_profiles/deactivateSwitch region detection off
GET /curation/projects/{project}/region_profiles/{name}One profile
PUT /curation/projects/{project}/region_profiles/{name}Save a new revision
DELETE /curation/projects/{project}/region_profiles/{name}Delete a stored profile
POST /curation/projects/{project}/region_profiles/{name}/activateActivate
POST /curation/projects/{project}/region_profiles/{name}/cloneCopy into a new stored profile
GET /curation/projects/{project}/region_profiles/{name}/revisionsRevision history
GET /curation/projects/{project}/region_profiles/{name}/revisions/{revision}One past revision

List and inspect​

curl -s "$API/curation/projects/cars/region_profiles?include_templates=true"
curl -s "$API/curation/projects/cars/region_profiles/vehicle_wheel"

The list has profiles (name, detector_model, segmenter_text_prompt, parent_classes, max_regions_per_item, text_reader, reads_text, region_class_name, display_name, read_only, revision, active), templates, active and config_revision. A profile document adds body (every field), description, etag, cloned_from and effective. effective states which legs run, whether the segmenter is enabled, whether text is read, and whether the OCR text-hint re-pass is active.

Profile fields​

Defaults are in parentheses. The full list with ranges is returned by the schema route. Field names with no default listed here are tuning values whose defaults are in src/config/detection_profile.py.

GroupFields
Identity and scopedisplay_name, display_name_singular, region_class_name, parent_classes
Detector legdetector_model (empty = none), detector_version, input_size (640), confidence_floor (0.4), batch_limit (16), letterbox_fill
Segmenter legsegmenter_name (sam3), segmenter_version, segmenter_text_prompt (empty = off)
Segmenter gatinggate_hit_rate (false), gate_hit_window (20), gate_hit_miss_threshold (15), gate_hit_sample_floor (0.1): skip the segmenter for an item class that keeps missing, still sampling it; skipped items are stamped region_gate_skip and re-run through the reprocess filter region_gate_skipped. Never applies to an item whose class a human owns or validated
Selectionmax_regions_per_item (1), region_nms_iou (0.5), auto_confirm_aspect, auto_confirm_area_frac
Text readingtext_reader (vlm_then_ocr), text_pattern, text_format, text_charset, text_uppercase, text_join, text_len_min, text_len_max, text_stopwords, text_min_confidence, text_placeholders, text_reject_sequences, text_crop_margin, text_crop_min_height, text_min_height_ratio, text_border_margin
OCR modelsocr_pipeline_model, ocr_rec_model, ocr_rec_version
OCR text hinttext_hint_enabled (true), text_hint_aspect_min, text_hint_aspect_max, text_hint_len_min, text_hint_len_max, text_hint_rec_floor, text_hint_require_letters_and_digits
Otherhuman_detector_name, human_detector_version, feature_output, secondary_shape_groups, assigns_class, labels_path

The segmenter prompt is plain text. At most 200 characters, at most 8 phrases separated by commas, one line.

Validate​

curl -s -X POST "$API/curation/projects/cars/region_profiles/validate?for_activation=true" \
-H 'Content-Type: application/json' \
-d '{
"name": "vehicle_wheel_v2",
"body": {
"segmenter_text_prompt": "wheel",
"parent_classes": ["car"],
"max_regions_per_item": 4,
"text_reader": "none",
"text_hint_enabled": false,
"ocr_pipeline_model": "",
"region_class_name": "wheel",
"display_name": "Wheels",
"display_name_singular": "Wheel"
}
}'

The body may be partial; missing fields take their defaults. With for_activation=true the unreachable and not-ready dependency checks are errors instead of warnings, which is what an activation would see. The response is {ok, errors, warnings, force_allowed}.

CodeSeverityMeaning
profile_name_invalid, profile_name_reservederrorName must match ^[a-z0-9][a-z0-9_.-]{1,63}$; off, none and default are reserved
name_conflicterrorName already used
profile_field_unknown, profile_field_type, profile_field_rangeerrorUnknown field, wrong type, or value out of range. input_size must be a multiple of 32
region_class_name_invaliderrorNot a valid class name
text_reader_invalid, text_regex_invaliderrorUnknown reader mode, or a bad regular expression
no_candidate_sourceerrorNeither a detector model nor a segmenter prompt
segmenter_prompt_emptyerror when the segmenter is the only leg, else warningEmpty prompt
segmenter_prompt_too_long, segmenter_prompt_too_many_phrases, segmenter_prompt_multilineerrorPrompt over the limits above
detector_model_not_founderrorModel is not in the Triton repository
detector_model_not_readywarning, error for activation; bypassableModel is not READY
detector_model_unusablewarning on save, error for activationThe loaded model has no output0 tensor (for example a YOLO end-to-end model), or its configuration cannot be read from Triton; every item would end no_region_box
detector_model_not_shared, detector_model_other_projecterror, warningThe model belongs to another project and is not shared, or is shared
detector_model_classes_unmappedwarningA shared model has classes with no match by name in this project
triton_unreachable, segmenter_unreachable, ocr_model_not_readywarning, error for activation; bypassableDependency down
segmenter_not_configuredwarningOP_SEGMENTER_URL is not set
ocr_model_not_founderrorOCR model not in Triton
vlm_not_configuredwarningA text mode needs a VLM and none is configured; it falls back to OCR
text_fields_ignoredwarningtext_reader is none and text fields were changed
text_hint_inactive_no_ocrwarningText hint on with no OCR pipeline
display_name_missingwarningThe UI will say "Regions" and "Region"
parent_class_unknownwarningThe class is not in the registry (a proposal name is allowed)
pack_multi_region_keys_missingerror on activationThe active prompt pack lacks the per-box reply keys

Check a segmenter prompt alone:

curl -s -X POST "$API/curation/projects/cars/region_profiles/validate_segmenter_prompt" \
-H 'Content-Type: application/json' \
-d '{"text_prompt": "wheel", "sole_leg": true}'

Create, edit, clone​

curl -s -X POST "$API/curation/projects/cars/region_profiles/vehicle_wheel/clone" \
-H 'Content-Type: application/json' \
-d '{"new_name": "cars_wheels", "description": "Wheels on car crops"}'

curl -s -X POST "$API/curation/projects/cars/region_profiles" \
-H 'Content-Type: application/json' \
-d '{"name": "cars_wheels", "description": "", "body": { ...fields... }}'

curl -s -X PUT "$API/curation/projects/cars/region_profiles/cars_wheels" \
-H 'Content-Type: application/json' \
-d '{"expected_revision": 1, "description": "allow 6 wheels", "body": { ...fields... }}'

Clone takes optional revision and from_project. Create and save answer with the profile document and validation. They refuse a profile with validation errors with 422. Warnings do not block.

Activate, impact, roll back, deactivate​

curl -s -X POST "$API/curation/projects/cars/region_profiles/cars_wheels/activate" \
-H 'Content-Type: application/json' \
-d '{"revision": null, "force": false, "expected_active": null}'

curl -s "$API/curation/projects/cars/region_profiles/active/impact"

curl -s -X POST "$API/curation/projects/cars/region_profiles/active/rollback" \
-H 'Content-Type: application/json' -d '{"expected_active": null}'

curl -s -X POST "$API/curation/projects/cars/region_profiles/deactivate" \
-H 'Content-Type: application/json' -d '{"expected_active": null}'

force bypasses only the bypassable codes in the table (a dependency that is down or not ready). It never bypasses a structural error. The activate response has the same fields as for prompt packs (active, previous, applied) plus impact and validation.

impact has:

FieldMeaning
items_totalItems in the project
by_profileItem counts per profile name and revision that produced their regions
validated_itemsItems with human-validated regions
unseeded_itemsItems with no region profile stamp
pending_items, pending_not_matchingItems waiting for detection, and those outside the new profile's scope
stale_itemsMachine-written items the active profile revision did not produce
suggested_reprocessA dry-run reprocess request that selects the stale items, or null

Nothing is rewritten by activation. To apply the new profile to old items, post suggested_reprocess to the reprocess route; see Reprocess. Workers switch to a newly activated profile at a quiet point.

Revisions​

curl -s "$API/curation/projects/cars/region_profiles/cars_wheels/revisions"
curl -s "$API/curation/projects/cars/region_profiles/cars_wheels/revisions/1"
curl -s -X DELETE "$API/curation/projects/cars/region_profiles/cars_wheels?expected_revision=2"

Delete answers 204 and is refused while the profile is active.

Errors​

StatuserrorWhen
404not_foundUnknown or not-stored profile
404unknown_revisionNo such revision
403read_onlySave or delete of a built-in, file or template profile
409name_conflictCreate or clone onto a used name
409revision_conflictexpected_revision is stale
409in_useDelete of the active profile
409active_conflictAnother writer changed the activation; current is returned
409no_previous, previous_deletedNothing to roll back to
422validation_failedValidation errors; report lists them

An assist run with the segment action (POST .../assist/runs) re-runs the segmenter on chosen items and waits in status waiting_region while the region worker handles them. It answers 409 region_profile_required with no active profile, 409 no_segmenter_leg when the active profile has no segmenter_text_prompt, 409 region_stage_paused while the region stage is paused, and 409 verify_endpoint_mismatch when segment.verify is vlm but the run names another endpoint than the project's.

Cropwright​

The region profile editor: grouped fields, the segmenter, and the revision list (captured from Cropwright against the public COCO sample projects)

See also​