Skip to content

Commit 50523f2

Browse files
Add loguru & better path handling (#132)
* Add loguru & better path handling * Add tqdm dependency * Update deps & fix unittests * [Automated] Updated coverage badge * Update README.md * Set Python to 3.10 & dependency update * Add seaborn --------- Co-authored-by: GitHub Actions <[email protected]>
1 parent 16a629d commit 50523f2

15 files changed

+95
-45
lines changed

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
> \[!NOTE\]\
44
> This is the latest version of tools CLI. If you are looking for the tools web application, please refer to the [web-app](https://github.com/luxonis/tools/tree/web-app) branch.
55
6-
This is a command-line tool that simplifies the conversion process of YOLO models. It supports the conversion of YOLOs ranging from V5 through V11 and Gold Yolo including oriented bounding boxes object detection (OBB), pose estimation, and instance segmentation variants of YOLOv8 and YOLO11 to ONNX format.
6+
This is a command-line tool that simplifies the conversion process of YOLO models. It supports the conversion of YOLOs ranging from V5 through V11 and Gold Yolo including oriented bounding boxes object detection (OBB), pose estimation, and instance segmentation variants of YOLOv8 and YOLO11 to ONNX format and archiving them in the NN Archive format.
77

88
> \[!WARNING\]\
99
> Please note that for the moment, we support conversion of YOLOv9 weights only from [Ultralytics](https://docs.ultralytics.com/models/yolov9/#performance-on-ms-coco-dataset).
@@ -34,8 +34,6 @@ cd tools
3434

3535
### Using Python package
3636

37-
For this to work, you need to be located in the root folder of the project.
38-
3937
```bash
4038
# Install the package
4139
pip install .

media/coverage_badge.svg

Lines changed: 2 additions & 2 deletions
Loading

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "tools"
3-
version = "0.2.1"
3+
version = "0.2.3"
44
description = "Converter for YOLO models into .ONNX format."
55
readme = "README.md"
66
requires-python = ">=3.8"
@@ -49,7 +49,7 @@ select = ["E4", "E7", "E9", "F", "W", "B", "I", "FA"]
4949
convention = "google"
5050

5151
[tool.mypy]
52-
python_version = "3.8"
52+
python_version = "3.10"
5353
ignore_missing_imports = true
5454

5555
[tool.pyright]

requirements-dev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
pre-commit==3.2.1
1+
pre-commit>=4.1.0
22
pytest-cov>=4.1.0
33
docker-squash>=1.1.0

requirements.txt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
torch>=1.9.1,<2.6.0
1+
torch>=2.0.0,<2.6.0
22
torchvision>=0.10.1
33
Pillow>=7.1.2
44
PyYAML>=5.3.1
55
gcsfs
6-
luxonis-ml[data,nn_archive]>=0.5.1
7-
# luxonis-ml[data,nn_archive] @ git+https://github.com/luxonis/luxonis-ml@dev
8-
onnx>=1.10.1
9-
onnxruntime
10-
onnxsim
6+
luxonis-ml[data,nn_archive,utils]>=0.6.1
7+
onnx>=1.17.0
8+
onnxruntime>=1.20.1
9+
onnxsim>=0.4.36
1110
s3fs
11+
tqdm
1212
s3transfer
1313
typer>=0.12.3
1414
psutil
15-
mmcv==1.5.0
16-
seaborn
15+
seaborn
16+
mmcv>=1.5.0,<2.0.0

tests/test_conversion.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import requests
66

77
from tools.utils.version_detection import detect_version
8+
from tools.yolo.yolov6_exporter import YoloV6R4Exporter
89
from tools.yolo.yolov8_exporter import YoloV8Exporter
910
from tools.yolo.yolov10_exporter import YoloV10Exporter
1011
from tools.yolov7.yolov7_exporter import YoloV7Exporter
@@ -94,6 +95,14 @@ def test_yolov6nr4_automatic_version_detection():
9495
_remove_file("tests/yolov6n.pt")
9596

9697

98+
def test_yolov6nr4_model_conversion():
99+
"""Test the conversion of an YOLOv6nr4 model."""
100+
_download_file(
101+
"https://github.com/meituan/YOLOv6/releases/download/0.4.0/yolov6n.pt"
102+
)
103+
_test_model_conversion(YoloV6R4Exporter, "tests/yolov6n.pt", (640, 480), True)
104+
105+
97106
def test_yolov7t_automatic_version_detection():
98107
"""Test the YOLOv7t autodetection of the model version."""
99108
_download_file(

tools/main.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
#!/usr/bin/env python3
12
from __future__ import annotations
23

3-
import logging
44
from typing import Optional
55

66
import typer
7+
from loguru import logger
8+
from luxonis_ml.utils import setup_logging
79
from typing_extensions import Annotated
810

911
from tools.utils import (
@@ -24,9 +26,7 @@
2426
)
2527
from tools.utils.constants import MISC_DIR
2628

27-
logging.basicConfig()
28-
logging.getLogger().setLevel(logging.INFO)
29-
29+
setup_logging()
3030

3131
app = typer.Typer(help="Tools CLI", add_completion=False, rich_markup_mode="markdown")
3232

@@ -80,9 +80,6 @@ def convert(
8080
),
8181
] = None,
8282
):
83-
logger = logging.getLogger(__name__)
84-
logger.info("Converting model...")
85-
8683
if version is not None and version not in YOLO_VERSIONS:
8784
logger.error("Wrong YOLO version selected!")
8885
raise typer.Exit(code=1) from None

tools/yolo/yolov10_exporter.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
from __future__ import annotations
22

3+
import os
34
import sys
45
from typing import List, Optional, Tuple
56

7+
from loguru import logger
8+
69
from tools.modules import DetectV10, Exporter
710
from tools.utils import get_first_conv2d_in_channels
811

9-
sys.path.append("./tools/yolo/ultralytics")
12+
current_dir = os.path.dirname(os.path.abspath(__file__))
13+
yolo_path = os.path.join(current_dir, "ultralytics")
14+
sys.path.append(yolo_path)
15+
1016
from ultralytics.nn.modules import Detect # noqa: E402
1117
from ultralytics.nn.tasks import attempt_load_one_weight # noqa: E402
1218

@@ -48,7 +54,7 @@ def load_model(self):
4854
self.number_of_channels = get_first_conv2d_in_channels(model)
4955
# print(f"Number of channels: {self.number_of_channels}")
5056
except Exception as e:
51-
print(f"Error while getting number of channels: {e}")
57+
logger.error(f"Error while getting number of channels: {e}")
5258

5359
# check if image size is suitable
5460
gs = max(int(model.stride.max()), 32) # model stride

tools/yolo/yolov5_exporter.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
from __future__ import annotations
22

3+
import os
34
import sys
45
from typing import List, Optional, Tuple
56

67
import torch.nn as nn
8+
from loguru import logger
79

810
from tools.modules import DetectV5, Exporter
911
from tools.utils import get_first_conv2d_in_channels
1012

11-
sys.path.append("./tools/yolo/yolov5")
13+
current_dir = os.path.dirname(os.path.abspath(__file__))
14+
yolov5_path = os.path.join(current_dir, "yolov5")
15+
sys.path.append(yolov5_path)
1216

1317
from models.common import Conv # noqa: E402
14-
from models.experimental import attempt_load # noqa: E402
15-
from models.yolo import Detect # noqa: E402
18+
from models.experimental import attempt_load as attempt_load_yolov5 # noqa: E402
19+
from models.yolo import Detect as DetectYOLOv5 # noqa: E402
1620
from utils.activations import SiLU # noqa: E402
1721

1822

@@ -35,7 +39,7 @@ def __init__(
3539
def load_model(self):
3640
# code based on export.py from YoloV5 repository
3741
# load the model
38-
model = attempt_load(self.model_path, device="cpu") # load FP32 model
42+
model = attempt_load_yolov5(self.model_path, device="cpu") # load FP32 model
3943

4044
# check num classes and labels
4145
assert model.nc == len(
@@ -60,7 +64,7 @@ def load_model(self):
6064
if isinstance(m, Conv): # assign export-friendly activations
6165
if isinstance(m.act, nn.SiLU):
6266
m.act = SiLU()
63-
elif isinstance(m, Detect):
67+
elif isinstance(m, DetectYOLOv5):
6468
m.inplace = inplace
6569
m.onnx_dynamic = False
6670
if hasattr(m, "forward_export"):
@@ -78,7 +82,7 @@ def load_model(self):
7882
self.number_of_channels = get_first_conv2d_in_channels(model)
7983
# print(f"Number of channels: {self.number_of_channels}")
8084
except Exception as e:
81-
print(f"Error while getting number of channels: {e}")
85+
logger.error(f"Error while getting number of channels: {e}")
8286

8387
self.m = model.module.model[-1] if hasattr(model, "module") else model.model[-1]
8488
self.num_branches = len(self.m.anchor_grid)

tools/yolo/yolov6_exporter.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
from __future__ import annotations
22

3+
import os
34
import sys
45
from typing import Tuple
56

7+
from loguru import logger
8+
69
from tools.modules import DetectV6R4m, DetectV6R4s, Exporter
710
from tools.utils import get_first_conv2d_in_channels
811

9-
sys.path.append("./tools/yolo/YOLOv6")
12+
current_dir = os.path.dirname(os.path.abspath(__file__))
13+
yolov6_path = os.path.join(current_dir, "YOLOv6")
14+
sys.path.append(yolov6_path)
15+
1016
from yolov6.layers.common import RepVGGBlock # noqa: E402
1117
from yolov6.models.heads.effidehead_distill_ns import Detect # noqa: E402
1218
from yolov6.utils.checkpoint import load_checkpoint # noqa: E402
@@ -51,7 +57,7 @@ def load_model(self):
5157
self.number_of_channels = get_first_conv2d_in_channels(model)
5258
# print(f"Number of channels: {self.number_of_channels}")
5359
except Exception as e:
54-
print(f"Error while getting number of channels: {e}")
60+
logger.error(f"Error while getting number of channels: {e}")
5561

5662
self.num_branches = len(model.detect.grid)
5763

0 commit comments

Comments
 (0)