diff --git a/README.md b/README.md index 934a072..8d865c1 100644 --- a/README.md +++ b/README.md @@ -3,15 +3,29 @@ > \[!NOTE\]\ > 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. -This application is used for exporting Yolo V5, V6, V7, V8 (OBB, instance segmentation, pose estimation, cls) and Gold YOLO object detection models to .ONNX. +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. + +> \[!WARNING\]\ +> 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). ## Running -You can either export a model stored on cloud (e.g. S3) or locally. To export a local model, please put it inside a `shared-component` folder. +You can either export a model stored on the cloud (e.g. S3) or locally. You can choose to install the toolkit through pip or using Docker. In the sections below, we'll describe both options. -The output files are going to be in `shared-component/output` folder. +### Using Python package + +```bash +# Install the package +pip install tools@git+https://github.com/luxonis/tools.git@main +# Running the package +tools yolov6nr4.pt --imgsz "416" +``` + +### Using Docker or Docker Compose -### Prerequisites +This option requires you to have Docker installed on your device. Additionally, to export a local model, please put it inside a `shared-component/models/` folder in the root folder of the project. + +#### Prerequisites ```bash # Cloning the tools repository and all submodules @@ -20,7 +34,7 @@ git clone --recursive https://github.com/luxonis/tools.git cd tools ``` -### Using Docker +#### Using Docker ```bash # Building Docker image @@ -29,7 +43,7 @@ docker build -t tools_cli . docker run -v "${PWD}/shared_with_container:/app/shared_with_container" tools_cli shared_with_container/models/yolov8n-seg.pt --imgsz "416" ``` -### Using Docker compose +#### Using Docker compose ```bash # Building Docker image @@ -38,14 +52,7 @@ docker compose build docker compose run tools_cli shared_with_container/models/yolov6nr4.pt ``` -### Using Python package - -```bash -# Building the package -pip install . -# Running the package -tools shared_with_container/models/yolov6nr4.pt --imgsz "416" -``` +The output files are going to be in `shared-component/output` folder. ### Arguments @@ -60,7 +67,7 @@ tools shared_with_container/models/yolov6nr4.pt --imgsz "416" ## Credits -This application uses source code of the following repositories: [YOLOv5](https://github.com/ultralytics/yolov5), [YOLOv6](https://github.com/meituan/YOLOv6), [GoldYOLO](https://github.com/huawei-noah/Efficient-Computing) [YOLOv7](https://github.com/WongKinYiu/yolov7), and [Ultralytics YOLOv8](https://github.com/ultralytics/ultralytics) (see each of them for more information). +This application uses source code of the following repositories: [YOLOv5](https://github.com/ultralytics/yolov5), [YOLOv6](https://github.com/meituan/YOLOv6), [GoldYOLO](https://github.com/huawei-noah/Efficient-Computing) [YOLOv7](https://github.com/WongKinYiu/yolov7), and [Ultralytics](https://github.com/ultralytics/ultralytics) (see each of them for more information). ## License diff --git a/requirements.txt b/requirements.txt index fc9bb56..0b6b353 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ torchvision>=0.10.1 Pillow>=7.1.2 PyYAML>=5.3.1 gcsfs -luxonis-ml[data,nn_archive]>=0.4.0 +luxonis-ml[data,nn_archive]>=0.4.1 # luxonis-ml[data,nn_archive] @ git+https://github.com/luxonis/luxonis-ml@dev onnx>=1.10.1 onnxruntime diff --git a/tools/main.py b/tools/main.py index 2741dd4..7755d5c 100644 --- a/tools/main.py +++ b/tools/main.py @@ -4,6 +4,7 @@ from typing import Optional import typer +from typing_extensions import Annotated from tools.utils import ( GOLD_YOLO_CONVERSION, @@ -46,14 +47,38 @@ @app.command() def convert( - model: str, - imgsz: str = "416 416", - version: Optional[str] = None, - use_rvc2: bool = True, - class_names: Optional[str] = None, - output_remote_url: Optional[str] = None, - config_path: Optional[str] = None, - put_file_plugin: Optional[str] = None, + model: Annotated[str, typer.Argument(help="Path to the model file.")], + imgsz: Annotated[ + str, typer.Option(help="Input image size [width, height].") + ] = "416 416", + version: Annotated[ + Optional[str], + typer.Option( + help='YOLO version (e.g. `"yolov8"`). If `None`, the toolkit will run an automatic version detector.' + ), + ] = None, + use_rvc2: Annotated[ + bool, typer.Option(help="Whether the target platform is RVC2 or RVC3.") + ] = True, + class_names: Annotated[ + Optional[str], + typer.Option( + help='A list of class names the model is capable of recognizing (e.g. `"person, bicycle, car"`).' + ), + ] = None, + output_remote_url: Annotated[ + Optional[str], typer.Option(help="An URL to upload the output to.") + ] = None, + config_path: Annotated[ + Optional[str], + typer.Option(help="An optional path to a conversion config file."), + ] = None, + put_file_plugin: Annotated[ + Optional[str], + typer.Option( + help="The name of a registered function under the PUT_FILE_REGISTRY." + ), + ] = None, ): logger = logging.getLogger(__name__) logger.info("Converting model...") @@ -146,7 +171,7 @@ def convert( try: logger.info("Creating NN archive...") exporter.export_nn_archive(config.class_names) - logger.info("NN archive created.") + logger.info(f"NN archive created in {exporter.output_folder}.") except Exception as e: logger.error(f"Error creating NN archive: {e}") raise typer.Exit(code=1) from e diff --git a/tools/utils/config.py b/tools/utils/config.py index 698f46f..42518f9 100644 --- a/tools/utils/config.py +++ b/tools/utils/config.py @@ -12,7 +12,7 @@ class Config(LuxonisConfig): default=[416, 416], min_length=2, max_length=2, - min_ledescription="Image size [width, height].", + min_ledescription="Input image size [width, height].", ) class_names: Optional[List[str]] = Field(None, description="List of class names.") use_rvc2: Literal[False, True] = Field(True, description="Whether to use RVC2.")