trtyolo-export 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
trtyolo_export/cli.py ADDED
@@ -0,0 +1,570 @@
1
+ #!/usr/bin/env python
2
+ # -*-coding:utf-8 -*-
3
+ # ==============================================================================
4
+ # Copyright (c) 2024 laugh12321 Authors. All Rights Reserved.
5
+ #
6
+ # Licensed under the GNU General Public License v3.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # https://www.gnu.org/licenses/gpl-3.0.html
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ # ==============================================================================
18
+ # File : cli.py
19
+ # Version : 6.4.0
20
+ # Author : laugh12321
21
+ # Contact : laugh12321@vip.qq.com
22
+ # Date : 2024/07/05 14:26:53
23
+ # Desc : trtyolo cli.
24
+ # ==============================================================================
25
+ from __future__ import annotations
26
+
27
+ import sys
28
+ import warnings
29
+ from collections.abc import Sequence
30
+ from copy import deepcopy
31
+ from pathlib import Path
32
+ from typing import List, Optional, Tuple, Union
33
+
34
+ import onnx
35
+ import rich_click as click
36
+ import torch
37
+ from loguru import logger
38
+
39
+ # Filter warnings
40
+ warnings.filterwarnings("ignore")
41
+
42
+ # For scripts
43
+ logger.configure(handlers=[{'sink': sys.stdout, 'colorize': True, 'format': "<level>[{level.name[0]}]</level> <level>{message}</level>"}])
44
+
45
+
46
+ class ModelExporter:
47
+ """Base class for model export functionality."""
48
+
49
+ def __init__(self) -> None:
50
+ from .head import (
51
+ UltralyticsClassify,
52
+ UltralyticsDetect,
53
+ UltralyticsOBB,
54
+ UltralyticsPose,
55
+ UltralyticsSegment,
56
+ YOLOClassify,
57
+ YOLODetect,
58
+ YOLOEDetectHead,
59
+ YOLOESegmentHead,
60
+ YOLOSegment,
61
+ YOLOV10Detect,
62
+ YOLOWorldDetect,
63
+ )
64
+
65
+ self.__batch = None
66
+ self.__model = None
67
+ self.__head_name = None
68
+ self.__version = None
69
+
70
+ self.__max_boxes = None
71
+ self.__dynamic = None
72
+ self.__weight_name = None
73
+
74
+ self.__output_names = ["num_dets", "det_boxes", "det_scores", "det_classes"]
75
+ self.__dynamic_axes = {
76
+ "images": {0: "batch", 2: "height", 3: "width"},
77
+ "num_dets": {0: "batch"},
78
+ "det_boxes": {0: "batch"},
79
+ "det_scores": {0: "batch"},
80
+ "det_classes": {0: "batch"},
81
+ }
82
+ self.__head_config = {
83
+ "Detect": {
84
+ "class_map": {
85
+ "yolov3": YOLODetect,
86
+ "yolov5": YOLODetect,
87
+ "yolov8": UltralyticsDetect,
88
+ "yolo11": UltralyticsDetect,
89
+ "yolo12": UltralyticsDetect,
90
+ "ultralytics": UltralyticsDetect,
91
+ },
92
+ "output_names": self.__output_names,
93
+ "dynamic_axes": self.__dynamic_axes,
94
+ },
95
+ "v10Detect": {
96
+ "class_map": {"yolov10": YOLOV10Detect, "ultralytics": YOLOV10Detect},
97
+ "output_names": self.__output_names,
98
+ "dynamic_axes": self.__dynamic_axes,
99
+ },
100
+ "WorldDetect": {
101
+ "class_map": {"yolo-world": YOLOWorldDetect, "ultralytics": YOLOWorldDetect},
102
+ "output_names": self.__output_names,
103
+ "dynamic_axes": self.__dynamic_axes,
104
+ },
105
+ "YOLOEDetect": {
106
+ "class_map": {"yoloe": YOLOEDetectHead, "ultralytics": YOLOEDetectHead},
107
+ "output_names": self.__output_names,
108
+ "dynamic_axes": self.__dynamic_axes,
109
+ },
110
+ "YOLOESegment": {
111
+ "class_map": {"yoloe": YOLOESegmentHead, "ultralytics": YOLOESegmentHead},
112
+ "output_names": self.__output_names + ["det_masks"],
113
+ "dynamic_axes": {**self.__dynamic_axes, "det_masks": {0: "batch", 2: "height", 3: "width"}},
114
+ },
115
+ "OBB": {
116
+ "class_map": {
117
+ "yolov8": UltralyticsOBB,
118
+ "yolo11": UltralyticsOBB,
119
+ "yolo12": UltralyticsOBB,
120
+ "ultralytics": UltralyticsOBB,
121
+ },
122
+ "output_names": self.__output_names,
123
+ "dynamic_axes": self.__dynamic_axes,
124
+ },
125
+ "Segment": {
126
+ "class_map": {
127
+ "yolov3": YOLOSegment,
128
+ "yolov5": YOLOSegment,
129
+ "yolov8": UltralyticsSegment,
130
+ "yolo11": UltralyticsSegment,
131
+ "yolo12": UltralyticsSegment,
132
+ "ultralytics": UltralyticsSegment,
133
+ },
134
+ "output_names": self.__output_names + ["det_masks"],
135
+ "dynamic_axes": {**self.__dynamic_axes, "det_masks": {0: "batch", 2: "height", 3: "width"}},
136
+ },
137
+ "Pose": {
138
+ "class_map": {
139
+ "yolov8": UltralyticsPose,
140
+ "yolo11": UltralyticsPose,
141
+ "yolo12": UltralyticsPose,
142
+ "ultralytics": UltralyticsPose,
143
+ },
144
+ "output_names": self.__output_names + ["det_kpts"],
145
+ "dynamic_axes": {**self.__dynamic_axes, "det_kpts": {0: "batch"}},
146
+ },
147
+ "Classify": {
148
+ "class_map": {
149
+ "yolov3": YOLOClassify,
150
+ "yolov5": YOLOClassify,
151
+ "yolov8": UltralyticsClassify,
152
+ "yolo11": UltralyticsClassify,
153
+ "yolo12": UltralyticsClassify,
154
+ "ultralytics": UltralyticsClassify,
155
+ },
156
+ "output_names": ["topk"],
157
+ "dynamic_axes": {"images": {0: "batch", 2: "height", 3: "width"}, "topk": {0: "batch"}},
158
+ },
159
+ }
160
+ self.__export_info = {
161
+ 'yolov6': "https://github.com/meituan/YOLOv6/tree/main/deploy/ONNX#tensorrt-backend-tensorrt-version-800",
162
+ 'yolov7': "https://github.com/WongKinYiu/yolov7#export",
163
+ 'yolov9': "https://github.com/WongKinYiu/yolov9/issues/130#issue-2162045461",
164
+ }
165
+ logger.info("Starting export with Pytorch.")
166
+
167
+ def load(self, weights: str, version: str, repo_dir: Optional[str] = None, custom_classes: Optional[Sequence[str]] = None) -> None:
168
+ self.__version = version
169
+ self.__weight_name = Path(weights).stem
170
+
171
+ yolo_versions_with_repo = {
172
+ 'yolov3': 'ultralytics/yolov3',
173
+ 'yolov5': 'ultralytics/yolov5',
174
+ }
175
+
176
+ source = 'github' if repo_dir is None else 'local'
177
+
178
+ if version in yolo_versions_with_repo:
179
+ repo_dir = yolo_versions_with_repo[version] if repo_dir is None else repo_dir
180
+ self.__model = torch.hub.load(repo_dir, 'custom', path=weights, source=source, _verbose=False)
181
+ elif version in ['yolov8', 'yolov10', 'yolo11', 'yolo12', 'yolo-world', 'yoloe', 'ultralytics']:
182
+ from ultralytics import YOLO
183
+
184
+ self.__model = YOLO(model=weights, verbose=False).model
185
+
186
+ if custom_classes is not None:
187
+ if version == 'yolo-world':
188
+ self.__model.set_classes(custom_classes)
189
+ elif version == 'yoloe':
190
+ self.__model.set_classes(custom_classes, self.__model.get_text_pe(custom_classes))
191
+ else:
192
+ logger.error(
193
+ f"YOLO version '{version}' is unsupported for export with trtyolo CLI tool. "
194
+ "Please provide a valid version, e.g., yolov3, yolov5, yolov8, yolov10, yolo11, yolo12, yolo-world, yoloe, ultralytics."
195
+ )
196
+ if version in self.__export_info:
197
+ logger.warning(
198
+ f"The official {version} repository supports exporting an ONNX model with the EfficientNMS_TRT plugin. "
199
+ f"Please refer to {self.__export_info[version]} for instructions on how to export it."
200
+ )
201
+ sys.exit(1)
202
+
203
+ def register(self, batch: int, max_boxes: int, iou_thres: float, conf_thres: float) -> None:
204
+ self.__model = deepcopy(self.__model).to(torch.device("cpu"))
205
+ supported = False
206
+
207
+ self.__max_boxes = max_boxes
208
+ self.__dynamic = batch <= 0
209
+ self.__batch = 1 if batch <= 0 else batch
210
+
211
+ for m in self.__model.modules():
212
+ class_name = m.__class__.__name__
213
+ if class_name in self.__head_config:
214
+ self.__head_name = class_name
215
+ detect_head = self.__head_config[class_name]["class_map"].get(self.__version)
216
+ if detect_head:
217
+ supported = True
218
+ if class_name != "Classify":
219
+ detect_head.dynamic = self.__dynamic
220
+ detect_head.max_det = max_boxes
221
+ detect_head.iou_thres = iou_thres
222
+ detect_head.conf_thres = conf_thres
223
+ m.__class__ = detect_head
224
+ break
225
+
226
+ if not supported:
227
+ logger.error(f"YOLO version '{self.__version}' output head not supported!")
228
+ sys.exit(1)
229
+
230
+ def export(self, output: str, imgsz: Union[int, Sequence[int]], opset_version: int, simplify: bool) -> None:
231
+ from ultralytics.utils.checks import check_imgsz
232
+
233
+ imgsz = check_imgsz(imgsz, stride=self.__model.stride, min_dim=2)
234
+ im = torch.zeros(self.__batch, 3, *imgsz).to(torch.device("cpu"))
235
+
236
+ for p in self.__model.parameters():
237
+ p.requires_grad = False
238
+ self.__model.eval()
239
+ self.__model.float()
240
+
241
+ preds = self.__model(im)
242
+
243
+ output_path = Path(output)
244
+ output_path.mkdir(parents=True, exist_ok=True)
245
+ onnx_path = output_path / (self.__weight_name + ".onnx")
246
+
247
+ torch.onnx.export(
248
+ model=self.__model,
249
+ args=im,
250
+ f=str(onnx_path),
251
+ opset_version=opset_version,
252
+ input_names=['images'],
253
+ output_names=self.__head_config[self.__head_name]["output_names"],
254
+ dynamic_axes=self.__head_config[self.__head_name]["dynamic_axes"] if self.__dynamic else None,
255
+ )
256
+
257
+ onnx_model = onnx.load(onnx_path)
258
+ onnx.checker.check_model(onnx_model)
259
+
260
+ # Update dynamic axes names
261
+ output_shapes = {
262
+ 'num_dets': ["batch" if self.__dynamic else self.__batch, 1],
263
+ 'det_boxes': ["batch" if self.__dynamic else self.__batch, self.__max_boxes, 4],
264
+ 'det_scores': ["batch" if self.__dynamic else self.__batch, self.__max_boxes],
265
+ 'det_classes': ["batch" if self.__dynamic else self.__batch, self.__max_boxes],
266
+ }
267
+
268
+ if self.__head_name == "OBB":
269
+ output_shapes['det_boxes'] = ["batch" if self.__dynamic else self.__batch, self.__max_boxes, 5]
270
+ elif self.__head_name == "Pose":
271
+ output_shapes['det_kpts'] = [
272
+ "batch" if self.__dynamic else self.__batch,
273
+ self.__max_boxes,
274
+ preds[-1].shape[-2],
275
+ preds[-1].shape[-1],
276
+ ]
277
+ elif self.__head_name == "Segment" or self.__head_name == 'YOLOESegment':
278
+ output_shapes['det_masks'] = [
279
+ "batch" if self.__dynamic else self.__batch,
280
+ self.__max_boxes,
281
+ "height" if self.__dynamic else imgsz[0] // 4,
282
+ "width" if self.__dynamic else imgsz[1] // 4,
283
+ ]
284
+ elif self.__head_name == "Classify":
285
+ output_shapes = {'topk': ["batch" if self.__dynamic else self.__batch, preds[-1].shape[1], 2]}
286
+
287
+ for node in onnx_model.graph.output:
288
+ for idx, dim in enumerate(node.type.tensor_type.shape.dim):
289
+ dim.dim_param = str(output_shapes[node.name][idx])
290
+
291
+ if simplify:
292
+ try:
293
+ import onnxsim
294
+
295
+ logger.success(f"Simplifying ONNX model with onnxsim version {onnxsim.__version__}...")
296
+ onnx_model, check = onnxsim.simplify(onnx_model)
297
+ assert check, "Simplified ONNX model could not be validated"
298
+ except ImportError:
299
+ logger.warning('onnxsim not found. Please install onnx-simplifier for example: `pip install onnx-simplifier>=0.4.1`.')
300
+ except Exception as e:
301
+ logger.warning(f"Simplifier failure: {e}")
302
+
303
+ onnx.save(onnx_model, onnx_path)
304
+
305
+ logger.success(f'Export complete, results saved to {output}, visualize at https://netron.app')
306
+
307
+
308
+ def torch_export(
309
+ weights: str,
310
+ output: str,
311
+ version: str,
312
+ imgsz: Optional[Sequence[int]] = [640, 640],
313
+ batch: Optional[int] = 1,
314
+ max_boxes: Optional[int] = 100,
315
+ iou_thres: Optional[float] = 0.45,
316
+ conf_thres: Optional[float] = 0.25,
317
+ opset_version: Optional[int] = 12,
318
+ simplify: Optional[bool] = True,
319
+ repo_dir: Optional[str] = None,
320
+ custom_classes: Optional[Sequence[str]] = None,
321
+ ) -> None:
322
+ """
323
+ Export YOLO model to ONNX format using Torch.
324
+
325
+ Args:
326
+ weights (str): Path to YOLO weights for PyTorch.
327
+ output (str): Directory path to save the exported model.
328
+ version (str): YOLO version, e.g., yolov3, yolov5, yolov8, yolov10, yolo11, yolo12, yolo-world, yoloe, ultralytics.
329
+ imgsz (Optional[Sequence[int]], optional): Inference image size (height, width). Defaults to [640, 640].
330
+ batch (Optional[int], optional): Total batch size for the model. Use -1 for dynamic batch size. Defaults to 1.
331
+ max_boxes (Optional[int], optional): Maximum number of detections to output per image. Defaults to 100.
332
+ iou_thres (Optional[float], optional): NMS IoU threshold for post-processing. Defaults to 0.45.
333
+ conf_thres (Optional[float], optional): Confidence threshold for object detection. Defaults to 0.25.
334
+ opset_version (Optional[int], optional): ONNX opset version. Defaults to 12.
335
+ simplify (Optional[bool], optional): Whether to simplify the exported ONNX. Defaults to True.
336
+ repo_dir (Optional[str], optional): Directory containing the local repository (if using torch.hub.load). Defaults to None.
337
+ custom_classes (Optional[Sequence[str]], optional): Custom class names for the YOLO-World and YOLOE. Defaults to None.
338
+ """
339
+ exporter = ModelExporter()
340
+ exporter.load(weights, version, repo_dir, custom_classes)
341
+ exporter.register(batch, max_boxes, iou_thres, conf_thres)
342
+ exporter.export(output, imgsz, opset_version, simplify)
343
+
344
+
345
+ def paddle_export(
346
+ model_dir: str,
347
+ model_filename: str,
348
+ params_filename: str,
349
+ output: str,
350
+ batch: Optional[int] = 1,
351
+ max_boxes: Optional[int] = 100,
352
+ iou_thres: Optional[float] = 0.45,
353
+ conf_thres: Optional[float] = 0.25,
354
+ opset_version: Optional[int] = 12,
355
+ simplify: Optional[bool] = True,
356
+ ) -> None:
357
+ """
358
+ Export YOLO model to ONNX format using PaddleDetection.
359
+
360
+ Args:
361
+ model_dir (str): Path to the directory containing the PaddleDetection PP-YOLOE model.
362
+ model_filename (str): The filename of the PP-YOLOE model.
363
+ params_filename (str): The filename of the PP-YOLOE parameters.
364
+ output (str): Directory path to save the exported model.
365
+ batch (Optional[int], optional): Total batch size for the model. Use -1 for dynamic batch size. Defaults to 1.
366
+ max_boxes (Optional[int], optional): Maximum number of detections to output per image. Defaults to 100.
367
+ iou_thres (Optional[float], optional): NMS IoU threshold for post-processing. Defaults to 0.45.
368
+ conf_thres (Optional[float], optional): Confidence threshold for object detection. Defaults to 0.25.
369
+ opset_version (Optional[int], optional): ONNX opset version. Defaults to 12.
370
+ simplify (Optional[bool], optional): Whether to simplify the exported ONNX. Defaults to True.
371
+ """
372
+ from .ppyoloe import PPYOLOEGraphSurgeon
373
+
374
+ logger.info("Starting export with PaddlePaddle.")
375
+
376
+ output_path = Path(output)
377
+ output_path.mkdir(parents=True, exist_ok=True)
378
+ onnx_filepath = output_path / (Path(model_filename).stem + ".onnx")
379
+
380
+ ppyoloe_gs = PPYOLOEGraphSurgeon(
381
+ model_dir=model_dir,
382
+ onnx_path=str(onnx_filepath),
383
+ model_filename=model_filename,
384
+ params_filename=params_filename,
385
+ opset=opset_version,
386
+ batch_size=1 if batch <= 0 else batch,
387
+ dynamic=batch <= 0,
388
+ simplify=simplify,
389
+ )
390
+
391
+ # Register the `EfficientNMS_TRT` into the graph.
392
+ ppyoloe_gs.register_nms(score_thresh=conf_thres, nms_thresh=iou_thres, detections_per_img=max_boxes)
393
+
394
+ # Save the exported ONNX models.
395
+ ppyoloe_gs.save(str(onnx_filepath))
396
+
397
+ logger.success(f'Export complete, results saved to {output}, visualize at https://netron.app')
398
+
399
+
400
+ def validate_imgsz(ctx: click.Context, param: click.Parameter, value: str) -> Tuple[int, int]:
401
+ """Validate and parse the imgsz parameter."""
402
+ try:
403
+ if ',' in value:
404
+ h, w = map(int, value.split(','))
405
+ return (h, w)
406
+ size = int(value)
407
+ return (size, size)
408
+ except ValueError:
409
+ raise click.BadParameter('Image size must be in format "size" or "height,width" (e.g., 640 or 640,480)')
410
+
411
+
412
+ def validate_names(ctx: click.Context, param: click.Parameter, value: str) -> Optional[List[str]]:
413
+ """Validate and parse the names parameter."""
414
+ if value is None:
415
+ return None
416
+ return [name.strip() for name in value.split(',')]
417
+
418
+
419
+ def validate_export_params(ctx: click.Context, param: click.Parameter, value: str) -> str:
420
+ """Validate the combination of export parameters."""
421
+ version = ctx.params.get('version')
422
+ model_dir = ctx.params.get('model_dir')
423
+ model_filename = ctx.params.get('model_filename')
424
+ params_filename = ctx.params.get('params_filename')
425
+ weights = ctx.params.get('weights')
426
+
427
+ if version == 'pp-yoloe':
428
+ if not all([model_dir, model_filename, params_filename]):
429
+ raise click.BadParameter('For PP-YOLOE, --model_dir, --model_filename and --params_filename are required')
430
+ elif version and version != 'pp-yoloe':
431
+ if not weights:
432
+ raise click.BadParameter('For non PP-YOLOE models, --weights is required')
433
+
434
+ return value
435
+
436
+
437
+ @click.group()
438
+ def trtyolo():
439
+ """Command line tool for exporting models and performing inference with TensorRT-YOLO."""
440
+ pass
441
+
442
+
443
+ @trtyolo.command(
444
+ help="Export YOLO models to ONNX format compatible with TensorRT-YOLO. "
445
+ "Supports YOLOv3, YOLOv5, YOLOv8, YOLOv10, YOLO11, YOLO12, YOLO-World, YOLOE, PP-YOLOE, and PP-YOLOE+."
446
+ )
447
+ @click.option(
448
+ '-v',
449
+ '--version',
450
+ help='Model version. Options include yolov3, yolov5, yolov8, yolov10, yolo11, yolo12, yolo-world, yoloe, pp-yoloe, ultralytics.',
451
+ type=str,
452
+ required=True,
453
+ callback=validate_export_params,
454
+ )
455
+ @click.option(
456
+ '-o',
457
+ '--output',
458
+ help='Directory path to save the exported model.',
459
+ type=click.Path(file_okay=False, dir_okay=True, path_type=str),
460
+ required=True,
461
+ )
462
+ @click.option(
463
+ '-w',
464
+ '--weights',
465
+ help='Path to PyTorch YOLO weights (required for non PP-YOLOE models).',
466
+ type=click.Path(exists=True, file_okay=True, dir_okay=False, path_type=str),
467
+ )
468
+ @click.option(
469
+ '--model_dir',
470
+ help='Directory path containing the PaddleDetection PP-YOLOE model (required for PP-YOLOE).',
471
+ type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=str),
472
+ )
473
+ @click.option('--model_filename', help='Filename of the PaddleDetection PP-YOLOE model (required for PP-YOLOE).', type=str)
474
+ @click.option('--params_filename', help='Filename of the PaddleDetection PP-YOLOE parameters (required for PP-YOLOE).', type=str)
475
+ @click.option('-b', '--batch', default=1, help='Total batch size for the model. Use -1 for dynamic batch size. Defaults to 1.', type=int)
476
+ @click.option(
477
+ '--max_boxes',
478
+ default=100,
479
+ help='Maximum number of detections per image (not applicable for classification models). Defaults to 100.',
480
+ type=int,
481
+ )
482
+ @click.option(
483
+ '--iou_thres',
484
+ default=0.45,
485
+ help='NMS IoU threshold for post-processing (not applicable for classification models). Defaults to 0.45.',
486
+ type=float,
487
+ )
488
+ @click.option(
489
+ '--conf_thres',
490
+ default=0.25,
491
+ help='Confidence threshold for object detection (not applicable for classification models). Defaults to 0.25.',
492
+ type=float,
493
+ )
494
+ @click.option(
495
+ '--imgsz',
496
+ default='640',
497
+ help='Image size (single value for square or "height,width"). Defaults to "640" (for non PP-YOLOE models).',
498
+ type=str,
499
+ callback=validate_imgsz,
500
+ )
501
+ @click.option(
502
+ '-n',
503
+ '--names',
504
+ help='Custom class names for YOLO-World and YOLOE (comma-separated, e.g., "person,car,dog"). Only applicable for YOLO-World and YOLOE models.',
505
+ type=str,
506
+ callback=validate_names,
507
+ )
508
+ @click.option(
509
+ '--repo_dir',
510
+ help='Directory containing the local repository (if using torch.hub.load). Only applicable for YOLOv3 and YOLOv5 models.',
511
+ type=str,
512
+ )
513
+ @click.option('--opset', default=12, help='ONNX opset version. Defaults to 12.', type=int)
514
+ @click.option('-s', '--simplify', is_flag=True, help='Whether to simplify the exported ONNX model. Defaults to False.')
515
+ def export(
516
+ version: str,
517
+ output: str,
518
+ weights: Optional[str],
519
+ model_dir: Optional[str],
520
+ model_filename: Optional[str],
521
+ params_filename: Optional[str],
522
+ imgsz: Optional[Tuple[int, int]],
523
+ names: Optional[List[str]],
524
+ repo_dir: Optional[str],
525
+ batch: Optional[int],
526
+ max_boxes: Optional[int],
527
+ iou_thres: Optional[float],
528
+ conf_thres: Optional[float],
529
+ opset: Optional[int],
530
+ simplify: Optional[bool],
531
+ ):
532
+ """Export models for TensorRT-YOLO.
533
+
534
+ This command allows exporting models for both PaddlePaddle and PyTorch frameworks to be used with TensorRT-YOLO.
535
+ """
536
+
537
+ if version == 'pp-yoloe':
538
+ paddle_export(
539
+ model_dir=model_dir,
540
+ model_filename=model_filename,
541
+ params_filename=params_filename,
542
+ batch=batch,
543
+ output=output,
544
+ max_boxes=max_boxes,
545
+ iou_thres=iou_thres,
546
+ conf_thres=conf_thres,
547
+ opset_version=opset,
548
+ simplify=simplify,
549
+ )
550
+ else:
551
+ torch_export(
552
+ weights=weights,
553
+ output=output,
554
+ version=version,
555
+ imgsz=imgsz,
556
+ batch=batch,
557
+ max_boxes=max_boxes,
558
+ iou_thres=iou_thres,
559
+ conf_thres=conf_thres,
560
+ opset_version=opset,
561
+ simplify=simplify,
562
+ repo_dir=repo_dir,
563
+ custom_classes=names,
564
+ )
565
+
566
+ logger.success("Export completed successfully!")
567
+
568
+
569
+ if __name__ == '__main__':
570
+ trtyolo()