-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathImagePoolUtils.py
More file actions
162 lines (139 loc) · 5.4 KB
/
ImagePoolUtils.py
File metadata and controls
162 lines (139 loc) · 5.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
from pathlib import Path
from typing import Optional, Union, List
from utils.ImageUtils import CvImage, read_image
DEFAULT_ACCEPT_SUFFIX = [".png", ".jpg", ".jpeg", ".bmp"]
class Nothing:
"""
Nothing 主要用于解决连续链式调用(a.b.c.d...)的中间报错,类似于 JavaScript 中的 a?.b?.c
Nothing 是等于 None 的,但由于无法重写 is 的判定,一次需要使用 ==
"""
def get(self, key):
return self
def __getattr__(self, item):
return self
def __getitem__(self, item):
return self
def __eq__(self, other):
return other is None
def __bool__(self):
return False
def __str__(self):
return f"{self.__class__.__name__}()"
NOTHING = Nothing()
class ImagePool(object):
def __init__(self, root_path: Union[Path, str], work_path: Union[Path, str] = None, images: dict = None,
strict: bool = False, scan: bool = False, ignore_suffix: bool = False,
cache_sub_pool: bool = True,
accept_suffix: Optional[List[str]] = None):
"""
初始化一个图片池
:param root_path: 根目录
:param work_path: 工作目录
:param images: 图片数据保存的字典
:param strict: 是否启用严格模式(获取不存在的图片直接报错)
:param scan: 是否自动工作目录(扫描目录下的图片文件)
:param ignore_suffix: 是否忽略后缀(第一次时需要带后缀才可以正确读取文件,之后不需要带后缀)
:param cache_sub_pool: 是否缓存子目录的图片池
:param accept_suffix: 自动读取时扫描文件的后缀
"""
# 保存参数
self._kwargs = {
"scan": scan,
"strict": strict,
"ignore_suffix": ignore_suffix,
"cache_sub_pool": cache_sub_pool,
"accept_suffix": accept_suffix,
}
self._strict = strict
self._ignore_suffix = ignore_suffix
self._cache_sub_pool = cache_sub_pool
self._images = {} if images is None else images
# 根目录
self.root_path: Path = (root_path if isinstance(root_path, Path) else Path(root_path)).resolve()
# 检查目录
if not self.root_path.exists():
raise FileNotFoundError("根目录不存在")
# 工作目录
if work_path is None:
self.work_path: Path = self.root_path
elif isinstance(work_path, Path):
try:
work_path = work_path.resolve()
work_path.relative_to(self.root_path)
self.work_path: Path = work_path
except ValueError:
raise ValueError("工作目录应该是根目录的子目录")
else:
self.work_path: Path = self.root_path.joinpath(work_path).resolve()
# 检查工作目录
if not self.work_path.exists():
raise FileNotFoundError("工作目录不存在")
# 允许的文件类型
self.accept_suffix = accept_suffix or DEFAULT_ACCEPT_SUFFIX
# 自动扫描目录下的图片文件
if scan:
self._scan_()
def _scan_(self):
"""
自动扫描读取目录下的图片文件
:return:
"""
for accept_suffix in self.accept_suffix:
for filepath in self.work_path.glob(f"*{accept_suffix}"):
key = self._get_key_(filepath)
self._images[key] = read_image(str(filepath))
def cwd(self) -> Path:
"""
获取当前工作目录
:return:
"""
return self.work_path
def home(self) -> Path:
"""
获取根(家)目录
:return:
"""
return self.root_path
@property
def images(self):
return self._images.keys()
def _get_key_(self, filepath: Path) -> str:
key = filepath.relative_to(self.root_path)
if self._ignore_suffix:
key = str(key).replace(key.name, key.stem)
else:
key = str(key)
return key
def get(self, path: str) -> Union[Nothing, CvImage, "ImagePool"]:
if path is None:
raise ValueError("图片路径不能是 `None`")
filepath = self.work_path.joinpath(path)
key = self._get_key_(filepath)
# 判断是否存在
if key in self._images: # 存在直接返回
return self._images[key]
else: # 不存在尝试读取
if filepath.exists():
# 为子目录
if filepath.is_dir():
# 创建子目录图片池
pool = ImagePool(self.root_path, filepath, self._images, **self._kwargs)
if self._cache_sub_pool:
self._images[key] = pool
return pool
else:
image = read_image(str(filepath))
self._images[key] = image
return image
else:
# 严格模式直接报错,非严格模式返回None
if self._strict:
raise FileNotFoundError(f"Image file `{filepath}` not found")
else:
return NOTHING
def __getitem__(self, item):
return self.get(item)
def __getattr__(self, item):
return self.get(item)
def __str__(self):
return f"{self.__class__.__name__}({self.work_path})"