albumentations-team / albucore

A high-performance image processing library designed to optimize and extend the Albumentations library with specialized functions for advanced image transformations. Perfect for developers working in computer vision who require efficient and scalable image augmentation.
MIT License
12 stars 3 forks source link

YOLOv8 with Albucore >= 0.0.15 results in masks must be list of numpy arrays #35

Closed armanivers closed 1 month ago

armanivers commented 1 month ago

I've been using Albumentations in YOLOv8 for instance segmentation. Ultralytics versions have no problem, but albumentations results into a conflict.

The error starts after Albumentations version > 1.4.7

Versions >=1.4.8 and <=1.4.15 don't get recognized by ultralytics at all (starting training process, the albumentations init method for data augmentation in ultralytics.data.augment doesn't start, which as far as I know mostly means that ultralytics doesn't see albumentations installed)

Versions >=1.4.16 get recognized again, but result into the following error:

TypeError: masks must be list of numpy arrays

the only fix that worked mentioned here

https://github.com/ultralytics/ultralytics/pull/6624

was to downgrade albumentations and its core

python3 -m pip install --upgrade albumentation==1.4.14 albucore==0.0.14

which made 1.4.14 recognizable again and no numpy array error.

Would be great if whatever happend after albucre 0.0.14 can be fixed.

Here is the full error code:

TypeError                                 Traceback (most recent call last)
Cell In[6], line 25
     23 initYaml(i)
     24 model = YOLO('yolov8x-seg.pt')
---> 25 model_results = model.train(data=os.path.join(ROOT_DIR, f'config{i}.yaml'), epochs=training_epochs, imgsz=512, batch=16, deterministic=True, plots=True,
     26                 close_mosaic = 0,
     27                 # disable built-in augmentation, instead use Albumentations Library
     28                 augment=False, hsv_h=0, hsv_s=0, hsv_v=0, degrees=0, translate=0, 
     29                 scale=0, shear=0.0, perspective=0, flipud=0, fliplr=0, bgr=0, 
     30                 mosaic=0, mixup=0, copy_paste=0, erasing=0, crop_fraction=0)
     31 results = model.val()
     33 print("\n" + "#" * 60)

File [~/yolov8/lib/python3.11/site-packages/ultralytics/engine/model.py:802](http://172.22.50.111:9000/user/user/lab/tree/myraid/YOLOv8_home/~/yolov8/lib/python3.11/site-packages/ultralytics/engine/model.py#line=801), in Model.train(self, trainer, **kwargs)
    799     self.model = self.trainer.model
    801 self.trainer.hub_session = self.session  # attach optional HUB session
--> 802 self.trainer.train()
    803 # Update model and cfg after training
    804 if RANK in {-1, 0}:

File [~/yolov8/lib/python3.11/site-packages/ultralytics/engine/trainer.py:207](http://172.22.50.111:9000/user/user/lab/tree/myraid/YOLOv8_home/~/yolov8/lib/python3.11/site-packages/ultralytics/engine/trainer.py#line=206), in BaseTrainer.train(self)
    204         ddp_cleanup(self, str(file))
    206 else:
--> 207     self._do_train(world_size)

File [~/yolov8/lib/python3.11/site-packages/ultralytics/engine/trainer.py:367](http://172.22.50.111:9000/user/user/lab/tree/myraid/YOLOv8_home/~/yolov8/lib/python3.11/site-packages/ultralytics/engine/trainer.py#line=366), in BaseTrainer._do_train(self, world_size)
    365     pbar = TQDM(enumerate(self.train_loader), total=nb)
    366 self.tloss = None
--> 367 for i, batch in pbar:
    368     self.run_callbacks("on_train_batch_start")
    369     # Warmup

File [~/yolov8/lib/python3.11/site-packages/tqdm/std.py:1181](http://172.22.50.111:9000/user/user/lab/tree/myraid/YOLOv8_home/~/yolov8/lib/python3.11/site-packages/tqdm/std.py#line=1180), in tqdm.__iter__(self)
   1178 time = self._time
   1180 try:
-> 1181     for obj in iterable:
   1182         yield obj
   1183         # Update and possibly print the progressbar.
   1184         # Note: does not call self.update(1) for speed optimisation.

File [~/yolov8/lib/python3.11/site-packages/ultralytics/data/build.py:48](http://172.22.50.111:9000/user/user/lab/tree/myraid/YOLOv8_home/~/yolov8/lib/python3.11/site-packages/ultralytics/data/build.py#line=47), in InfiniteDataLoader.__iter__(self)
     46 """Creates a sampler that repeats indefinitely."""
     47 for _ in range(len(self)):
---> 48     yield next(self.iterator)

File [~/yolov8/lib/python3.11/site-packages/torch/utils/data/dataloader.py:630](http://172.22.50.111:9000/user/user/lab/tree/myraid/YOLOv8_home/~/yolov8/lib/python3.11/site-packages/torch/utils/data/dataloader.py#line=629), in _BaseDataLoaderIter.__next__(self)
    627 if self._sampler_iter is None:
    628     # TODO(https://github.com/pytorch/pytorch/issues/76750)
    629     self._reset()  # type: ignore[call-arg]
--> 630 data = self._next_data()
    631 self._num_yielded += 1
    632 if self._dataset_kind == _DatasetKind.Iterable and \
    633         self._IterableDataset_len_called is not None and \
    634         self._num_yielded > self._IterableDataset_len_called:

File ~/yolov8/lib/python3.11/site-packages/torch/utils/data/dataloader.py:1344, in _MultiProcessingDataLoaderIter._next_data(self)
   1342 else:
   1343     del self._task_info[idx]
-> 1344     return self._process_data(data)

File [~/yolov8/lib/python3.11/site-packages/torch/utils/data/dataloader.py:1370](http://172.22.50.111:9000/user/user/lab/tree/myraid/YOLOv8_home/~/yolov8/lib/python3.11/site-packages/torch/utils/data/dataloader.py#line=1369), in _MultiProcessingDataLoaderIter._process_data(self, data)
   1368 self._try_put_index()
   1369 if isinstance(data, ExceptionWrapper):
-> 1370     data.reraise()
   1371 return data

File [~/yolov8/lib/python3.11/site-packages/torch/_utils.py:706](http://172.22.50.111:9000/user/user/lab/tree/myraid/YOLOv8_home/~/yolov8/lib/python3.11/site-packages/torch/_utils.py#line=705), in ExceptionWrapper.reraise(self)
    702 except TypeError:
    703     # If the exception takes multiple arguments, don't try to
    704     # instantiate since we don't know how to
    705     raise RuntimeError(msg) from None
--> 706 raise exception

TypeError: Caught TypeError in DataLoader worker process 0.
Original Traceback (most recent call last):
  File "/home/user/yolov8/lib/python3.11/site-packages/torch/utils/data/_utils/worker.py", line 309, in _worker_loop
    data = fetcher.fetch(index)  # type: ignore[possibly-undefined]
           ^^^^^^^^^^^^^^^^^^^^
  File "/home/user/yolov8/lib/python3.11/site-packages/torch/utils/data/_utils/fetch.py", line 52, in fetch
    data = [self.dataset[idx] for idx in possibly_batched_index]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/yolov8/lib/python3.11/site-packages/torch/utils/data/_utils/fetch.py", line 52, in <listcomp>
    data = [self.dataset[idx] for idx in possibly_batched_index]
            ~~~~~~~~~~~~^^^^^
  File "/home/user/yolov8/lib/python3.11/site-packages/ultralytics/data/base.py", line 256, in __getitem__
    return self.transforms(self.get_image_and_label(index))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/yolov8/lib/python3.11/site-packages/ultralytics/data/augment.py", line 201, in __call__
    data = t(data)
           ^^^^^^^
  File "/tmp/ipykernel_39409/4044539362.py", line 189, in __call__
    new = self.transform(image=im,
          ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/yolov8/lib/python3.11/site-packages/albumentations/core/composition.py", line 334, in __call__
    self.preprocess(data)
  File "/home/user/yolov8/lib/python3.11/site-packages/albumentations/core/composition.py", line 363, in preprocess
    self._check_args(**data)
  File "/home/user/yolov8/lib/python3.11/site-packages/albumentations/core/composition.py", line 416, in _check_args
    raise TypeError(f"{data_name} must be list of numpy arrays")
TypeError: masks must be list of numpy arrays
ternaus commented 1 month ago

Fixed in https://github.com/albumentations-team/albumentations/pull/1960