From 9f06c39be18ee43079d8b084ee4ddf6485bb3d36 Mon Sep 17 00:00:00 2001 From: Ryan Folks Date: Wed, 18 Jun 2025 15:53:08 -0400 Subject: [PATCH 1/8] Change the model metadata files from yaml to json. --- .../object_detection_models/onnx_yolov11_detection.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ChartExtractor/object_detection_models/onnx_yolov11_detection.py b/ChartExtractor/object_detection_models/onnx_yolov11_detection.py index b46bdb0..b342955 100644 --- a/ChartExtractor/object_detection_models/onnx_yolov11_detection.py +++ b/ChartExtractor/object_detection_models/onnx_yolov11_detection.py @@ -15,6 +15,7 @@ """ # Built-in imports +import json from pathlib import Path from typing import Dict, List, Literal, Tuple @@ -28,7 +29,6 @@ from ..utilities.annotations import BoundingBox from ..utilities.detections import Detection from ..utilities.detection_reassembly import non_maximum_suppression -from ..utilities.read_config import read_yaml_file class OnnxYolov11Detection(ObjectDetectionModel): @@ -86,7 +86,11 @@ def load_classes(model_metadata_filepath: Path) -> Dict: potential_err_msg = "An exception has occured while loading the classes " potential_err_msg += "yaml file. Ensure the model metadata filepath is " potential_err_msg += "correct and the model's yaml file is correctly formatted." - classes: Dict = read_yaml_file(model_metadata_filepath, potential_err_msg) + try: + classes: Dict[str, str] = json.loads(open(model_metadata_filepath, 'r').read()) + except FileNotFoundError as e: + print(potential_err_msg) + print(e) return classes def __call__( From 6b8fce4bbe9452a2cb659abd6a318dfb74cd4be2 Mon Sep 17 00:00:00 2001 From: Ryan Folks Date: Wed, 18 Jun 2025 16:01:58 -0400 Subject: [PATCH 2/8] Change yaml files in extraction.py to the equivalent json files. --- ChartExtractor/extraction/extraction.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ChartExtractor/extraction/extraction.py b/ChartExtractor/extraction/extraction.py index 96b0a2c..2966ce4 100644 --- a/ChartExtractor/extraction/extraction.py +++ b/ChartExtractor/extraction/extraction.py @@ -68,37 +68,37 @@ MODEL_CONFIG: Dict = read_config() INTRAOP_DOC_MODEL = OnnxYolov11Detection( PATH_TO_MODELS / MODEL_CONFIG["intraoperative_document_landmarks"]["name"], - PATH_TO_MODEL_METADATA / MODEL_CONFIG["intraoperative_document_landmarks"]["name"].replace(".onnx", ".yaml") + PATH_TO_MODEL_METADATA / MODEL_CONFIG["intraoperative_document_landmarks"]["name"].replace(".onnx", ".json") ) PREOP_POSTOP_DOC_MODEL = OnnxYolov11Detection( PATH_TO_MODELS / MODEL_CONFIG["preop_postop_document_landmarks"]["name"], - PATH_TO_MODEL_METADATA / MODEL_CONFIG["preop_postop_document_landmarks"]["name"].replace(".onnx", ".yaml"), + PATH_TO_MODEL_METADATA / MODEL_CONFIG["preop_postop_document_landmarks"]["name"].replace(".onnx", ".json"), ) NUMBERS_MODEL = OnnxYolov11Detection( PATH_TO_MODELS / MODEL_CONFIG["numbers"]["name"], - PATH_TO_MODEL_METADATA / MODEL_CONFIG["numbers"]["name"].replace(".onnx", ".yaml") + PATH_TO_MODEL_METADATA / MODEL_CONFIG["numbers"]["name"].replace(".onnx", ".json") ) SYSTOLIC_MODEL = OnnxYolov11PoseSingle( PATH_TO_MODELS / MODEL_CONFIG["systolic"]["name"], - PATH_TO_MODEL_METADATA / MODEL_CONFIG["systolic"]["name"].replace(".onnx", ".yaml"), + PATH_TO_MODEL_METADATA / MODEL_CONFIG["systolic"]["name"].replace(".onnx", ".json"), 608, 608, ) DIASTOLIC_MODEL = OnnxYolov11PoseSingle( PATH_TO_MODELS / MODEL_CONFIG["diastolic"]["name"], - PATH_TO_MODEL_METADATA / MODEL_CONFIG["diastolic"]["name"].replace(".onnx", ".yaml"), + PATH_TO_MODEL_METADATA / MODEL_CONFIG["diastolic"]["name"].replace(".onnx", ".json"), 608, 608, ) HEART_RATE_MODEL = OnnxYolov11PoseSingle( PATH_TO_MODELS / MODEL_CONFIG["heart_rate"]["name"], - PATH_TO_MODEL_METADATA / MODEL_CONFIG["heart_rate"]["name"].replace(".onnx", ".yaml"), + PATH_TO_MODEL_METADATA / MODEL_CONFIG["heart_rate"]["name"].replace(".onnx", ".json"), 608, 608, ) CHECKBOXES_MODEL = OnnxYolov11Detection( PATH_TO_MODELS / MODEL_CONFIG["checkboxes"]["name"], - PATH_TO_MODEL_METADATA / MODEL_CONFIG["checkboxes"]["name"].replace(".onnx", ".yaml"), + PATH_TO_MODEL_METADATA / MODEL_CONFIG["checkboxes"]["name"].replace(".onnx", ".json"), ) From 218f106d11cb16ca0be7bb257d9ddac52f0cddac Mon Sep 17 00:00:00 2001 From: Ryan Folks Date: Wed, 18 Jun 2025 16:05:00 -0400 Subject: [PATCH 3/8] Switch the yaml config file in extraction.py to the json version. --- ChartExtractor/extraction/extraction.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChartExtractor/extraction/extraction.py b/ChartExtractor/extraction/extraction.py index 2966ce4..2de2bec 100644 --- a/ChartExtractor/extraction/extraction.py +++ b/ChartExtractor/extraction/extraction.py @@ -2,6 +2,7 @@ # Built-in imports from functools import partial, reduce +import json from operator import concat import os from pathlib import Path @@ -55,7 +56,6 @@ non_maximum_suppression, ) from ..utilities.image_conversion import pil_to_cv2 -from ..utilities.read_config import read_config from ..utilities.tiling import tile_image # External Imports @@ -65,7 +65,7 @@ PATH_TO_DATA: Path = (Path(os.path.dirname(__file__)) / ".." / ".." / "data").resolve() PATH_TO_MODELS: Path = PATH_TO_DATA / "models" PATH_TO_MODEL_METADATA = PATH_TO_DATA / "model_metadata" -MODEL_CONFIG: Dict = read_config() +MODEL_CONFIG: Dict = json.loads(open(str(PATH_TO_DATA/"config.json"), 'r').read()) INTRAOP_DOC_MODEL = OnnxYolov11Detection( PATH_TO_MODELS / MODEL_CONFIG["intraoperative_document_landmarks"]["name"], PATH_TO_MODEL_METADATA / MODEL_CONFIG["intraoperative_document_landmarks"]["name"].replace(".onnx", ".json") From 2563a05ce9850a596ad84ca3f5bd9b44bb9c776f Mon Sep 17 00:00:00 2001 From: Ryan Folks Date: Wed, 18 Jun 2025 16:06:02 -0400 Subject: [PATCH 4/8] Remove read_config.py. --- ChartExtractor/utilities/read_config.py | 50 ------------------------- 1 file changed, 50 deletions(-) delete mode 100644 ChartExtractor/utilities/read_config.py diff --git a/ChartExtractor/utilities/read_config.py b/ChartExtractor/utilities/read_config.py deleted file mode 100644 index 66b89f1..0000000 --- a/ChartExtractor/utilities/read_config.py +++ /dev/null @@ -1,50 +0,0 @@ -"""Reads the object detection model config yaml file.""" - -# Built-in Imports -from pathlib import Path -import sys -from typing import Dict - -# External Imports -import yaml - - -def read_config() -> Dict: - """Reads the object detection model config yaml file. - - Returns: - A dictionary mapping constant names to file names of model weights - and the tile size proportion that the model was trained on. - """ - config_path: Path = (Path(__file__) / ".." / ".." / ".." / "config.yaml").resolve() - potential_err_msg = "An exception has occured, ensure that config.yaml is " - potential_err_msg += "correctly formatted and is at the root of the " - potential_err_msg += "ChartExtractor package." - config_data: Dict = read_yaml_file(config_path, potential_err_msg) - return config_data - - -def read_yaml_file(filepath: Path, err_msg: str) -> Dict: - """Reads a yaml file. Raises slightly more helpful exceptions. - - Args: - filepath (Path): - The path to the yaml file. - err_msg (str): - The error message to print before the exception. - - Raises: - Any exception relating to loading and parsing a yaml file. - - Returns: - The data within the yaml file as a dictionary. - """ - try: - data: str = open(filepath, "r").read() - parsed_data: Dict = yaml.safe_load(data) - return parsed_data - except Exception as e: - print(err_msg) - print("Exact exception:") - print(e) - sys.exit() From c6f63813db33f3e9ff0b27fc76368218386ed7c3 Mon Sep 17 00:00:00 2001 From: Ryan Folks Date: Wed, 18 Jun 2025 16:07:46 -0400 Subject: [PATCH 5/8] Replace yaml classes metadata file in onnx_yolov11_pose_single.py with the equivalent json file. --- .../object_detection_models/onnx_yolov11_pose_single.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ChartExtractor/object_detection_models/onnx_yolov11_pose_single.py b/ChartExtractor/object_detection_models/onnx_yolov11_pose_single.py index 362c346..7caddbe 100644 --- a/ChartExtractor/object_detection_models/onnx_yolov11_pose_single.py +++ b/ChartExtractor/object_detection_models/onnx_yolov11_pose_single.py @@ -19,6 +19,7 @@ """ # Built-in imports +import json from pathlib import Path from typing import Dict, List, Literal, Tuple @@ -32,7 +33,6 @@ from ..utilities.annotations import BoundingBox, Keypoint, Point from ..utilities.detections import Detection from ..utilities.detection_reassembly import non_maximum_suppression -from ..utilities.read_config import read_yaml_file class OnnxYolov11PoseSingle(ObjectDetectionModel): @@ -90,7 +90,11 @@ def load_classes(model_metadata_filepath: Path) -> Dict: potential_err_msg = "An exception has occured while loading the classes " potential_err_msg += "yaml file. Ensure the model metadata filepath is " potential_err_msg += "correct and the model's yaml file is correctly formatted." - classes: Dict = read_yaml_file(model_metadata_filepath, potential_err_msg) + try: + classes: Dict[str, str] = json.loads(open(model_metadata_filepath, 'r').read()) + except FileNotFoundError as e: + print(potential_err_msg) + print(e) return classes def __call__( From f7a9729eb24fed1dc9d213fb3aeec43e0583d9c4 Mon Sep 17 00:00:00 2001 From: Ryan Folks Date: Wed, 18 Jun 2025 16:15:11 -0400 Subject: [PATCH 6/8] change the name of the model metadata to model classes. This more clearly explains what theis file is for. --- .../object_detection_models/onnx_yolov11_detection.py | 8 ++++---- .../object_detection_models/onnx_yolov11_pose_single.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ChartExtractor/object_detection_models/onnx_yolov11_detection.py b/ChartExtractor/object_detection_models/onnx_yolov11_detection.py index b342955..0664083 100644 --- a/ChartExtractor/object_detection_models/onnx_yolov11_detection.py +++ b/ChartExtractor/object_detection_models/onnx_yolov11_detection.py @@ -45,7 +45,7 @@ class OnnxYolov11Detection(ObjectDetectionModel): def __init__( self, model_weights_filepath: Path, - model_metadata_filepath: Path, + model_classes_filepath: Path, input_im_width: int = 640, input_im_height: int = 640, ): @@ -54,8 +54,8 @@ def __init__( Args: model_weights_filepath (Path): The filepath to the model's weights. - model_metadata_filepath (Path): - The filepath to the metadata (for class names). + model_classes_filepath (Path): + The filepath to a json file with all the classes. input_im_width (int): The image width that the model accepts. Defaults to 640. @@ -66,7 +66,7 @@ def __init__( self.model = ort.InferenceSession(model_weights_filepath) self.input_im_width = input_im_width self.input_im_height = input_im_height - self.classes = self.load_classes(model_metadata_filepath) + self.classes = self.load_classes(model_classes_filepath) @staticmethod def load_classes(model_metadata_filepath: Path) -> Dict: diff --git a/ChartExtractor/object_detection_models/onnx_yolov11_pose_single.py b/ChartExtractor/object_detection_models/onnx_yolov11_pose_single.py index 7caddbe..d9777e9 100644 --- a/ChartExtractor/object_detection_models/onnx_yolov11_pose_single.py +++ b/ChartExtractor/object_detection_models/onnx_yolov11_pose_single.py @@ -49,7 +49,7 @@ class OnnxYolov11PoseSingle(ObjectDetectionModel): def __init__( self, model_weights_filepath: Path, - model_metadata_filepath: Path, + model_classes_filepath: Path, input_im_width: int = 640, input_im_height: int = 640, ): @@ -58,8 +58,8 @@ def __init__( Args: model_weights_filepath (Path): The filepath to the model's weights. - model_metadata_filepath (Path): - The filepath to the metadata (for class names). + model_classes_filepath (Path): + The filepath to a json file with all the classes. input_im_width (int): The image width that the model accepts. Defaults to 640. @@ -70,7 +70,7 @@ def __init__( self.model = ort.InferenceSession(model_weights_filepath) self.input_im_width = input_im_width self.input_im_height = input_im_height - self.classes = self.load_classes(model_metadata_filepath) + self.classes = self.load_classes(model_classes_filepath) @staticmethod def load_classes(model_metadata_filepath: Path) -> Dict: From 5515869983c8eff08b9f63289369d4af07cdf548 Mon Sep 17 00:00:00 2001 From: Ryan Folks Date: Wed, 18 Jun 2025 16:20:28 -0400 Subject: [PATCH 7/8] Moved config.yaml to the data folder. --- config.yaml | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 config.yaml diff --git a/config.yaml b/config.yaml deleted file mode 100644 index 1a59d72..0000000 --- a/config.yaml +++ /dev/null @@ -1,35 +0,0 @@ -intraoperative_document_landmarks: - name: intraop_doc_landmark_detector.onnx - tile_size_proportion: 0.3 - horz_overlap_proportion: 0.2 - vert_overlap_proportion: 0.2 -preop_postop_document_landmarks: - name: preop_postop_doc_landmark_detector.onnx - tile_size_proportion: 0.3 - horz_overlap_proportion: 0.2 - vert_overlap_proportion: 0.2 -numbers: - name: digits.onnx - tile_size_proportion: 0.3 - horz_overlap_proportion: 0.2 - vert_overlap_proportion: 0.2 -systolic: - name: sys_yolov11m_pose_best_no_transfer.onnx - tile_size_proportion: 0.2 - horz_overlap_proportion: 0.2 - vert_overlap_proportion: 0.2 -diastolic: - name: dia_yolov11m_pose_best_no_transfer.onnx - tile_size_proportion: 0.2 - horz_overlap_proportion: 0.2 - vert_overlap_proportion: 0.2 -heart_rate: - name: hr_yolov11m_pose_best_no_transfer.onnx - tile_size_proportion: 0.2 - horz_overlap_proportion: 0.2 - vert_overlap_proportion: 0.2 -checkboxes: - name: checkboxes.onnx - tile_size_proportion: 0.2 - horz_overlap_proportion: 0.2 - vert_overlap_proportion: 0.2 From c969ddec42df61e7492e8be1cdd6d4fc99cc3e70 Mon Sep 17 00:00:00 2001 From: Ryan Folks Date: Wed, 18 Jun 2025 16:23:09 -0400 Subject: [PATCH 8/8] Remove pyyaml from the pyproject.toml file. --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2d1b3ec..ff75434 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,6 @@ opencv-python-headless = "^4.10.0.84" numpy = "^2.1.2" pillow = "^10.4.0" scikit-learn = "^1.5.2" -pyyaml = "^6.0.2" onnxruntime = "^1.20.1" [tool.poetry.group.dev.dependencies]