我正在尝试缓存一个加载图像的函数PIL.Image.open
(我也尝试过mpimg.imread
)。一些图像被截断;我明白了OSError: image file is truncated (0 bytes not processed)
。我试图ImageFile.LOAD_TRUNCATED_IMAGES = True
防止引发异常。那行得通,但是 diskcache 模块的缓存没有效果。
下面是一个示例片段,它显示了当截断图像位于文件夹中时的这种行为:
import diskcache
import os
from PIL import Image
cache = diskcache.Cache(directory="/tmp/cache")
@cache.memoize(expire=1000)
def load_images(path):
return [Image.open(os.path.join(path, f)) for f in os.listdir(path)]
load_images("/path/to/image/folder")
也无法从装饰函数中捕获异常。我试过这样:
cache = diskcache.Cache(directory="/tmp/cache")
@cache.memoize(expire=1000)
def load_images(path):
def load_image(filename):
try:
return Image.open(os.path.join(path, filename))
except OSError:
return None
return list(map(load_image, os.listdir(path)))
但该功能仍然出错;这是错误:
---------------------------------------------------------------------------
OSError Traceback (most recent call last)
/tmp/ipykernel_41351/160153895.py in <module>
11 return [Image.open(os.path.join(path, f)) for f in os.listdir(path)]
12
---> 13 x = load_images("/path/to/image/folder")
~/anaconda3/envs/image-service-v1/lib/python3.9/site-packages/diskcache/core.py in wrapper(*args, **kwargs)
1889 result = func(*args, **kwargs)
1890 if expire is None or expire > 0:
-> 1891 self.set(key, result, expire, tag=tag, retry=True)
1892
1893 return result
~/anaconda3/envs/image-service-v1/lib/python3.9/site-packages/diskcache/core.py in set(self, key, value, expire, read, tag, retry)
773 db_key, raw = self._disk.put(key)
774 expire_time = None if expire is None else now + expire
--> 775 size, mode, filename, db_value = self._disk.store(value, read, key=key)
776 columns = (expire_time, tag, size, mode, filename, db_value)
777
~/anaconda3/envs/image-service-v1/lib/python3.9/site-packages/diskcache/core.py in store(self, value, read, key)
239 return size, MODE_BINARY, filename, None
240 else:
--> 241 result = pickle.dumps(value, protocol=self.pickle_protocol)
242
243 if len(result) < min_file_size:
~/anaconda3/envs/image-service-v1/lib/python3.9/site-packages/PIL/Image.py in __getstate__(self)
694
695 def __getstate__(self):
--> 696 return [self.info, self.mode, self.size, self.getpalette(), self.tobytes()]
697
698 def __setstate__(self, state):
~/anaconda3/envs/image-service-v1/lib/python3.9/site-packages/PIL/Image.py in getpalette(self)
1358 """
1359
-> 1360 self.load()
1361 try:
1362 return list(self.im.getpalette())
~/anaconda3/envs/image-service-v1/lib/python3.9/site-packages/PIL/ImageFile.py in load(self)
247 break
248 else:
--> 249 raise OSError(
250 "image file is truncated "
251 f"({len(b)} bytes not processed)"
OSError: image file is truncated (0 bytes not processed)
我觉得很奇怪加载图像的问题导致缓存无效。知道如何解决这个问题吗?”。也许磁盘缓存的维护者甚至会监视这个标签。
顺便提一句。加载mpimg.imread
会给出此错误TypeError: No loop matching the specified signature and casting was found for ufunc true_divide
编辑
我将调试打印放入 matplotlib.image 到_pil_png_to_float_array
这个块中。损坏的图像在转换为 numpy 数组时没有形状。
if mode == "RGB": # RGB.
print(np.array(pil_png).shape) # prints `()`
return np.divide(pil_png, 2**8 - 1, dtype=np.float32)