mdbloice / Augmentor

Image augmentation library in Python for machine learning.
https://augmentor.readthedocs.io/en/stable
MIT License
5.07k stars 866 forks source link

Error for a single class images #135

Closed matsui528 closed 6 years ago

matsui528 commented 6 years ago

Hi, thanks for this wonderful library!

I found that an error is thrown if there exists only one class for images. Is this expected behavior?

Minimum code to reproduce the problem: If there are two classes, the following code works

$ tree
.
├── img_two_classes
│   ├── cat
│   │   └── 001.jpg
│   └── dog
│       └── 000.jpg
└── run.py
$ cat run.py
import Augmentor
p = Augmentor.Pipeline('img_two_classes')
p.flip_top_bottom(probability=0.1)
p.status()
p.sample(10)
$ python run.py
Initialised with 2 image(s) found.
Output directory set to img_two_classes/output.Operations: 1
        0: Flip (probability=0.1 top_bottom_left_right=TOP_BOTTOM )
Images: 2
Classes: 2
        Class index: 0 Class label: cat 
        Class index: 1 Class label: dog 
Dimensions: 2
        Width: 220 Height: 205
        Width: 602 Height: 520
Formats: 1
         JPEG

You can remove operations using the appropriate index and the remove_operation(index) function.
Processing <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=220x205 at 0x7FC0E2B75C50>: 100%|███████████| 10/10 [00:00<00:00, 62.40 Samples/s]

However, if there is only one class, it doesn't seems the following code works:

$ tree
.
├── img_single_class
│   └── dog
│       └── 000.jpg
└── run.py
$ cat run.py
import Augmentor
p = Augmentor.Pipeline('img_single_class')
p.flip_top_bottom(probability=0.1)
p.status()
p.sample(10)
$ python run.py
Initialised with 1 image(s) found.
Output directory set to img_single_class/output.Operations: 1
        0: Flip (probability=0.1 top_bottom_left_right=TOP_BOTTOM )
Images: 1
Classes: 1
        Class index: 0 Class label: dog 
Dimensions: 1
        Width: 220 Height: 205
Formats: 1
         JPEG

You can remove operations using the appropriate index and the remove_operation(index) function.
Executing Pipeline:   0%|                                                                                                                              | 0/10 [00:00<?, ? Samples/s]
Traceback (most recent call last):
  File "/home/XXX/usr/src/anaconda/anaconda3/envs/cvpr19/lib/python3.6/site-packages/Augmentor/Pipeline.py", line 226, in _execute
    images[i].save(os.path.join(augmentor_image.output_directory, save_name))
  File "/home/XXX/usr/src/anaconda/anaconda3/envs/cvpr19/lib/python3.6/site-packages/PIL/Image.py", line 1947, in save
    fp = builtins.open(filename, "w+b")
FileNotFoundError: [Errno 2] No such file or directory: '/home/XXX/Desktop/test/img_single_class/output/dog/dog_original_000.jpg_86d5b4ae-0437-4e6f-8479-2e3c9784e708.jpg'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "run.py", line 5, in <module>
    p.sample(10)
  File "/home/XXX/usr/src/anaconda/anaconda3/envs/cvpr19/lib/python3.6/site-packages/Augmentor/Pipeline.py", line 345, in sample
    for result in executor.map(self, augmentor_images):
  File "/home/XXX/usr/src/anaconda/anaconda3/envs/cvpr19/lib/python3.6/concurrent/futures/_base.py", line 586, in result_iterator
    yield fs.pop().result()
  File "/home/XXX/usr/src/anaconda/anaconda3/envs/cvpr19/lib/python3.6/concurrent/futures/_base.py", line 425, in result
    return self.__get_result()
  File "/home/XXX/usr/src/anaconda/anaconda3/envs/cvpr19/lib/python3.6/concurrent/futures/_base.py", line 384, in __get_result
    raise self._exception
  File "/home/XXX/usr/src/anaconda/anaconda3/envs/cvpr19/lib/python3.6/concurrent/futures/thread.py", line 56, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/XXX/usr/src/anaconda/anaconda3/envs/cvpr19/lib/python3.6/site-packages/Augmentor/Pipeline.py", line 103, in __call__
    return self._execute(augmentor_image)
  File "/home/XXX/usr/src/anaconda/anaconda3/envs/cvpr19/lib/python3.6/site-packages/Augmentor/Pipeline.py", line 232, in _execute
    print("Error writing %s, %s. Change save_format to PNG?" % (file_name, e.message))
AttributeError: 'FileNotFoundError' object has no attribute 'message'

My environment is:

Best,

mdbloice commented 6 years ago

Hi @matsui528 glad you are making use of the library :-) Yeah, basically although the error is a strange one and not very informative, I think it is because you have a directory img_single_class and then another directory dog for your single class. It would be better if you just initialised the pipeline within the dog directory that contains the images.

However, thanks for making this issue, I guess my tests do not cover situations where the initialisation directory contains only one directory. In cases with only one class, I assumed users would just initialise within a directory containing only images. I will certainly fix that in the next release!

matsui528 commented 6 years ago

Got it. p = Augmentor.Pipeline('img_single_class/dog') works perfectly. Thank you again for your great library!

mdbloice commented 6 years ago

Great, glad it's working. I am working a major update that will be released soon, hopefully I can also include this fix as well. Thanks again for pointing this out!