Coretex
label_me_converter.py
1 # Copyright (C) 2023 Coretex LLC
2 
3 # This file is part of Coretex.ai
4 
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License as
7 # published by the Free Software Foundation, either version 3 of the
8 # License, or (at your option) any later version.
9 
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU Affero General Public License for more details.
14 
15 # You should have received a copy of the GNU Affero General Public License
16 # along with this program. If not, see <https://www.gnu.org/licenses/>.
17 
18 from typing import Any, Optional, List, Set, Dict
19 from pathlib import Path
20 
21 import os
22 import json
23 import glob
24 import logging
25 
26 import numpy as np
27 
28 from ..base_converter import BaseConverter
29 from ...annotation import CoretexImageAnnotation, CoretexSegmentationInstance, BBox
30 
31 
32 class LabelMeConverter(BaseConverter):
33 
34  def __init__(self, datasetName: str, projectId: int, datasetPath: str) -> None:
35  super().__init__(datasetName, projectId, datasetPath)
36 
37  self.__imagesPath = os.path.join(datasetPath, "images")
38 
39  annotations = os.path.join(datasetPath, "annotations")
40  self.__fileNames = glob.glob(os.path.join(annotations, "*.json"))
41 
42  def _dataSource(self) -> List[str]:
43  return self.__fileNames
44 
45  def _extractLabels(self) -> Set[str]:
46  labels: Set[str] = set()
47 
48  for fileName in self.__fileNames:
49  with open(fileName) as jsonFile:
50  data = json.load(jsonFile)
51 
52  for shape in data["shapes"]:
53  labels.add(shape["label"])
54 
55  return labels
56 
57  def __extractInstance(self, shape: Dict[str, Any]) -> Optional[CoretexSegmentationInstance]:
58  label = shape["label"]
59 
60  coretexClass = self._dataset.classByName(label)
61  if coretexClass is None:
62  logging.getLogger("coretexpylib").info(f">> [Coretex] Class: ({label}) is not a part of dataset")
63  return None
64 
65  points: List[int] = np.array(shape["points"]).flatten().tolist()
66  bbox = BBox.fromPoly(points)
67 
68  return CoretexSegmentationInstance.create(coretexClass.classIds[0], bbox, [points])
69 
70  def __extractImageAnnotation(self, imageAnnotation: Dict[str, Any]) -> None:
71  imageName = Path(imageAnnotation["imagePath"]).stem
72  imageName = f"{imageName}.jpg"
73 
74  width = imageAnnotation["imageWidth"]
75  height = imageAnnotation["imageHeight"]
76 
77  coretexAnnotation = CoretexImageAnnotation.create(imageName, width, height, [])
78 
79  for shape in imageAnnotation["shapes"]:
80  instance = self.__extractInstance(shape)
81  if instance is None:
82  continue
83 
84  coretexAnnotation.instances.append(instance)
85 
86  self._saveImageAnnotationPair(os.path.join(self.__imagesPath, imageName), coretexAnnotation)
87 
88  def _extractSingleAnnotation(self, fileName: str) -> None:
89  with open(fileName) as jsonFile:
90  data = json.load(jsonFile)
91  self.__extractImageAnnotation(data)