Skip to content

Update yolo_object_detection_training to use YOLOn26-obb configuration#44

Merged
kluge7 merged 17 commits intomainfrom
refactor/yolo_object_detection_training
Feb 22, 2026
Merged

Update yolo_object_detection_training to use YOLOn26-obb configuration#44
kluge7 merged 17 commits intomainfrom
refactor/yolo_object_detection_training

Conversation

@jenscaa
Copy link
Contributor

@jenscaa jenscaa commented Jan 29, 2026

Updates the YOLO object detection training pipeline to use the YOLOv26 OBB configuration. The training script now initializes a YOLOv26-oriented bounding box model, downloads the corresponding Roboflow OBB dataset, trains on GPU using Ultralytics, and exports the best checkpoint for deployment.

@jenscaa jenscaa requested a review from kluge7 January 29, 2026 11:03
@jenscaa jenscaa self-assigned this Jan 29, 2026
@codecov
Copy link

codecov bot commented Jan 29, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 0.00%. Comparing base (81092cc) to head (c313b74).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@          Coverage Diff          @@
##            main     #44   +/-   ##
=====================================
  Coverage   0.00%   0.00%           
=====================================
  Files          3       3           
  Lines        191     191           
  Branches      17      17           
=====================================
  Misses       191     191           
Flag Coverage Δ
unittests 0.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
ros_nodes/vortex_image_segmentation/setup.py 0.00% <ø> (ø)
...segmentation/vortex_image_segmentation/yolo_seg.py 0.00% <ø> (ø)
...ntation/vortex_image_segmentation/yolo_seg_node.py 0.00% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@kluge7 kluge7 left a comment

Choose a reason for hiding this comment

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

Make a different folder for OBB and leave normal object detection unchanged

@jenscaa jenscaa force-pushed the refactor/yolo_object_detection_training branch from 75e4288 to b268124 Compare January 29, 2026 12:50
@kluge7 kluge7 requested a review from Copilot January 29, 2026 13:07
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 10 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

project = rf.workspace(ROBOFLOW_WORKSPACE_NAME).project(ROBOFLOW_PROJECT)

# Export format: Roboflow's "yolov8" export works well with ultralytics
# and also with recent YOLOv2.6 OBB support when datasets include OBB
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

The comment incorrectly refers to "YOLOv2.6 OBB support" which is not a valid YOLO version. This should reference the actual YOLO version that supports OBB (e.g., "YOLOv8 OBB" or "YOLOv11 OBB").

Suggested change
# and also with recent YOLOv2.6 OBB support when datasets include OBB
# and also with modern YOLO OBB support when datasets include OBB

Copilot uses AI. Check for mistakes.
Comment on lines +55 to +63
model_arg = MODEL_NAME
if not MODEL_NAME.endswith(".pt") and not Path(f"{MODEL_NAME}.pt").exists():
model_arg = MODEL_NAME
elif Path(MODEL_NAME).exists() or Path(f"{MODEL_NAME}.pt").exists():
model_arg = str(
Path(MODEL_NAME)
if Path(MODEL_NAME).suffix == ".pt"
else Path(f"{MODEL_NAME}.pt")
)
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

The model resolution logic contains redundant conditions. Lines 56-57 check if MODEL_NAME doesn't end with ".pt" and the file doesn't exist, then assign MODEL_NAME to model_arg (which is already set to MODEL_NAME on line 55). This condition will never change the value. The logic should be simplified to handle three clear cases: (1) MODEL_NAME is already a .pt file that exists, (2) MODEL_NAME without .pt extension exists as a file, or (3) MODEL_NAME is a model identifier to be resolved by the library.

Suggested change
model_arg = MODEL_NAME
if not MODEL_NAME.endswith(".pt") and not Path(f"{MODEL_NAME}.pt").exists():
model_arg = MODEL_NAME
elif Path(MODEL_NAME).exists() or Path(f"{MODEL_NAME}.pt").exists():
model_arg = str(
Path(MODEL_NAME)
if Path(MODEL_NAME).suffix == ".pt"
else Path(f"{MODEL_NAME}.pt")
)
model_path = Path(MODEL_NAME)
pt_model_path = Path(f"{MODEL_NAME}.pt")
if model_path.suffix == ".pt" and model_path.exists():
# Case 1: MODEL_NAME is already a .pt file that exists.
model_arg = str(model_path)
elif pt_model_path.exists():
# Case 2: MODEL_NAME without .pt extension has a corresponding .pt file.
model_arg = str(pt_model_path)
else:
# Case 3: MODEL_NAME is a model identifier to be resolved by the library.
model_arg = MODEL_NAME

Copilot uses AI. Check for mistakes.
Comment on lines +76 to +82
project=Path("results") / "yolov26_obb",
name=experiment_name,
)

# Load the best checkpoint produced during training.
best_weights_path = (
Path("results") / "yolov26_obb" / experiment_name / "weights" / "best.pt"
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

The project path uses "yolov26_obb" which references a non-existent YOLO version. This should be updated to match the actual YOLO version being used (e.g., "yolov8_obb" or "yolov11_obb"). This is also used in the best_weights_path on line 82.

Suggested change
project=Path("results") / "yolov26_obb",
name=experiment_name,
)
# Load the best checkpoint produced during training.
best_weights_path = (
Path("results") / "yolov26_obb" / experiment_name / "weights" / "best.pt"
project=Path("results") / "yolov8_obb",
name=experiment_name,
)
# Load the best checkpoint produced during training.
best_weights_path = (
Path("results") / "yolov8_obb" / experiment_name / "weights" / "best.pt"

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,101 @@
#!/usr/bin/env python3
"""Train a YOLOv26 OBB object detection model using a Roboflow dataset.
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

The PR description mentions updating to use "YOLOv26 OBB configuration", but YOLOv26 is not a valid YOLO version. The description should be updated to reference the actual YOLO version that will be used (e.g., YOLOv8 or YOLOv11). This discrepancy suggests the entire PR may be based on an incorrect understanding of available YOLO versions.

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +54
# Resolve model argument for ultralytics YOLO: allow either a local .pt
# or a model name like 'yolo26n-obb' which the library may resolve.
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

The comment references 'yolo26n-obb' which is not a valid YOLO model name. This should be updated to reference a real model like 'yolov8n-obb' or 'yolov11n-obb'.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,43 @@
# Object detection training
Scripts for training an oriented object detection model using YOLOv26 on Roboflow datasets.
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

The documentation incorrectly references "YOLOv26" which is not a valid YOLO version. This should be updated to reference the actual YOLO version being used (e.g., YOLOv8 or YOLOv11).

Suggested change
Scripts for training an oriented object detection model using YOLOv26 on Roboflow datasets.
Scripts for training an oriented object detection model using YOLO on Roboflow datasets.

Copilot uses AI. Check for mistakes.
Comment on lines +74 to +97
device=device_str,
workers=8,
project=Path("results") / "yolov26_obb",
name=experiment_name,
)

# Load the best checkpoint produced during training.
best_weights_path = (
Path("results") / "yolov26_obb" / experiment_name / "weights" / "best.pt"
)
if not best_weights_path.exists():
raise FileNotFoundError(
f"Trained model checkpoint not found at {best_weights_path}. "
"Ensure training completed successfully before validation and export."
)

trained_model = YOLO(str(best_weights_path))

metrics = trained_model.val(data=str(data_yaml_path))
print("Validation metrics:", metrics)

# Export formats for deployment
for fmt in ["onnx"]:
trained_model.export(format=fmt, device=DEVICE)
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

There's an inconsistency in device specification. Line 74 uses device=device_str (a string like "cuda:0") for training, while line 97 uses device=DEVICE (an integer 0) for export. For consistency and following the pattern in yolo_object_detection_training/train.py:56,79, both should use the same format. The integer format (device=DEVICE) is simpler and consistent with the existing codebase.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

#SBATCH --partition=GPUQ
#SBATCH --account=studiegrupper-vortex
#SBATCH --job-name=vortex-obj-detect-train
#SBATCH --time=1:00:00
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

The SLURM job time limit is set to 1 hour, but the training script is configured to run for 200 epochs (line 71 in train.py). For most deep learning training tasks, especially with object detection models, 200 epochs typically takes significantly longer than 1 hour. This mismatch will likely cause the job to be terminated before training completes. Consider either reducing the number of epochs or increasing the time limit to a more realistic value (e.g., 8-24 hours depending on dataset size).

Copilot uses AI. Check for mistakes.
onnx>=1.12.0
onnxruntime>=1.16.0
opencv_contrib_python==4.9.0.80
opencv_python==4.9.0.80
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

Both opencv_contrib_python and opencv_python are installed, which can cause conflicts since opencv_contrib_python already includes all functionality from opencv_python. Installing both packages is redundant and can lead to version conflicts or unexpected behavior. Remove opencv_python and keep only opencv_contrib_python, or use only opencv_python if the contrib modules are not needed.

Suggested change
opencv_python==4.9.0.80

Copilot uses AI. Check for mistakes.
onnxruntime>=1.16.0
opencv_contrib_python==4.9.0.80
opencv_python==4.9.0.80
pafy==0.5.5
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

The pafy library (version 0.5.5) is deprecated and no longer maintained. It was primarily used for YouTube video downloads but has known issues with recent YouTube API changes. If this dependency is not actually used in the code (no imports found in train.py), it should be removed. If it's an indirect dependency of ultralytics that's needed for video processing features, consider if those features are actually required for this training pipeline.

Suggested change
pafy==0.5.5

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +66
# Resolve model argument for ultralytics YOLO: allow either a local .pt
# or a model name like 'yolo26n-obb' which the library may resolve.
model_arg = MODEL_NAME
if not MODEL_NAME.endswith(".pt") and not Path(f"{MODEL_NAME}.pt").exists():
model_arg = MODEL_NAME
elif Path(MODEL_NAME).exists() or Path(f"{MODEL_NAME}.pt").exists():
model_arg = str(
Path(MODEL_NAME)
if Path(MODEL_NAME).suffix == ".pt"
else Path(f"{MODEL_NAME}.pt")
)

model = YOLO(model_arg)

Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

The model resolution logic is redundant and confusing. Lines 56-57 check if MODEL_NAME doesn't end with ".pt" and the file doesn't exist, then assign MODEL_NAME to model_arg (which is already done on line 55). Lines 58-63 check if the file exists and construct a path, but this is unnecessary since MODEL_NAME is already "yolo26m-obb.pt" (ends with .pt). This entire block can be simplified to just pass MODEL_NAME directly to YOLO() on line 65, as the ultralytics library will handle model resolution internally.

Suggested change
# Resolve model argument for ultralytics YOLO: allow either a local .pt
# or a model name like 'yolo26n-obb' which the library may resolve.
model_arg = MODEL_NAME
if not MODEL_NAME.endswith(".pt") and not Path(f"{MODEL_NAME}.pt").exists():
model_arg = MODEL_NAME
elif Path(MODEL_NAME).exists() or Path(f"{MODEL_NAME}.pt").exists():
model_arg = str(
Path(MODEL_NAME)
if Path(MODEL_NAME).suffix == ".pt"
else Path(f"{MODEL_NAME}.pt")
)
model = YOLO(model_arg)
# Initialize the YOLO model; ultralytics will handle model resolution.
model = YOLO(MODEL_NAME)

Copilot uses AI. Check for mistakes.

# Export formats for deployment
for fmt in ["onnx"]:
trained_model.export(format=fmt, device=DEVICE)
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

The export method is being called with device=DEVICE where DEVICE is an integer (0). However, the training was done with device=device_str which is a string like "cuda:0". For consistency and to avoid potential issues, the export should use the same device format as training. Change device=DEVICE to device=device_str.

Suggested change
trained_model.export(format=fmt, device=DEVICE)
trained_model.export(format=fmt, device=device_str)

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

onnxruntime>=1.16.0
opencv_contrib_python==4.9.0.80
opencv_python==4.9.0.80
pafy==0.5.5
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

pafy is included as a direct dependency, but it doesn’t appear to be used anywhere in this repository. Carrying unused dependencies increases install time and the chance of supply-chain / compatibility issues; consider removing it unless there is a concrete runtime use-case for it in this training pipeline.

Suggested change
pafy==0.5.5

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +6
"""Train a YOLOv26 OBB object detection model using a Roboflow dataset.

This script is written to work with YOLOv2.6 oriented-bounding-box (OBB)
model names such as `yolo26n-obb`. It downloads a Roboflow dataset,
trains a model using the `ultralytics` API and exports the trained model.
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The module docstring uses both “YOLOv26” and “YOLOv2.6” to refer to the model/version. Please standardize on one term throughout the docstring to avoid confusion for readers and future maintainers.

Copilot uses AI. Check for mistakes.
ROBOFLOW_PROJECT = "valve_obb_annotations-ejsa6"
ROBOFLOW_PROJECT_VERSION = "2"

# Use a pretrained YOLOv26n model to avoid training from scratch.
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

This comment says “YOLOv26n” but MODEL_NAME is set to yolo26m-obb.pt. Update the comment (or the constant) so the documented model size matches what will actually be trained.

Suggested change
# Use a pretrained YOLOv26n model to avoid training from scratch.
# Use a pretrained YOLOv26m model (yolo26m-obb.pt) to avoid training from scratch.

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +33
print("CUDA version:", torch.version.cuda)
print("cuDNN version:", torch.backends.cudnn.version())
print("Using GPU:", torch.cuda.get_device_name(0))
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

GPU logging is hard-coded to device index 0 (torch.cuda.get_device_name(0)) while training uses the configurable DEVICE. If DEVICE is changed, the script will print the wrong GPU and may later fail when selecting the device. Use DEVICE for the device name lookup (and consider validating DEVICE < torch.cuda.device_count() early).

Suggested change
print("CUDA version:", torch.version.cuda)
print("cuDNN version:", torch.backends.cudnn.version())
print("Using GPU:", torch.cuda.get_device_name(0))
# Validate that the configured DEVICE index is usable before proceeding.
if not isinstance(DEVICE, int) or DEVICE < 0 or DEVICE >= torch.cuda.device_count():
raise RuntimeError(
f"Configured DEVICE index {DEVICE} is invalid. "
f"Available CUDA device indices are 0 to {torch.cuda.device_count() - 1}."
)
print("CUDA version:", torch.version.cuda)
print("cuDNN version:", torch.backends.cudnn.version())
print("Using GPU:", torch.cuda.get_device_name(DEVICE))

Copilot uses AI. Check for mistakes.
@kluge7 kluge7 merged commit 45bef8c into main Feb 22, 2026
4 checks passed
@kluge7 kluge7 deleted the refactor/yolo_object_detection_training branch February 22, 2026 21:04
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.

3 participants