import re from collections import OrderedDict from os import path, makedirs, listdir from typing import Callable, Dict, Optional, Tuple, List, Generator, Any, Union import numpy as np import pandas as pd from cv2 import imread, imwrite DIRIN = path.abspath("in") DIROUT = path.abspath("out") DIRCACHE = path.abspath("cache") [makedirs(d, exist_ok=True) for d in [DIRIN, DIROUT, DIRCACHE]] def dslice(odict: Dict[Any, Any], start: Optional[int] = None, end: Optional[int] = None) -> Dict[Any, Any]: return OrderedDict([ (k, odict[k]) for k in list(odict.keys())[start:end] ]) def lval(odict: Dict[Any, Any]) -> Any: return odict[list(odict.keys())[-1]] def summarize(dlist): summary = pd.concat(dlist) summary.sort_values(["Hour", "Culture", "Label", "Grain"], ignore_index=True, inplace=True) return summary class FILE: def __init__(self, fpath: str, esum: Optional[str] = None): self.path, self.fname = path.split(path.relpath(fpath, start=DIRIN)) self.fname, self.fext = path.splitext(self.fname) self.opqueue: Dict[str, Tuple[str, Callable, List[int]]] = OrderedDict() self.meta: Optional[pd.DataFrame] = None self.outlines: Optional[np.ndarray] = None self.load({}) def __repr__(self) -> str: return path.join(self.path, "".join([self.fname, self.fext])) def __gt__(self, other) -> bool: return [int(c) if c.isdigit() else c for c in re.split('([0-9]+)', repr(self))] > \ [int(c) if c.isdigit() else c for c in re.split('([0-9]+)', repr(other))] def apply(self, opts: Dict[str, Tuple[str, Callable, List[int]]]): if self.load(opts): pass else: self.apply(dslice(opts, None, -1)) try: self.data = lval(opts)[0](self.data, *lval(opts)[1], **lval(opts)[2]) if type(self.data) is tuple: self.meta = pd.DataFrame(None if self.data[1]["data"][1:] == [] else self.data[1]["data"][1:], columns=self.data[1]["data"][0]) self.meta.insert(loc=0, column="Label", value="".join([self.fname, self.fext])) spath = self.path.split(path.sep) if len(spath) > 2 and spath[-2][:-1].isdigit(): hour, culture = self.path.split(path.sep)[-2:] hour = int(hour[:-1]) else: hour, culture = None, None self.meta.insert(loc=0, column="Hour", value=hour) self.meta.insert(loc=1, column="Culture", value=culture) self.outlines = self.data[1]["outlines"] self.data = self.data[0] if lval(opts)[3]: self.save(False, opts) except SyntaxError as error: print(f"Error: {error}") def getOpStr(self, opts: Dict[str, Tuple[str, Callable, List[int]]]) -> str: return ';'.join([f"{x}_{','.join([str(y) for y in opts[x][1]])}" for x in opts.keys()]) def getName(self, cache: bool, opts: Dict[str, Tuple[str, Callable, List[int]]]) -> str: return f"{self.fname}{(cache and self.getOpStr(opts) + '.png') or self.fext}" def save(self, toDirOut: bool, opts: Dict[str, Tuple[str, Callable, List[int]]]): if toDirOut: if not path.exists(path.join(DIROUT, self.path)): makedirs(path.join(DIROUT, self.path)) imwrite(path.join(DIROUT, self.path, f"{self.fname}.jpg"), self.data) if self.outlines is not None: imwrite(path.join(DIROUT, self.path, f"{self.fname}.outlines.jpg"), self.outlines) if self.meta is not None: self.meta.to_csv(path.join(DIROUT, self.path, f"{self.fname}.csv"), index=False) else: if not path.exists(path.join(DIRCACHE, self.path)): makedirs(path.join(DIRCACHE, self.path)) imwrite(path.join(DIRCACHE, self.path, self.getName(True, opts)), self.data) def load(self, opts: Dict[str, Tuple[str, Callable, List[int]]]) -> bool: if opts == {} and path.exists(path.join(DIRIN, self.path, self.getName(False, []))): self.data = imread(path.join(DIRIN, self.path, self.getName(False, [])), -1) return True if path.exists(path.join(DIRCACHE, self.path, self.getName(True, opts))): self.data = imread(path.join(DIRCACHE, self.path, self.getName(True, opts)), -1) return True return False def search(pathlist: List[str]) -> Generator[str, None, None]: """ Generate file objects from given list of Paths. +------------+ | Parameters | +------------+ | pathlist: List[str] | List of files and directories. """ for fpath in pathlist: if path.isfile(fpath): yield path.abspath(fpath) continue if path.isdir(fpath): yield from search([path.join(fpath, x) for x in listdir(fpath)]) continue print(f"[WARN]: No such file or directory: {fpath}")