mirror of
				https://github.com/THU-MIG/yolov10.git
				synced 2025-11-04 08:56:11 +08:00 
			
		
		
		
	ultralytics 8.1.24 new OpenVINO 2023.3 export updates (#8417)
				
					
				
			Co-authored-by: UltralyticsAssistant <web@ultralytics.com> Co-authored-by: Glenn Jocher <glenn.jocher@ultralytics.com>
This commit is contained in:
		
							parent
							
								
									16a91a9b6b
								
							
						
					
					
						commit
						a7cfd83c5f
					
				@ -98,7 +98,7 @@ dev = [
 | 
				
			|||||||
export = [
 | 
					export = [
 | 
				
			||||||
    "onnx>=1.12.0", # ONNX export
 | 
					    "onnx>=1.12.0", # ONNX export
 | 
				
			||||||
    "coremltools>=7.0; platform_system != 'Windows' and python_version <= '3.11'", # CoreML supported on macOS and Linux
 | 
					    "coremltools>=7.0; platform_system != 'Windows' and python_version <= '3.11'", # CoreML supported on macOS and Linux
 | 
				
			||||||
    "openvino-dev>=2023.0; python_version <= '3.11'", # OpenVINO export
 | 
					    "openvino>=2023.3; python_version <= '3.11'", # OpenVINO export
 | 
				
			||||||
    "tensorflow<=2.13.1; python_version <= '3.11'", # TF bug https://github.com/ultralytics/ultralytics/issues/5161
 | 
					    "tensorflow<=2.13.1; python_version <= '3.11'", # TF bug https://github.com/ultralytics/ultralytics/issues/5161
 | 
				
			||||||
    "tensorflowjs>=3.9.0; python_version <= '3.11'", # TF.js export, automatically installs tensorflow
 | 
					    "tensorflowjs>=3.9.0; python_version <= '3.11'", # TF.js export, automatically installs tensorflow
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
				
			|||||||
@ -29,7 +29,7 @@ from ultralytics.utils import (
 | 
				
			|||||||
    is_dir_writeable,
 | 
					    is_dir_writeable,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
from ultralytics.utils.downloads import download
 | 
					from ultralytics.utils.downloads import download
 | 
				
			||||||
from ultralytics.utils.torch_utils import TORCH_1_9
 | 
					from ultralytics.utils.torch_utils import TORCH_1_9, TORCH_1_13
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MODEL = WEIGHTS_DIR / "path with spaces" / "yolov8n.pt"  # test spaces in path
 | 
					MODEL = WEIGHTS_DIR / "path with spaces" / "yolov8n.pt"  # test spaces in path
 | 
				
			||||||
CFG = "yolov8n.yaml"
 | 
					CFG = "yolov8n.yaml"
 | 
				
			||||||
@ -219,6 +219,7 @@ def test_export_onnx():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(checks.IS_PYTHON_3_12, reason="OpenVINO not supported in Python 3.12")
 | 
					@pytest.mark.skipif(checks.IS_PYTHON_3_12, reason="OpenVINO not supported in Python 3.12")
 | 
				
			||||||
 | 
					@pytest.mark.skipif(not TORCH_1_13, reason="OpenVINO requires torch>=1.13")
 | 
				
			||||||
def test_export_openvino():
 | 
					def test_export_openvino():
 | 
				
			||||||
    """Test exporting the YOLO model to OpenVINO format."""
 | 
					    """Test exporting the YOLO model to OpenVINO format."""
 | 
				
			||||||
    f = YOLO(MODEL).export(format="openvino")
 | 
					    f = YOLO(MODEL).export(format="openvino")
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
# Ultralytics YOLO 🚀, AGPL-3.0 license
 | 
					# Ultralytics YOLO 🚀, AGPL-3.0 license
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__version__ = "8.1.23"
 | 
					__version__ = "8.1.24"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ultralytics.data.explorer.explorer import Explorer
 | 
					from ultralytics.data.explorer.explorer import Explorer
 | 
				
			||||||
from ultralytics.models import RTDETR, SAM, YOLO, YOLOWorld
 | 
					from ultralytics.models import RTDETR, SAM, YOLO, YOLOWorld
 | 
				
			||||||
 | 
				
			|||||||
@ -87,7 +87,7 @@ from ultralytics.utils.checks import PYTHON_VERSION, check_imgsz, check_is_path_
 | 
				
			|||||||
from ultralytics.utils.downloads import attempt_download_asset, get_github_assets
 | 
					from ultralytics.utils.downloads import attempt_download_asset, get_github_assets
 | 
				
			||||||
from ultralytics.utils.files import file_size, spaces_in_path
 | 
					from ultralytics.utils.files import file_size, spaces_in_path
 | 
				
			||||||
from ultralytics.utils.ops import Profile
 | 
					from ultralytics.utils.ops import Profile
 | 
				
			||||||
from ultralytics.utils.torch_utils import get_latest_opset, select_device, smart_inference_mode
 | 
					from ultralytics.utils.torch_utils import TORCH_1_13, get_latest_opset, select_device, smart_inference_mode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def export_formats():
 | 
					def export_formats():
 | 
				
			||||||
@ -283,7 +283,7 @@ class Exporter:
 | 
				
			|||||||
            f[0], _ = self.export_torchscript()
 | 
					            f[0], _ = self.export_torchscript()
 | 
				
			||||||
        if engine:  # TensorRT required before ONNX
 | 
					        if engine:  # TensorRT required before ONNX
 | 
				
			||||||
            f[1], _ = self.export_engine()
 | 
					            f[1], _ = self.export_engine()
 | 
				
			||||||
        if onnx or xml:  # OpenVINO requires ONNX
 | 
					        if onnx:  # ONNX
 | 
				
			||||||
            f[2], _ = self.export_onnx()
 | 
					            f[2], _ = self.export_onnx()
 | 
				
			||||||
        if xml:  # OpenVINO
 | 
					        if xml:  # OpenVINO
 | 
				
			||||||
            f[3], _ = self.export_openvino()
 | 
					            f[3], _ = self.export_openvino()
 | 
				
			||||||
@ -411,16 +411,16 @@ class Exporter:
 | 
				
			|||||||
    @try_export
 | 
					    @try_export
 | 
				
			||||||
    def export_openvino(self, prefix=colorstr("OpenVINO:")):
 | 
					    def export_openvino(self, prefix=colorstr("OpenVINO:")):
 | 
				
			||||||
        """YOLOv8 OpenVINO export."""
 | 
					        """YOLOv8 OpenVINO export."""
 | 
				
			||||||
        check_requirements("openvino-dev>=2023.0")  # requires openvino-dev: https://pypi.org/project/openvino-dev/
 | 
					        check_requirements("openvino>=2023.3")  # requires openvino: https://pypi.org/project/openvino-dev/
 | 
				
			||||||
        import openvino.runtime as ov  # noqa
 | 
					        import openvino as ov  # noqa
 | 
				
			||||||
        from openvino.tools import mo  # noqa
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        LOGGER.info(f"\n{prefix} starting export with openvino {ov.__version__}...")
 | 
					        LOGGER.info(f"\n{prefix} starting export with openvino {ov.__version__}...")
 | 
				
			||||||
        f = str(self.file).replace(self.file.suffix, f"_openvino_model{os.sep}")
 | 
					        assert TORCH_1_13, f"OpenVINO export requires torch>=1.13.0 but torch=={torch.__version__} is installed"
 | 
				
			||||||
        fq = str(self.file).replace(self.file.suffix, f"_int8_openvino_model{os.sep}")
 | 
					        ov_model = ov.convert_model(
 | 
				
			||||||
        f_onnx = self.file.with_suffix(".onnx")
 | 
					            self.model.cpu(),
 | 
				
			||||||
        f_ov = str(Path(f) / self.file.with_suffix(".xml").name)
 | 
					            input=None if self.args.dynamic else [self.im.shape],
 | 
				
			||||||
        fq_ov = str(Path(fq) / self.file.with_suffix(".xml").name)
 | 
					            example_input=self.im,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def serialize(ov_model, file):
 | 
					        def serialize(ov_model, file):
 | 
				
			||||||
            """Set RT info, serialize and save metadata YAML."""
 | 
					            """Set RT info, serialize and save metadata YAML."""
 | 
				
			||||||
@ -433,21 +433,19 @@ class Exporter:
 | 
				
			|||||||
            if self.model.task != "classify":
 | 
					            if self.model.task != "classify":
 | 
				
			||||||
                ov_model.set_rt_info("fit_to_window_letterbox", ["model_info", "resize_type"])
 | 
					                ov_model.set_rt_info("fit_to_window_letterbox", ["model_info", "resize_type"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ov.serialize(ov_model, file)  # save
 | 
					            ov.save_model(ov_model, file, compress_to_fp16=self.args.half)
 | 
				
			||||||
            yaml_save(Path(file).parent / "metadata.yaml", self.metadata)  # add metadata.yaml
 | 
					            yaml_save(Path(file).parent / "metadata.yaml", self.metadata)  # add metadata.yaml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ov_model = mo.convert_model(
 | 
					 | 
				
			||||||
            f_onnx, model_name=self.pretty_name, framework="onnx", compress_to_fp16=self.args.half
 | 
					 | 
				
			||||||
        )  # export
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if self.args.int8:
 | 
					        if self.args.int8:
 | 
				
			||||||
 | 
					            fq = str(self.file).replace(self.file.suffix, f"_int8_openvino_model{os.sep}")
 | 
				
			||||||
 | 
					            fq_ov = str(Path(fq) / self.file.with_suffix(".xml").name)
 | 
				
			||||||
            if not self.args.data:
 | 
					            if not self.args.data:
 | 
				
			||||||
                self.args.data = DEFAULT_CFG.data or "coco128.yaml"
 | 
					                self.args.data = DEFAULT_CFG.data or "coco128.yaml"
 | 
				
			||||||
                LOGGER.warning(
 | 
					                LOGGER.warning(
 | 
				
			||||||
                    f"{prefix} WARNING ⚠️ INT8 export requires a missing 'data' arg for calibration. "
 | 
					                    f"{prefix} WARNING ⚠️ INT8 export requires a missing 'data' arg for calibration. "
 | 
				
			||||||
                    f"Using default 'data={self.args.data}'."
 | 
					                    f"Using default 'data={self.args.data}'."
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            check_requirements("nncf>=2.5.0")
 | 
					            check_requirements("nncf>=2.8.0")
 | 
				
			||||||
            import nncf
 | 
					            import nncf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            def transform_fn(data_item):
 | 
					            def transform_fn(data_item):
 | 
				
			||||||
@ -466,6 +464,7 @@ class Exporter:
 | 
				
			|||||||
            if n < 300:
 | 
					            if n < 300:
 | 
				
			||||||
                LOGGER.warning(f"{prefix} WARNING ⚠️ >300 images recommended for INT8 calibration, found {n} images.")
 | 
					                LOGGER.warning(f"{prefix} WARNING ⚠️ >300 images recommended for INT8 calibration, found {n} images.")
 | 
				
			||||||
            quantization_dataset = nncf.Dataset(dataset, transform_fn)
 | 
					            quantization_dataset = nncf.Dataset(dataset, transform_fn)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ignored_scope = None
 | 
					            ignored_scope = None
 | 
				
			||||||
            if isinstance(self.model.model[-1], Detect):
 | 
					            if isinstance(self.model.model[-1], Detect):
 | 
				
			||||||
                # Includes all Detect subclasses like Segment, Pose, OBB, WorldDetect
 | 
					                # Includes all Detect subclasses like Segment, Pose, OBB, WorldDetect
 | 
				
			||||||
@ -473,20 +472,24 @@ class Exporter:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                ignored_scope = nncf.IgnoredScope(  # ignore operations
 | 
					                ignored_scope = nncf.IgnoredScope(  # ignore operations
 | 
				
			||||||
                    patterns=[
 | 
					                    patterns=[
 | 
				
			||||||
                        f"/{head_module_name}/Add",
 | 
					                        f".*{head_module_name}/.*/Add",
 | 
				
			||||||
                        f"/{head_module_name}/Sub",
 | 
					                        f".*{head_module_name}/.*/Sub*",
 | 
				
			||||||
                        f"/{head_module_name}/Mul",
 | 
					                        f".*{head_module_name}/.*/Mul*",
 | 
				
			||||||
                        f"/{head_module_name}/Div",
 | 
					                        f".*{head_module_name}/.*/Div*",
 | 
				
			||||||
                        f"/{head_module_name}/dfl",
 | 
					                        f".*{head_module_name}\\.dfl.*",
 | 
				
			||||||
                    ],
 | 
					                    ],
 | 
				
			||||||
                    names=[f"/{head_module_name}/Sigmoid"],
 | 
					                    types=["Sigmoid"],
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            quantized_ov_model = nncf.quantize(
 | 
					            quantized_ov_model = nncf.quantize(
 | 
				
			||||||
                ov_model, quantization_dataset, preset=nncf.QuantizationPreset.MIXED, ignored_scope=ignored_scope
 | 
					                ov_model, quantization_dataset, preset=nncf.QuantizationPreset.MIXED, ignored_scope=ignored_scope
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            serialize(quantized_ov_model, fq_ov)
 | 
					            serialize(quantized_ov_model, fq_ov)
 | 
				
			||||||
            return fq, None
 | 
					            return fq, None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        f = str(self.file).replace(self.file.suffix, f"_openvino_model{os.sep}")
 | 
				
			||||||
 | 
					        f_ov = str(Path(f) / self.file.with_suffix(".xml").name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        serialize(ov_model, f_ov)
 | 
					        serialize(ov_model, f_ov)
 | 
				
			||||||
        return f, None
 | 
					        return f, None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -180,17 +180,17 @@ class AutoBackend(nn.Module):
 | 
				
			|||||||
            metadata = session.get_modelmeta().custom_metadata_map  # metadata
 | 
					            metadata = session.get_modelmeta().custom_metadata_map  # metadata
 | 
				
			||||||
        elif xml:  # OpenVINO
 | 
					        elif xml:  # OpenVINO
 | 
				
			||||||
            LOGGER.info(f"Loading {w} for OpenVINO inference...")
 | 
					            LOGGER.info(f"Loading {w} for OpenVINO inference...")
 | 
				
			||||||
            check_requirements("openvino>=2023.0")  # requires openvino-dev: https://pypi.org/project/openvino-dev/
 | 
					            check_requirements("openvino>=2023.3")  # requires openvino: https://pypi.org/project/openvino-dev/
 | 
				
			||||||
            from openvino.runtime import Core, Layout, get_batch  # noqa
 | 
					            import openvino as ov  # noqa
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            core = Core()
 | 
					            core = ov.Core()
 | 
				
			||||||
            w = Path(w)
 | 
					            w = Path(w)
 | 
				
			||||||
            if not w.is_file():  # if not *.xml
 | 
					            if not w.is_file():  # if not *.xml
 | 
				
			||||||
                w = next(w.glob("*.xml"))  # get *.xml file from *_openvino_model dir
 | 
					                w = next(w.glob("*.xml"))  # get *.xml file from *_openvino_model dir
 | 
				
			||||||
            ov_model = core.read_model(model=str(w), weights=w.with_suffix(".bin"))
 | 
					            ov_model = core.read_model(model=str(w), weights=w.with_suffix(".bin"))
 | 
				
			||||||
            if ov_model.get_parameters()[0].get_layout().empty:
 | 
					            if ov_model.get_parameters()[0].get_layout().empty:
 | 
				
			||||||
                ov_model.get_parameters()[0].set_layout(Layout("NCHW"))
 | 
					                ov_model.get_parameters()[0].set_layout(ov.Layout("NCHW"))
 | 
				
			||||||
            batch_dim = get_batch(ov_model)
 | 
					            batch_dim = ov.get_batch(ov_model)
 | 
				
			||||||
            if batch_dim.is_static:
 | 
					            if batch_dim.is_static:
 | 
				
			||||||
                batch_size = batch_dim.get_length()
 | 
					                batch_size = batch_dim.get_length()
 | 
				
			||||||
            ov_compiled_model = core.compile_model(ov_model, device_name="AUTO")  # AUTO selects best available device
 | 
					            ov_compiled_model = core.compile_model(ov_model, device_name="AUTO")  # AUTO selects best available device
 | 
				
			||||||
 | 
				
			|||||||
@ -25,6 +25,7 @@ except ImportError:
 | 
				
			|||||||
    thop = None
 | 
					    thop = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TORCH_1_9 = check_version(torch.__version__, "1.9.0")
 | 
					TORCH_1_9 = check_version(torch.__version__, "1.9.0")
 | 
				
			||||||
 | 
					TORCH_1_13 = check_version(torch.__version__, "1.13.0")
 | 
				
			||||||
TORCH_2_0 = check_version(torch.__version__, "2.0.0")
 | 
					TORCH_2_0 = check_version(torch.__version__, "2.0.0")
 | 
				
			||||||
TORCHVISION_0_10 = check_version(torchvision.__version__, "0.10.0")
 | 
					TORCHVISION_0_10 = check_version(torchvision.__version__, "0.10.0")
 | 
				
			||||||
TORCHVISION_0_11 = check_version(torchvision.__version__, "0.11.0")
 | 
					TORCHVISION_0_11 = check_version(torchvision.__version__, "0.11.0")
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user