diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..2c1aa481 --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +build: + pipreqs ./ --force + +test: + pip3 install -r dev_env/requirements.txt + pytest --pylint --mypy --doctest-modules + +format: + isort -y + black icarebot + +dep: + pip3 install -r requirements.txt diff --git a/__init__.py b/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/base/__init__.py b/base/__init__.py new file mode 100644 index 00000000..9fe7f3b0 --- /dev/null +++ b/base/__init__.py @@ -0,0 +1,3 @@ +from base.base_reader import * +from base.base_parser import * + diff --git a/base/base_parser.py b/base/base_parser.py new file mode 100644 index 00000000..e22f61c2 --- /dev/null +++ b/base/base_parser.py @@ -0,0 +1,35 @@ +import logging +import json + + +class Parser: + + ALLOW_EXTENSION = 'json' + + def __init__(self, proto_path: str): + self.logger: logging.Logger = logging.getLogger(self.__class__.__name__) + self.proto: dict = self._load_proto(proto_path) + + def __call__(self, *args, **kwargs): + raise NotImplementedError + + def _load_proto(self, proto_file_path: str): + self._is_json(proto_file_path) + with open(proto_file_path) as f: + proto = json.load(f) + + return proto + + def _is_json(self, path: str) -> None: + extension: str = path.split(".")[-1].lower() + if extension != "json": + self.logger.debug("Debug: proto file is not json") + raise RuntimeError("file is not json") + +if __name__ == "__main__": + proto_path = "../config/proto.json" + parser = Parser(proto_path) + _proto = parser.proto + print(_proto) + print(type(_proto)) + print(_proto.keys()) diff --git a/base/base_reader.py b/base/base_reader.py new file mode 100644 index 00000000..bf24d78d --- /dev/null +++ b/base/base_reader.py @@ -0,0 +1,13 @@ +import logging + + + +class Reader: + def __init__(self): + self.logger: logging.Logger = logging.getLogger(self.__class__.__name__) + + def __call__(self, *args, **kwargs): + raise NotImplementedError + + def _is_validated_file(self, filename: str) -> bool: + raise NotImplementedError diff --git a/config/proto.json b/config/proto.json new file mode 100644 index 00000000..4f211ea1 --- /dev/null +++ b/config/proto.json @@ -0,0 +1,14 @@ +{ + "image_path": "", + "image_size": [{"width": ""}, + {"height": ""}, + {"channel": ""}], + "object": [{"class": ""}, + {"boundary_box": [{"xmin": ""}, + {"ymin": ""}, + {"xmax": ""}, + {"ymax": ""} + ] + } + ] +} \ No newline at end of file diff --git a/config/xml.json b/config/xml.json new file mode 100644 index 00000000..988cf21b --- /dev/null +++ b/config/xml.json @@ -0,0 +1,51 @@ +{ + "image_path": [{"hierarchy": ["annotation", "path"]}, + {"options": ["single"]}, + {"contents": []}], + + "image_size": [ {"hierarchy": ["annotation", "size"]}, + {"options": ["multi"]}, + + {"contents" : [ + {"width": [{"hierarchy": ["width"]}, + {"options": ["single"]}, + {"contents": []}]}, + + {"height": [{"hierarchy": ["height"]}, + {"options": ["single"]}, + {"contents": []}]}, + + {"channel": [{"hierarchy": ["depth"]}, + {"options": ["single"]}, + {"contents": []}]} + ] + } + ], + + "object": [ {"hierarchy": ["annotation", "object"]}, + {"options": ["multi", "recursive"]}, + {"contents": [ + {"class": [{"hierarchy": ["name"]}, + {"options": ["single"]}, + {"contents": []}]}, + {"boundary_box": [{"hierarchy": ["bndbox"]}, + {"options": ["multi"]}, + {"contents": [ + {"xmin": [{"hierarchy": ["xmin"]}, + {"options": ["single"]}, + {"contents": []}]}, + {"ymin": [{"hierarchy": ["ymin"]}, + {"options": ["single"]}, + {"contents": []}]}, + {"xmax": [{"hierarchy": ["xmax"]}, + {"options": ["single"]}, + {"contents": []}]}, + {"ymax": [{"hierarchy": ["ymax"]}, + {"options": ["single"]}, + {"contents": []}]} + ] + }] + } + ]} + ] +} \ No newline at end of file diff --git a/utils/__init__.py b/utils/__init__.py new file mode 100644 index 00000000..d1d60199 --- /dev/null +++ b/utils/__init__.py @@ -0,0 +1 @@ +from utils.reader import * \ No newline at end of file diff --git a/utils/reader.py b/utils/reader.py new file mode 100644 index 00000000..b28a5b59 --- /dev/null +++ b/utils/reader.py @@ -0,0 +1,49 @@ +import xml.etree.ElementTree as Et +from xml.etree.ElementTree import ElementTree + +from base import base_reader + + +class XmlReader(base_reader.Reader): + + ALLOW_EXTENSION = "xml" + + def __init__(self) -> None: + super(XmlReader, self).__init__() + + def __call__(self, xml_path: str) -> None or ElementTree: + if not self._is_validated_file(xml_path): + return None + + return self._load_xml(xml_path) + + def _is_validated_file(self, filename: str) -> bool: + file_extension: str = filename.split(".")[-1].lower() + + if file_extension == XmlReader.ALLOW_EXTENSION: + return True + + self.logger.warning("Warning: extension of file not supported. " + \ + "this file skip. " + "Supported file extension following : " + \ + "`{}`".format(XmlReader.ALLOW_EXTENSION)) + return False + + @staticmethod + def _load_xml(filepath: str) -> ElementTree: + with open(filepath) as xml: + tree: ElementTree = Et.parse(xml) + + return tree + + +if __name__ == "__main__": + xml_file_path = "../example/voc/label/000001.xml" + wrong_file_path = "../example/voc/label/000001.jpeg" + + xml_reader = XmlReader() + xml_tree = xml_reader(xml_file_path) + print(xml_tree) + + result = xml_reader(wrong_file_path) + print(result) \ No newline at end of file