Skip to content

Add YOLO26 semantic segmentation export support#217

Merged
klemen1999 merged 5 commits into
mainfrom
feat/86c9x87hh-yolov26-semseg
Jun 23, 2026
Merged

Add YOLO26 semantic segmentation export support#217
klemen1999 merged 5 commits into
mainfrom
feat/86c9x87hh-yolov26-semseg

Conversation

@rolandocortez

@rolandocortez rolandocortez commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Purpose

Add support for exporting YOLO26 semantic segmentation models from tools.

This enables yolo26n-sem.pt to be exported as an ONNX NNArchive with a semantic segmentation head configuration, so the resulting archive can be converted through HubAI and used directly with ParsingNeuralNetwork / SegmentationParser.

Specification

This PR adds:

  • yolov26-sem version detection.
  • Routing for yolov26-sem in the main conversion flow.
  • Semantic segmentation mode in Yolo26Exporter.
  • Added a reusable make_segmentation_nn_archive() helper in Exporter to generate NNArchives with SegmentationParser + HeadSegmentationMetadata.
  • E2E and semantic-specific test coverage for the generated NNArchive head.

The YOLO26 semantic segmentation checkpoint is detected through the SemanticSegment head in the model checkpoint.

The generated archive keeps the existing YOLO26 output naming convention and uses output_yolo26 as the semantic segmentation output.

The generated ONNX output is:

output_yolo26 [1, 19, 416, 416]

The generated NNArchive head config is:

parser: SegmentationParser
outputs: ["output_yolo26"]
metadata:
  n_classes: 19
  is_softmax: false

No changes were needed in depthai-nodes, since the existing SegmentationParser already supports a single semantic segmentation logits output and produces a SegmentationMask.

I also verified that the existing YOLO26 detect / instance segmentation / pose output-name behavior stays unchanged.

Dependencies & Potential Impact

No new dependencies.

Impact should be limited to YOLO26 semantic segmentation export. Existing YOLO26 export paths are not intended to change.

Deployment Plan

No special deployment required.

Rollback is reverting this PR.

Testing & Validation

Tests:

pytest tests/test_end2end.py::test_yolo26_semseg_nnarchive_head --download-weights -s
# 1 passed

pytest tests/test_end2end.py --download-weights --test-case yolo26n-sem -s
# 2 passed, 102 skipped

Manual export validation:

  • Exported yolo26n-sem.pt through tools.
  • Verified the ONNX output name and shape: output_yolo26 [1, 19, 416, 416].
  • Verified the generated NNArchive uses SegmentationParser.
  • Verified the head outputs are ["output_yolo26"].
  • Verified the metadata has 19 classes and is_softmax=false.

Hub conversion validation:

  • RVC4 FP16: PASS
  • RVC4 INT8: PASS
  • RVC2: PASS

The converted archive configs were inspected and confirmed to preserve:

parser: SegmentationParser
outputs: ["output_yolo26"]
metadata:
  n_classes: 19
  is_softmax: false

Runtime validation:

  • RVC4 FP16: PASS
  • RVC4 INT8: PASS
  • RVC2: PASS

The converted archives were tested with a DepthAI pipeline using:

ReplayVideo -> ParsingNeuralNetwork -> ApplyColormap -> ImgFrameOverlay

The parser output was:

depthai_nodes.message.segmentation.SegmentationMask

and the visualizer rendered semantic segmentation masks / overlays correctly.

I also validated the RVC2 archive locally with oak-examples/neural-networks/generic-example on OAK-1 using -overlay.

AI Usage

Assisted-by: ChatGPT

Submitted code was reviewed by a human: YES

The author is taking responsibility for the contribution: YES

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for YOLOv26 semantic-segmentation variants, including automatic detection.
    • Extended the CLI/export flow to generate semantic-segmentation NN archives with the correct head and metadata.
  • Tests

    • Added an end-to-end test covering NN archive export and semantic-segmentation head configuration for the YOLOv26 semantic-segmentation variant.

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds end-to-end support for exporting YOLO26 semantic segmentation models. A new YOLOV26_SEM_CONVERSION constant and detection logic identify the variant, Yolo26Exporter gains a SEMSEG_MODE with corresponding load/export branches, and a make_semantic_seg_nn_archive method is added to the base exporter. CLI and tests are updated accordingly.

Changes

YOLOv26 Semantic Segmentation Export Pipeline

Layer / File(s) Summary
YOLOV26_SEM_CONVERSION constant and detect_version() update
tools/version_detection/version_detection.py, tools/version_detection/__init__.py
Defines YOLOV26_SEM_CONVERSION = "yolov26-sem", inserts a higher-priority branch in detect_version() that matches both "yolo26" and "SemanticSegment" in decoded data.pkl content, and re-exports the constant via __init__.py.
Base Exporter and Yolo26Exporter semseg support
tools/modules/exporter.py, tools/yolo/yolo26_exporter.py
Adds HeadSegmentationMetadata import and make_semantic_seg_nn_archive() to Exporter; adds SemanticSegment import, SEMSEG_MODE = 5, get_output_names SEMSEG branch, load_model head dispatch for SemanticSegment, and export_nn_archive SEMSEG branch in Yolo26Exporter.
CLI import, allowlist, and exporter routing
tools/main.py
Imports YOLOV26_SEM_CONVERSION, adds it to the YOLO_VERSIONS allowlist, and widens the Yolo26Exporter selection branch to match both YOLOV26_CONVERSION and YOLOV26_SEM_CONVERSION.
Test constants and end-to-end test
tests/constants.py, tests/test_end2end.py
Adds yolo26n-sem to TEST_MODELS and MODEL_TYPE2URL; introduces test_yolo26_semseg_nnarchive_head with version gating, CLI subprocess invocation, and assertions on output names, SegmentationParser type, n_classes == 19, and is_softmax is False.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested reviewers

  • klemen1999

Poem

🐇 Hop hop, a new head appears,
SemanticSegment to parse with cheers!
SEMSEG_MODE gets its own lane,
v26 detects and routes the brain.
The archive builds, the classes flow—
19 labels, softmax? No!
🥕 Another export off we go!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding YOLO26 semantic segmentation export support.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/86c9x87hh-yolov26-semseg

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown

☂️ Python Coverage

current status: ✅

Overall Coverage

Lines Covered Coverage Threshold Status
31896 6867 22% 0% 🟢

New Files

No new covered files...

Modified Files

File Coverage Status
tools/main.py 86% 🟢
tools/modules/exporter.py 80% 🟢
tools/version_detection/version_detection.py 47% 🟢
tools/yolo/yolo26_exporter.py 0% 🟢
TOTAL 53% 🟢

updated for commit: 501846c by action🐍

@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown

Test Results

  6 files    6 suites   23m 35s ⏱️
 26 tests  26 ✅ 0 💤 0 ❌
156 runs  156 ✅ 0 💤 0 ❌

Results for commit 501846c.

♻️ This comment has been updated with latest results.

@klemen1999 klemen1999 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM, just one nitpick and general question:
Do we potentially need any ultralytic submodule version bump? Just checking...

Comment thread tools/modules/exporter.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tools/modules/exporter.py (1)

247-253: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add a class-count consistency check at the semantic archive boundary.

class_list and n_classes are accepted independently, but there is no guard here. If they diverge, metadata becomes inconsistent and can break label mapping downstream. Please validate this in make_semantic_seg_nn_archive (Line 247 onward), not only in callers.

Suggested patch
 def make_semantic_seg_nn_archive(
     self,
     class_list: List[str],
     n_classes: int,
     is_softmax: bool = False,
     encoding: Encoding = Encoding.RGB,
 ):
@@
+    if len(class_list) != n_classes:
+        raise ValueError(
+            f"Number of class names ({len(class_list)}) does not match n_classes ({n_classes})."
+        )
+
     self.f_nn_archive = (self.output_folder / f"{self.model_name}.tar.xz").resolve()
     output_specs = self.get_output_specs()

Also applies to: 300-303

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/modules/exporter.py` around lines 247 - 253, The
`make_semantic_seg_nn_archive` method accepts `class_list` and `n_classes`
independently without validating consistency between them. Add a guard check at
the beginning of the `make_semantic_seg_nn_archive` method to ensure that the
length of `class_list` matches the value of `n_classes`, and raise a clear error
if they diverge. This prevents metadata inconsistencies from propagating
downstream into label mapping operations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@tools/modules/exporter.py`:
- Around line 247-253: The `make_semantic_seg_nn_archive` method accepts
`class_list` and `n_classes` independently without validating consistency
between them. Add a guard check at the beginning of the
`make_semantic_seg_nn_archive` method to ensure that the length of `class_list`
matches the value of `n_classes`, and raise a clear error if they diverge. This
prevents metadata inconsistencies from propagating downstream into label mapping
operations.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0810cdaa-b2df-40ec-8a59-effebfdcf6f6

📥 Commits

Reviewing files that changed from the base of the PR and between e870267 and 501846c.

📒 Files selected for processing (3)
  • tests/test_end2end.py
  • tools/modules/exporter.py
  • tools/yolo/yolo26_exporter.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • tools/yolo/yolo26_exporter.py
  • tests/test_end2end.py

@rolandocortez

Copy link
Copy Markdown
Contributor Author

Overall LGTM, just one nitpick and general question: Do we potentially need any ultralytic submodule version bump? Just checking...

I don't think we need a bumping right now. The current submodule pointer already includes SemanticSegment, and the targeted yolo26n-sem NNArchive test passes with the existing submodule version

@klemen1999 klemen1999 merged commit 3908a3f into main Jun 23, 2026
17 checks passed
@klemen1999 klemen1999 deleted the feat/86c9x87hh-yolov26-semseg branch June 23, 2026 20:15
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.

2 participants