File size: 4,291 Bytes
0598469 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | #!/usr/bin/env python3
"""Export an Ultralytics checkpoint and its metadata for one Rockchip chip."""
import argparse
import os
from pathlib import Path
import shutil
import tempfile
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("model", help="Checkpoint path or official model name, e.g. yolo11n-seg.pt")
parser.add_argument("--chip", required=True, choices=("rk3576", "rk3588"))
parser.add_argument("--output", required=True, type=Path, help="New output directory")
parser.add_argument("--imgsz", type=int, help="Square input size; defaults depend on the task")
parser.add_argument("--precision", choices=("fp16", "int8", "mixed"), default="fp16")
parser.add_argument("--data", type=Path, help="Calibration YAML, image list, or directory; detection INT8 needs a dataset YAML")
parser.add_argument("--calibration-limit", type=int, default=100,
help="Maximum calibration images for mixed precision (default: 100)")
args = parser.parse_args()
destination = args.output.resolve()
if destination.exists():
parser.error("Output already exists; choose a new directory")
if args.precision != "fp16" and not args.data:
parser.error("Quantization requires --data with representative calibration images")
if args.imgsz and (args.imgsz < 32 or args.imgsz > 4096 or args.imgsz % 32):
parser.error("--imgsz must be a multiple of 32 between 32 and 4096")
if not 1 <= args.calibration_limit <= 10000:
parser.error("--calibration-limit must be between 1 and 10000")
checkpoint = Path(args.model).expanduser()
checkpoint = checkpoint.resolve() if checkpoint.is_file() else None
dataset = args.data.resolve() if args.data else None
# Conversion runs in an existing toolkit environment; do not install packages for the user.
os.environ["YOLO_AUTOINSTALL"] = "false"
from ultralytics import YOLO
from ultralytics.utils import YAML
previous_directory = Path.cwd()
try:
# Exporters write intermediate files beside the checkpoint. Keep the original untouched.
with tempfile.TemporaryDirectory(prefix="nvr-export-") as scratch:
os.chdir(scratch)
if checkpoint:
shutil.copy2(checkpoint, checkpoint.name)
model = YOLO(checkpoint.name if checkpoint else args.model)
size = args.imgsz or {"classify": 224, "semantic": 512, "depth": 384}.get(model.task, 640)
optimized = (args.precision == "mixed" or model.task in {"semantic", "depth"}
or (args.precision == "int8" and model.task != "detect"))
if optimized:
from rknn_export import export_optimized
binary, metadata = export_optimized(
model, args.chip, size, dataset, args.calibration_limit,
args.precision)
else:
settings = dict(format="rknn", name=args.chip, imgsz=size, batch=1,
quantize=8 if args.precision == "int8" else 16,
device="cpu", simplify=True, opset=19)
if dataset:
settings["data"] = str(dataset)
exported = Path(model.export(**settings))
binaries = list(exported.glob("*.rknn"))
if len(binaries) != 1:
raise RuntimeError("Expected one RKNN model in the export directory")
binary = binaries[0]
metadata = YAML.load(exported / "metadata.yaml")
metadata["precision"] = args.precision
metadata["target_platform"] = args.chip
metadata["coordinates"] = ("normalized" if args.precision == "int8"
and model.task == "detect" else "pixels")
metadata["preprocess"] = "center_crop" if model.task == "classify" else "letterbox"
destination.mkdir(parents=True)
shutil.copy2(binary, destination / "model.rknn")
YAML.save(destination / "metadata.yaml", metadata)
finally:
os.chdir(previous_directory)
print(f"Exported {model.task} for {args.chip}: {destination}")
if __name__ == "__main__":
main()
|