18 from typing
import Optional, List, Set
26 from ..base_converter
import BaseConverter
27 from ...annotation
import CoretexImageAnnotation, CoretexSegmentationInstance, BBox
33 def isFloat(value: str) -> bool:
41 class YoloConverter(BaseConverter):
43 def __init__(self, datasetName: str, projectId: int, datasetPath: str) ->
None:
44 super().__init__(datasetName, projectId, datasetPath)
46 self.__imagesPath = os.path.join(datasetPath,
"images")
47 self.__annotations = os.path.join(datasetPath,
"annotations")
49 classesPath = os.path.join(self.__annotations,
"classes.txt")
50 if not os.path.exists(classesPath):
51 raise FileNotFoundError(
">> [Coretex] classes.txt file not found")
53 with open(classesPath,
'r')
as f:
55 self.__rawLabels = text.split(
"\n")
56 self.__rawLabels = [label
for label
in self.__rawLabels
if label]
58 def _dataSource(self) -> List[str]:
59 return os.listdir(self.__annotations)
61 def _extractLabels(self) -> Set[str]:
62 return set(self.__rawLabels)
64 def __extractBBox(self, rawInstance: List[str], width: int, height: int) -> BBox:
65 xYolo = float(rawInstance[1])
66 yYolo = float(rawInstance[2])
67 wYolo = float(rawInstance[3])
68 hYolo = float(rawInstance[4])
70 boxWidth = int(wYolo * width)
71 boxHeight = int(hYolo * height)
72 xMin = int(xYolo * width - (boxWidth / 2))
73 yMin = int(yYolo * height - (boxHeight / 2))
75 return BBox(xMin, yMin, boxWidth, boxHeight)
77 def __extractInstance(self, rawInstance: List[str], width: int, height: int) -> Optional[CoretexSegmentationInstance]:
79 labelId = int(rawInstance[0])
80 label = self.__rawLabels[labelId]
82 coretexClass = self._dataset.classByName(label)
83 if coretexClass
is None:
84 logging.getLogger(
"coretexpylib").info(f
">> [Coretex] Class: ({label}) is not a part of dataset")
87 bbox = self.__extractBBox(rawInstance, width, height)
88 return CoretexSegmentationInstance.create( coretexClass.classIds[0], bbox, [bbox.polygon])
90 def _extractSingleAnnotation(self, yoloFilePath: str) ->
None:
91 if not yoloFilePath.endswith(
"txt"):
94 if os.path.splitext(yoloFilePath)[0] ==
"classes":
97 yoloFilePath = os.path.join(self.__annotations, yoloFilePath)
98 yoloName = os.path.basename(yoloFilePath)
100 imagePath = self.imageCheck(os.path.join(self.__imagesPath, yoloName))
101 if imagePath
is not None:
102 imageName = os.path.basename(imagePath)
104 baseImageName = os.path.splitext(imageName)[0]
105 baseYoloName = os.path.splitext(yoloName)[0]
107 if baseImageName != baseYoloName:
110 with open(yoloFilePath,
'r')
as file:
111 allLines = file.readlines()
113 if imagePath
is None:
114 raise RuntimeError(f
"Image at path {imagePath} doesn't exist.")
116 image = Image.open(imagePath)
117 coretexAnnotation = CoretexImageAnnotation.create(imageName, image.width, image.height, [])
120 for line
in allLines:
121 yoloArray = re.split(
"\s", line.rstrip())
122 isFormatCorrect = YoloConverter.formatCheck(yoloArray)
124 if not isFormatCorrect:
127 instance = self.__extractInstance(yoloArray, image.width, image.height)
131 coretexAnnotation.instances.append(instance)
133 self._saveImageAnnotationPair(os.path.join(self.__imagesPath, imageName), coretexAnnotation)
136 def imageCheck(yoloFilePath: str) -> Optional[str]:
137 if os.path.exists(yoloFilePath.replace(
'txt',
'jpeg')):
138 return yoloFilePath.replace(
'txt',
'jpeg')
139 if os.path.exists(yoloFilePath.replace(
'txt',
'jpg')):
140 return yoloFilePath.replace(
'txt',
'jpg')
141 if os.path.exists(yoloFilePath.replace(
'txt',
'png')):
142 return yoloFilePath.replace(
'txt',
'png')
147 def formatCheck(yoloArray: List[str]) -> bool:
149 Checks format of yolo annotation file
153 yoloArray : List[str]
154 list with label id and bounding boxes
158 bool -> True if format is correct, False if format is not correct
161 if len(yoloArray) != 5:
164 for value
in yoloArray:
165 if not Helper.isFloat(value):