119 lines
5.0 KiB
Python
119 lines
5.0 KiB
Python
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}")
|