course22 icon indicating copy to clipboard operation
course22 copied to clipboard

01_intro - Image.open() issue

Open SirPentyna opened this issue 2 years ago • 2 comments
trafficstars

Hi, there is an issue with loading image to predict in 01_intro and the same issue in Is it a bird? - but probably with any other image notebook I would encounter the same issue.

When I try to run the code, I get an error related to Image.open() part of the code - from what I understood, since I create an image in the first line in the following code, it cannot be "opened" inside .predict() method.

img = PILImage.create(uploader.data[0])
is_cat,_,probs = learn.predict(img)
print(f"Is this a cat?: {is_cat}.")
print(f"Probability it's a cat: {probs[1].item():.6f}")

I have made no changes to the code, I have installed the latest fastai, I run all the cells in the notebook, one after the other.

Here is the screenshot of what happened:

image

And here is the whole error:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [10], in <cell line: 2>()
      1 img = PILImage.create(uploader.data[0])
----> 2 is_cat,_,probs = learn.predict(img)
      3 print(f"Is this a cat?: {is_cat}.")
      4 print(f"Probability it's a cat: {probs[1].item():.6f}")

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastai\learner.py:321, in Learner.predict(self, item, rm_type_tfms, with_input)
    319 def predict(self, item, rm_type_tfms=None, with_input=False):
    320     dl = self.dls.test_dl([item], rm_type_tfms=rm_type_tfms, num_workers=0)
--> 321     inp,preds,_,dec_preds = self.get_preds(dl=dl, with_input=True, with_decoded=True)
    322     i = getattr(self.dls, 'n_inp', -1)
    323     inp = (inp,) if i==1 else tuplify(inp)

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastai\learner.py:308, in Learner.get_preds(self, ds_idx, dl, with_input, with_decoded, with_loss, act, inner, reorder, cbs, **kwargs)
    306 if with_loss: ctx_mgrs.append(self.loss_not_reduced())
    307 with ContextManagers(ctx_mgrs):
--> 308     self._do_epoch_validate(dl=dl)
    309     if act is None: act = getcallable(self.loss_func, 'activation')
    310     res = cb.all_tensors()

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastai\learner.py:244, in Learner._do_epoch_validate(self, ds_idx, dl)
    242 if dl is None: dl = self.dls[ds_idx]
    243 self.dl = dl
--> 244 with torch.no_grad(): self._with_events(self.all_batches, 'validate', CancelValidException)

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastai\learner.py:199, in Learner._with_events(self, f, event_type, ex, final)
    198 def _with_events(self, f, event_type, ex, final=noop):
--> 199     try: self(f'before_{event_type}');  f()
    200     except ex: self(f'after_cancel_{event_type}')
    201     self(f'after_{event_type}');  final()

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastai\learner.py:205, in Learner.all_batches(self)
    203 def all_batches(self):
    204     self.n_iter = len(self.dl)
--> 205     for o in enumerate(self.dl): self.one_batch(*o)

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastai\data\load.py:127, in DataLoader.__iter__(self)
    125 self.before_iter()
    126 self.__idxs=self.get_idxs() # called in context of main process (not workers/subprocesses)
--> 127 for b in _loaders[self.fake_l.num_workers==0](self.fake_l):
    128     # pin_memory causes tuples to be converted to lists, so convert them back to tuples
    129     if self.pin_memory and type(b) == list: b = tuple(b)
    130     if self.device is not None: b = to_device(b, self.device)

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\torch\utils\data\dataloader.py:628, in _BaseDataLoaderIter.__next__(self)
    625 if self._sampler_iter is None:
    626     # TODO(https://github.com/pytorch/pytorch/issues/76750)
    627     self._reset()  # type: ignore[call-arg]
--> 628 data = self._next_data()
    629 self._num_yielded += 1
    630 if self._dataset_kind == _DatasetKind.Iterable and \
    631         self._IterableDataset_len_called is not None and \
    632         self._num_yielded > self._IterableDataset_len_called:

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\torch\utils\data\dataloader.py:671, in _SingleProcessDataLoaderIter._next_data(self)
    669 def _next_data(self):
    670     index = self._next_index()  # may raise StopIteration
--> 671     data = self._dataset_fetcher.fetch(index)  # may raise StopIteration
    672     if self._pin_memory:
    673         data = _utils.pin_memory.pin_memory(data, self._pin_memory_device)

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\torch\utils\data\_utils\fetch.py:43, in _IterableDatasetFetcher.fetch(self, possibly_batched_index)
     41         raise StopIteration
     42 else:
---> 43     data = next(self.dataset_iter)
     44 return self.collate_fn(data)

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastai\data\load.py:138, in DataLoader.create_batches(self, samps)
    136 if self.dataset is not None: self.it = iter(self.dataset)
    137 res = filter(lambda o:o is not None, map(self.do_item, samps))
--> 138 yield from map(self.do_batch, self.chunkify(res))

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastcore\basics.py:230, in chunked(it, chunk_sz, drop_last, n_chunks)
    228 if not isinstance(it, Iterator): it = iter(it)
    229 while True:
--> 230     res = list(itertools.islice(it, chunk_sz))
    231     if res and (len(res)==chunk_sz or not drop_last): yield res
    232     if len(res)<chunk_sz: return

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastai\data\load.py:153, in DataLoader.do_item(self, s)
    152 def do_item(self, s):
--> 153     try: return self.after_item(self.create_item(s))
    154     except SkipItemException: return None

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastai\data\load.py:160, in DataLoader.create_item(self, s)
    159 def create_item(self, s):
--> 160     if self.indexed: return self.dataset[s or 0]
    161     elif s is None:  return next(self.it)
    162     else: raise IndexError("Cannot index an iterable dataset numerically - must use `None`.")

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastai\data\core.py:458, in Datasets.__getitem__(self, it)
    457 def __getitem__(self, it):
--> 458     res = tuple([tl[it] for tl in self.tls])
    459     return res if is_indexer(it) else list(zip(*res))

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastai\data\core.py:458, in <listcomp>(.0)
    457 def __getitem__(self, it):
--> 458     res = tuple([tl[it] for tl in self.tls])
    459     return res if is_indexer(it) else list(zip(*res))

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastai\data\core.py:417, in TfmdLists.__getitem__(self, idx)
    415 res = super().__getitem__(idx)
    416 if self._after_item is None: return res
--> 417 return self._after_item(res) if is_indexer(idx) else res.map(self._after_item)

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastai\data\core.py:377, in TfmdLists._after_item(self, o)
--> 377 def _after_item(self, o): return self.tfms(o)

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastcore\transform.py:208, in Pipeline.__call__(self, o)
--> 208 def __call__(self, o): return compose_tfms(o, tfms=self.fs, split_idx=self.split_idx)

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastcore\transform.py:158, in compose_tfms(x, tfms, is_enc, reverse, **kwargs)
    156 for f in tfms:
    157     if not is_enc: f = f.decode
--> 158     x = f(x, **kwargs)
    159 return x

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastcore\transform.py:81, in Transform.__call__(self, x, **kwargs)
     79 @property
     80 def name(self): return getattr(self, '_name', _get_name(self))
---> 81 def __call__(self, x, **kwargs): return self._call('encodes', x, **kwargs)
     82 def decode  (self, x, **kwargs): return self._call('decodes', x, **kwargs)
     83 def __repr__(self): return f'{self.name}:\nencodes: {self.encodes}decodes: {self.decodes}'

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastcore\transform.py:91, in Transform._call(self, fn, x, split_idx, **kwargs)
     89 def _call(self, fn, x, split_idx=None, **kwargs):
     90     if split_idx!=self.split_idx and self.split_idx is not None: return x
---> 91     return self._do_call(getattr(self, fn), x, **kwargs)

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastcore\transform.py:97, in Transform._do_call(self, f, x, **kwargs)
     95     if f is None: return x
     96     ret = f.returns(x) if hasattr(f,'returns') else None
---> 97     return retain_type(f(x, **kwargs), x, ret)
     98 res = tuple(self._do_call(f, x_, **kwargs) for x_ in x)
     99 return retain_type(res, x)

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastcore\dispatch.py:120, in TypeDispatch.__call__(self, *args, **kwargs)
    118 elif self.inst is not None: f = MethodType(f, self.inst)
    119 elif self.owner is not None: f = MethodType(f, self.owner)
--> 120 return f(*args, **kwargs)

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastai\vision\core.py:125, in PILBase.create(cls, fn, **kwargs)
    123 if isinstance(fn,bytes): fn = io.BytesIO(fn)
    124 if isinstance(fn,Image.Image) and not isinstance(fn,cls): return cls(fn)
--> 125 return cls(load_image(fn, **merge(cls._open_args, kwargs)))

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\fastai\vision\core.py:98, in load_image(fn, mode)
     96 def load_image(fn, mode=None):
     97     "Open and load a `PIL.Image` and convert to `mode`"
---> 98     im = Image.open(fn)
     99     im.load()
    100     im = im._new(im.im)

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\PIL\Image.py:3101, in open(fp, mode, formats)
   3098     fp = io.BytesIO(fp.read())
   3099     exclusive_fp = True
-> 3101 prefix = fp.read(16)
   3103 preinit()
   3105 accept_warnings = []

File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\PIL\Image.py:517, in Image.__getattr__(self, name)
    515     deprecate("Image categories", 10, "is_animated", plural=True)
    516     return self._category
--> 517 raise AttributeError(name)

AttributeError: read

SirPentyna avatar Mar 10 '23 08:03 SirPentyna

I had exactly the same problem and I didn't know how to fix it! In fact, this issue is the object of these requests: https://github.com/fastai/course22/pull/55 https://github.com/fastai/fastbook/pull/567

For Is it a bird?, you only need to change the code by removing PILImage.create() and keep learn.predict('bird.jpg')

}
 ],
 "source": [
  "is_bird,_,probs = learn.predict('bird.jpg')\n",
  "print(f\"This is a: {is_bird}.\")\n",
  "print(f\"Probability it's a bird: {probs[0]:.4f}\")"
 ]

camillefranchet avatar Mar 12 '23 19:03 camillefranchet

Had the same issue. Thanks @camillefranchet for the answer :)

Ltwrk avatar Mar 19 '23 18:03 Ltwrk