0

我正在尝试缓存一个加载图像的函数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)
4

0 回答 0