Почему возникает ошибка атрибута при попытке отобразить изображение (PIL-объект)

#python #jupyter-notebook #python-imaging-library

#python #jupyter-notebook #python-imaging-library

Вопрос:

Я столкнулся с некоторыми проблемами при попытке сохранить изображения из архива в виде объектов pillow в списке. Я использую библиотеку pillow для python и jupyter notebook для работы с изображениями. И изначально я хотел иметь список словарей, где одним из ключей был бы объект pillow, чтобы я мог легко получить свое изображение (мне так кажется, может быть, я ошибаюсь). Я открываю изображения в архиве по одному как объект file, а затем открываю его как объект pillow. На этом шаге я хочу сохранить этот объект pillow, чтобы я мог работать с ним позже. Все изображения в порядке, если я использую display при добавлении их в список, они отображаются. Но есть одна вещь, которая выглядит странно для меня. Если я не отображаю изображения во время их добавления в список, я не смогу отображать их дальше, если я извлеку их из этого списка. Я хотел бы, чтобы вы могли мне помочь. Я полагаю, проблема может заключаться в моей неопытности в работе с файлами. Может быть, есть лучший способ сделать то, что мне нужно.

 import zipfile

from PIL import Image
import pytesseract
import cv2 as cv
import numpy as np

#%%
file = zipfile.ZipFile('small_img.zip', 'r')

data = []
images = []
for name in file.namelist():
    with file.open(name, 'r') as img_file:
        image = Image.open(img_file)
        data.append({'name': name, 'PilObject': image, 'text': None, 'bounding_boxes': None})
        images.append(image)
        #display(image)
        #if I leave the line above I could display my images further, fetching them from the list
        #If not, an error occurs
#%%
display(images[0])

    ---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

d:pythonprojectsuntitledvenvlibsite-packagesIPythoncoreformatters.py in __call__(self, obj)
    343             method = get_real_method(obj, self.print_method)
    344             if method is not None:
--> 345                 return method()
    346             return None
    347         else:

d:pythonprojectsuntitledvenvlibsite-packagesPILImage.py in _repr_png_(self)
    670         """
    671         b = io.BytesIO()
--> 672         self.save(b, "PNG")
    673         return b.getvalue()
    674 

d:pythonprojectsuntitledvenvlibsite-packagesPILImage.py in save(self, fp, format, **params)
   2122 
   2123         # may mutate self!
-> 2124         self._ensure_mutable()
   2125 
   2126         save_all = params.pop("save_all", False)

d:pythonprojectsuntitledvenvlibsite-packagesPILImage.py in _ensure_mutable(self)
    616     def _ensure_mutable(self):
    617         if self.readonly:
--> 618             self._copy()
    619         else:
    620             self.load()

d:pythonprojectsuntitledvenvlibsite-packagesPILImage.py in _copy(self)
    609 
    610     def _copy(self):
--> 611         self.load()
    612         self.im = self.im.copy()
    613         self.pyaccess = None

d:pythonprojectsuntitledvenvlibsite-packagesPILImageFile.py in load(self)
    241                         while True:
    242                             try:
--> 243                                 s = read(self.decodermaxblock)
    244                             except (IndexError, struct.error) as e:
    245                                 # truncated png/gif

d:pythonprojectsuntitledvenvlibsite-packagesPILPngImagePlugin.py in load_read(self, read_bytes)
    861         self.__idat = self.__idat - read_bytes
    862 
--> 863         return self.fp.read(read_bytes)
    864 
    865     def load_end(self):

~AppDataLocalProgramsPythonPython37libzipfile.py in read(self, n)
    928         self._offset = 0
    929         while n > 0 and not self._eof:
--> 930             data = self._read1(n)
    931             if n < len(data):
    932                 self._readbuffer = data

~AppDataLocalProgramsPythonPython37libzipfile.py in _read1(self, n)
    996             data = self._decompressor.unconsumed_tail
    997             if n > len(data):
--> 998                 data  = self._read2(n - len(data))
    999         else:
   1000             data = self._read2(n)

~AppDataLocalProgramsPythonPython37libzipfile.py in _read2(self, n)
   1028         n = min(n, self._compress_left)
   1029 
-> 1030         data = self._fileobj.read(n)
   1031         self._compress_left -= len(data)
   1032         if not data:

~AppDataLocalProgramsPythonPython37libzipfile.py in read(self, n)
    751                         "is an open writing handle on it. "
    752                         "Close the writing handle before trying to read.")
--> 753             self._file.seek(self._pos)
    754             data = self._file.read(n)
    755             self._pos = self._file.tell()

AttributeError: 'NoneType' object has no attribute 'seek'

<PIL.PngImagePlugin.PngImageFile image mode=RGB size=3600x6300 at 0x24E8704B1C8>
  

Комментарии:

1. Вызов image.load() внутри цикла — если вы абсолютно ничего не делаете с Image объектом, он никогда не загружается, и после цикла он не может быть загружен, потому что файл больше не открыт.

2. @jasonharper Я пробовал это. Похоже, дело не в этом. Смотрите тестовый источник ниже, он отлично работает только с Image.open().

Ответ №1:

Итак, мне любопытно, работает ли код в вопросе как есть?
Потому что, похоже, происходят разные странные вещи.
(Я не могу протестировать его как есть из-за отсутствия пакета opencv.)

В качестве основы использовал это, чтобы проверить, что изображения действительно работают,
при чтении из архива.

 import zipfile

from PIL import Image

archive = zipfile.ZipFile('media.zip', 'r')
fileNames = archive.namelist()
fileNames.pop(0)  # Remove directory entry (here, 'media/').

# Opening the image files, could be as simple as this:
images = [Image.open(fName) for fName in fileNames]

# Test images, by displaying them with tkinter.
import tkinter as tk
from PIL import ImageTk
tk.Tk()
# Store references, to keep PhotoImages alive (for tkinter).
tkImages = [ImageTk.PhotoImage(img) for img in images]
for img in tkImages: tk.Label(image=img).pack()
tk.mainloop()
  

Можете ли вы обновить цикл, в котором вы открываете изображения,

в соответствии с этим и посмотрите, сохраняется ли проблема?