Skip to content

feat(yolo26-sem): binary (nc==1) post-process + register fine-tuned variants in core registry#2407

Draft
leeclemnet wants to merge 11 commits into
mainfrom
feat/yolo26-sem-binary-inference
Draft

feat(yolo26-sem): binary (nc==1) post-process + register fine-tuned variants in core registry#2407
leeclemnet wants to merge 11 commits into
mainfrom
feat/yolo26-sem-binary-inference

Conversation

@leeclemnet
Copy link
Copy Markdown
Contributor

@leeclemnet leeclemnet commented Jun 3, 2026

What does this PR do?

Makes YOLO26 semantic-segmentation models (served via inference_models) work end-to-end on the inference server, and tightens the semantic-seg class-name contract. Four changes:

  1. Core registry (inference/models/utils.py): ROBOFLOW_MODEL_TYPES registered only the family key ("semantic-segmentation", "yolo26") — which pretrained/public models match (modelArchitecture = "yolo26"), but fine-tuned versioned models report their ORT modelType ("yolo26n-sem", …) with no variant→family normalization, raising ModelNotRecognisedError. Now registers the family alias plus every trained variant, mirroring the YOLOLite registration.
  2. Binary (nc==1) post-process: a single-foreground-class model trains as Ultralytics' native binary head → one output channel. softmax over one channel is degenerate (≡1.0), so the single-channel case uses the sigmoid foreground probability; sub-threshold pixels collapse to background via the existing threshold step. Shared by ONNX/TorchScript/TRT; multi-channel (DeepLab + multiclass) is untouched (only triggers on shape[0] == 1).
  3. Load-time validation: a shared validate_class_names requires a semantic-seg package to declare background + ≥1 foreground class (>= 2 names), raising CorruptedModelPackageError instead of failing silently. resolve_background_class_id is now a pure lookup that assumes a validated package.
  4. Refactor: moved the semantic-seg class-name helpers out of the generic model_packages.py into common/roboflow/semantic_segmentation.py (shared by the DeepLabV3+ and YOLO26-sem backends).

Related Issue(s): Builds on #2372 (YOLO26-sem ONNX/TorchScript/TRT backends). Pairs with roboflow-train #807.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Refactoring (no functional changes)

Testing

  • I have tested this change locally
  • I have added/updated tests for this change

Test details:
pytest over the semantic post-process, model_packages, and the new semantic_segmentation tests → 53 passed. Binary tests verified meaningful by direct invocation (without the branch a sub-threshold pixel wrongly becomes foreground [1]; with it, background [0]). New tests: test_validate_class_names_* (valid binary/multiclass, missing background, missing foreground). Registry resolution of ("semantic-segmentation", "yolo26n-sem") is covered by CI's full-deps import. E2E on staging (fine-tuned single-class model, paired with roboflow-train #807) pending.

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code where necessary, particularly in hard-to-understand areas
  • My changes generate no new warnings or errors
  • I have updated the documentation accordingly (if applicable) — n/a

Additional Context

Multi-channel/DeepLab behavior is unaffected throughout (binary branch only triggers on a single output channel). post_process_semantic_segmentation_logits intentionally stays in post_processing.py (it's a post-processor); only the class-name validation/resolution helpers moved.

@leeclemnet leeclemnet force-pushed the feat/yolo26-sem-binary-inference branch 3 times, most recently from c23f550 to ee29494 Compare June 3, 2026 17:42
@leeclemnet leeclemnet changed the title feat(yolo26-sem): handle binary (nc==1) head in semantic post-process feat(yolo26-sem): binary (nc==1) post-process + register fine-tuned variants in core registry Jun 4, 2026
@leeclemnet leeclemnet force-pushed the feat/yolo26-sem-binary-inference branch from e47eebd to c989129 Compare June 4, 2026 14:27
leeclemnet and others added 7 commits June 4, 2026 12:55
…post-process

A single foreground class trains as Ultralytics' nc==1 binary head, which emits
one channel. softmax over a single channel is degenerate (1.0), so detect the
1-channel case and use the sigmoid foreground probability: every pixel is
provisionally the lone foreground class (read from class_names [background,<fg>])
and sub-threshold pixels collapse to background via the existing threshold step.
Shared by the ONNX, TorchScript and TRT backends.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…registry

The core ROBOFLOW_MODEL_TYPES only registered the family key
('semantic-segmentation', 'yolo26') — which pretrained/public models match (they
report modelArchitecture 'yolo26'). Fine-tuned versioned models report their ORT
modelType ('yolo26n-sem', ...), and get_model_type does no variant->family
normalization, so they hit ModelNotRecognisedError. Register the family alias
plus every trained variant, mirroring the YOLOLite registration.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t load

resolve_background_class_id now validates that a semantic-seg package declares
background plus at least one foreground class (class_names >= 2), raising
CorruptedModelPackageError otherwise — instead of failing silently downstream.
This is the shared load-time gate for all three backends (ONNX/TorchScript/TRT),
so the binary post-process can drop its background_class_id fallback and assume
a foreground id exists.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…d_class_id stays pure

Move the semantic-seg class-name contract (background + >=1 foreground) out of
resolve_background_class_id into a dedicated validate_class_names utility, called
at model load in the ONNX/TorchScript/TRT backends. resolve_background_class_id
is now a pure index lookup that assumes a validated package.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ed module

validate_class_names and resolve_background_class_id are semantic-segmentation
specific and don't belong in the generic model_packages parsing module. Move
them to common/roboflow/semantic_segmentation.py (shared by the DeepLabV3+ and
YOLO26-sem backends) and repoint all six backend imports. Tests move to
test_semantic_segmentation.py.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…anket +1

The K-foreground-channel layout shifted argmax ids by +1, which only maps
correctly when background is at index 0. background_class_id is data-driven
(resolve_background_class_id), so map channel j to the j-th non-background class
id instead. Identical to +1 when background is at 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@leeclemnet leeclemnet force-pushed the feat/yolo26-sem-binary-inference branch from a16e4f3 to 9cb1d95 Compare June 4, 2026 15:25
leeclemnet and others added 4 commits June 4, 2026 12:58
Same semantic-seg class-name contract (background + >=1 foreground) applies to
DeepLabV3+ packages; call validate_class_names at load in all three backends.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per project code style: self-documenting code over narration. Trim the
explanatory inline comments and verbose docstrings added for the semantic-seg
class-name helpers and post-process to terse WHY-only notes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ass-id mapping

Both post-process branches (binary single-channel and multiclass K-foreground)
mapped foreground channel indices back into the full class-id space inline.
Extract insert_background_class (skips the background slot, data-driven id) and
use it for both, unifying the mapping. resolve_background_class_id stays — the
background id is also used by the sub-threshold collapse and letterbox pad.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant