0

The following code fails on learner_inf.predict(image), but sometimes with the same image, if I step through it, it will work. learner_inf is a Fastai AI model. I have tried implementing sleeps to see if it is a timing issue, but it hasn't helped.

class MyHandler(FileSystemEventHandler):
def on_created(self, event):
    if not event.is_directory:
        #time.sleep(10)
        # Open the image file
        try:
            with Image.open(event.src_path) as image:
                #time.sleep(10)
                predicted = learner_inf.predict(image)
                print(f"Predicted: {predicted}")
        except Exception as e:
            print(f"Error opening image: {str(e)}")
            
path = "inbox"
event_handler = MyHandler()
observer = Observer()
observer.schedule(event_handler, path, recursive=True)
observer.start()

try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    observer.stop()

observer.join()

learner_inf.predict(image) fails with

Error opening image: 'NoneType' object has no attribute 'crop'

The full debug trace is

Exception in thread Thread-7:
Traceback (most recent call last):
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\threading.py", line 1038, in     _bootstrap_inner
    self.run()
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\watchdog\observers\api.py", line 204, in run
    self.dispatch_events(self.event_queue)
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\watchdog\observers\api.py", line 380, in dispatch_events
handler.dispatch(event)
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\watchdog\events.py", line 276, in dispatch
{
  File "C:\Users\User\AppData\Local\Temp\ipykernel_10292\383391125.py", line 12, in on_created
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastai\learner.py", line 321, in predict
inp,preds,_,dec_preds = self.get_preds(dl=dl, with_input=True, with_decoded=True)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastai\learner.py", line 308, in get_preds
self._do_epoch_validate(dl=dl)
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastai\learner.py", line 244, in _do_epoch_validate
with torch.no_grad(): self._with_events(self.all_batches, 'validate', CancelValidException)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastai\learner.py", line 199, in _with_events
try: self(f'before_{event_type}');  f()
                                    ^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastai\learner.py", line 205, in all_batches
for o in enumerate(self.dl): self.one_batch(*o)
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastai\data\load.py", line 127, in __iter__
for b in _loaders[self.fake_l.num_workers==0](self.fake_l):
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\torch\utils\data\dataloader.py", line 633, in __next__
data = self._next_data()
       ^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\torch\utils\data\dataloader.py", line 677, in _next_data
data = self._dataset_fetcher.fetch(index)  # may raise StopIteration
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\torch\utils\data\_utils\fetch.py", line 41, in fetch
data = next(self.dataset_iter)
       ^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastai\data\load.py", line 138, in create_batches
yield from map(self.do_batch, self.chunkify(res))
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastcore\basics.py", line 230, in chunked
res = list(itertools.islice(it, chunk_sz))
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastai\data\load.py", line 153, in do_item
try: return self.after_item(self.create_item(s))
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastcore\transform.py", line 208, in __call__
def __call__(self, o): return compose_tfms(o, tfms=self.fs, split_idx=self.split_idx)
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastcore\transform.py", line 158, in compose_tfms
x = f(x, **kwargs)
    ^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastai\vision\augment.py", line 49, in __call__
return super().__call__(b, split_idx=split_idx, **kwargs) if self.do else b
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastcore\transform.py", line 81, in __call__
def __call__(self, x, **kwargs): return self._call('encodes', x, **kwargs)
                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastcore\transform.py", line 91, in _call
return self._do_call(getattr(self, fn), x, **kwargs)
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastcore\transform.py", line 98, in _do_call
res = tuple(self._do_call(f, x_, **kwargs) for x_ in x)
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastcore\transform.py", line 98, in <genexpr>
res = tuple(self._do_call(f, x_, **kwargs) for x_ in x)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastcore\transform.py", line 97, in _do_call
return retain_type(f(x, **kwargs), x, ret)
                   ^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastcore\dispatch.py", line 120, in __call__
return f(*args, **kwargs)
       ^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastai\vision\augment.py", line 323, in encodes
res = x.crop_pad(self.cp_size, self.tl, orig_sz=self.orig_sz,
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastai\vision\augment.py", line 164, in crop_pad
return x._do_crop_pad(sz, tl, orig_sz=orig_sz, pad_mode=pad_mode, resize_mode=resize_mode, resize_to=resize_to)
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\fastai\vision\augment.py", line 132, in _do_crop_pad
x = x.crop((*c, *tl.add(sz).min(orig_sz)))
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\PIL\Image.py", line 1234, in crop
return self._new(self._crop(self.im, box))
                 ^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\ProgramData\anaconda3\envs\cuda118\Lib\site-packages\PIL\Image.py", line 1254, in _crop
return im.crop((x0, y0, x1, y1))
       ^^^^^^^
AttributeError: 'NoneType' object has no attribute 'crop'
CarbonMan
  • 4,350
  • 12
  • 54
  • 75
  • You could perhaps use some kind of retrying logic in case the image opening fails? Preferably test if the image is open before going into `learner_inf.predict` and retry a few times if it is not. Here are some related questions https://stackoverflow.com/q/2083987/1256347 and https://stackoverflow.com/q/567622/1256347 – Saaru Lindestøkke Jun 20 '23 at 09:08

0 Answers0