Failed to load images from __getitem__ occasionally

username: KleinXin
cooked: <p>I want to add some custom online augmetation to the trainning data. So I tried to write the Dataset Class of my own. In the codes below, I use opencv to load the image from local disk but it occasionally failed. I checked the images I saved in ‘debug’ folder. The size of some of the images is zero. The error message is also shown below. Pytorch version 1.10 and Torchvision version 0.11.1.</p>
<pre><code class="lang-auto">import torch
import PIL
from PIL import Image
import os
import pandas as pd
import math
import numpy as np
import torchvision.datasets as tvdataset

import pdb
import cv2
from torch.utils.data import Dataset

class HotelID(Dataset):
      def __init__(self,img_root_dir,mask_dir,transform):

         self.img_root_dir = img_root_dir
         
         self.transform = transform

         self.data_list = []

         folders = os.listdir(img_root_dir)
         folders = sorted(folders)

         for folder_idx,folder_ in enumerate(folders):

             files = os.listdir(os.path.join(img_root_dir,folder_))
             files = sorted(files)

             for file in files:
                 self.data_list.append([os.path.join(img_root_dir,folder_,file),folder_idx])

         self.num_imgs = len(self.data_list)

      def __getitem__(self,idx):

          img_path = self.data_list[idx][0]
          label = self.data_list[idx][1]

          img_name = img_path.split('/')[-1]
          img_folder = img_path.split('/')[-2]

          I = cv2.imread(img_path)

          cv2.imwrite(os.path.join('./debug',img_folder+'_'+img_name),I)

          img_pil_out = Image.fromarray(I[:,:,::-1])

          img_pil_out.save(os.path.join('./debug',img_folder+'_'+img_name[:-4]+'_pil.jpg'))

          img_pil = self.transform(img_pil_out)

          return img_pil,label

      def __len__(self):
         return len(self.data_list)
          

def get_dataset(conf):

    conf['num_class'] = 3116
    
    transform_train = transforms.Compose([
        transforms.RandomCrop((conf.crop_size,conf.crop_size)),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))
    ])
    
    transform_test = transforms.Compose([
        transforms.CenterCrop((conf.crop_size,conf.crop_size)),
        transforms.ToTensor(),
        transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))
    ])

    ds_train = HotelID(conf.train_folder,conf.mask_folder,transform_train)
    #ds_train = tvdataset.ImageFolder(conf.train_folder, transform=transform_train)
    ds_test = tvdataset.ImageFolder(conf.test_folder, transform=transform_test)

    return ds_train,ds_test

</code></pre>
<p><img src="https://discuss.pytorch.org/uploads/default/original/3X/2/9/291111cdf97ad0570b4743574c093a63c18fa50a.png" alt="image" data-base62-sha1="5Ri99u5rtzgjv14Iuy5jhKAtfmy" width="545" height="341"></p>
<pre><code class="lang-auto">for i, (input, target) in enumerate(trainloader):
  File "/usr/local/lib/python3.6/dist-packages/torch/utils/data/dataloader.py", line 521, in __next__
    data = self._next_data()
  File "/usr/local/lib/python3.6/dist-packages/torch/utils/data/dataloader.py", line 1203, in _next_data
    return self._process_data(data)
  File "/usr/local/lib/python3.6/dist-packages/torch/utils/data/dataloader.py", line 1229, in _process_data
    data.reraise()
  File "/usr/local/lib/python3.6/dist-packages/torch/_utils.py", line 434, in reraise
    raise exception
TypeError: Caught TypeError in DataLoader worker process 0.
Original Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/torch/utils/data/_utils/worker.py", line 287, in _worker_loop
    data = fetcher.fetch(index)
  File "/usr/local/lib/python3.6/dist-packages/torch/utils/data/_utils/fetch.py", line 49, in fetch
    data = [self.dataset[idx] for idx in possibly_batched_index]
  File "/usr/local/lib/python3.6/dist-packages/torch/utils/data/_utils/fetch.py", line 49, in &lt;listcomp&gt;
    data = [self.dataset[idx] for idx in possibly_batched_index]
  File "datasets/hotel_id_2022.py", line 109, in __getitem__
    img_pil = self.transform(img_pil_out)
  File "/usr/local/lib/python3.6/dist-packages/torchvision/transforms/transforms.py", line 61, in __call__
    img = t(img)
  File "/usr/local/lib/python3.6/dist-packages/torch/nn/modules/module.py", line 1102, in _call_impl
    return forward_call(*input, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/torchvision/transforms/transforms.py", line 642, in forward
    i, j, h, w = self.get_params(img, self.size)
  File "/usr/local/lib/python3.6/dist-packages/torchvision/transforms/transforms.py", line 597, in get_params
    if h + 1 &lt; th or w + 1 &lt; tw:
TypeError: '&lt;' not supported between instances of 'int' and 'NoneType'

</code></pre>
<p>I checked those images and wrote a test scripts to load those images. It works fine.</p>
<p>The I add try … except and randomly choose another image when one image is failed to be loaded. The codes are shown below. Nevertheless, it stuck in the while loop and show the error message as shown below. From the error message, it can be known that another image is definetely been chosen. But all images are failed to be loaded. Anyone knows what happens?</p>
<pre><code class="lang-auto">import torch
import PIL
from PIL import Image
import os
import pandas as pd
import math
import numpy as np
import torchvision.datasets as tvdataset

import pdb
import cv2
from torch.utils.data import Dataset

class HotelID(Dataset):
      def __init__(self,img_root_dir,mask_dir,transform):

         self.img_root_dir = img_root_dir
         
         self.transform = transform

         self.data_list = []

         folders = os.listdir(img_root_dir)
         folders = sorted(folders)

         for folder_idx,folder_ in enumerate(folders):

             files = os.listdir(os.path.join(img_root_dir,folder_))
             files = sorted(files)

             for file in files:
                 self.data_list.append([os.path.join(img_root_dir,folder_,file),folder_idx])

         self.num_imgs = len(self.data_list)

      def __getitem__(self,idx):

          img_path = self.data_list[idx][0]
          label = self.data_list[idx][1]

          fail_flag = False

          img_name = img_path.split('/')[-1]
          img_folder = img_path.split('/')[-2]
          
          while True:
              try:

                 if fail_flag == True:
                    idx_ = np.random.choice(self.num_imgs,1,replace=False)[0]
                    img_path = self.data_list[idx_][0]
                    label = self.data_list[idx_][1]
                    img_name = img_path.split('/')[-1]
                    img_folder = img_path.split('/')[-2]
                    print(f"{img_name}\t{label}")

                 I = cv2.imread(img_path)

                 img_pil_ = Image.fromarray(I[:,:,::-1])
                 img_pil = self.transform(img_pil_)
                
                 print(f"{img_path}")
                 break

              except Exception as e:
                     fail_flag = True
                     print(f"{repr(e)}")
                     continue
          
          cv2.imwrite(os.path.join('./debug',img_folder+'_'+img_name),I)

          #img_pil_.save(os.path.join('./debug',img_folder+'_'+img_name[:-4]+'_pil.jpg'))

          return img_pil,label

      def __len__(self):
         return len(self.data_list)
          

def get_dataset(conf):

    conf['num_class'] = 3116

    transform_train = transforms.Compose([
        transforms.RandomCrop((conf.crop_size,conf.crop_size)),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))
    ])
    
    transform_test = transforms.Compose([
        transforms.CenterCrop((conf.crop_size,conf.crop_size)),
        transforms.ToTensor(),
        transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))
    ])

    ds_train = HotelID(conf.train_folder,conf.mask_folder,transform_train)
    #ds_train = tvdataset.ImageFolder(conf.train_folder, transform=transform_train)
    ds_test = tvdataset.ImageFolder(conf.test_folder, transform=transform_test)

    return ds_train,ds_test

</code></pre>
<pre><code class="lang-auto">000029619.jpg   813
000002340.jpg   2313
TypeError("'&lt;' not supported between instances of 'int' and 'NoneType'",)
000022355.jpg   1900
TypeError("'&lt;' not supported between instances of 'int' and 'NoneType'",)
000044926.jpg   381
000018797.jpg   2727
TypeError("'&lt;' not supported between instances of 'int' and 'NoneType'",)
TypeError("'&lt;' not supported between instances of 'int' and 'NoneType'",)
TypeError("'&lt;' not supported between instances of 'int' and 'NoneType'",)
TypeError("'&lt;' not supported between instances of 'int' and 'NoneType'",)
TypeError("'&lt;' not supported between instances of 'int' and 'NoneType'",)
TypeError("'&lt;' not supported between instances of 'int' and 'NoneType'",)
000023085.jpg   2375
000020744.jpg   852
000022277.jpg   2428
000040648.jpg   1594
000032900.jpg   874
000040367.jpg   174
000015278.jpg   1025
TypeError("'&lt;' not supported between instances of 'int' and 'NoneType'",)
TypeError("'&lt;' not supported between instances of 'int' and 'NoneType'",)
TypeError("'&lt;' not supported between instances of 'int' and 'NoneType'",)
000034317.jpg   3016
000025976.jpg   2082

</code></pre>

username: AlphaBetaGamma96
cooked: <p>The line below is failing because it expects all terms to be <code>ints</code>. However, as you load in an empty image it’s most likely defaulting to type <code>None</code>, and hence throws the error. Try removing those empty images from your directory and re-run your code. The error should go away.</p>
<aside class="quote no-group" data-username="KleinXin" data-post="1" data-topic="148943">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/letter_avatar_proxy/v4/letter/k/90db22/48.png" class="avatar"> KleinXin:</div>
<blockquote>
<pre><code class="lang-auto">    if h + 1 &lt; th or w + 1 &lt; tw:
</code></pre>
</blockquote>
</aside>

username: KleinXin
cooked: <p>I checked those images and wrote a test scripts to load those images. It works fine.<br>
I tried to use try … except to omit those images that are failed to be loaded. It also does not work. I will paste my codes after a while.</p>

username: AlphaBetaGamma96
cooked: <p>Can you check the output when it loads the empty images? It most likely returning type <code>None</code>.  Also, why do you need empty image files in a directory?</p>

username: KleinXin
cooked: <p>I print the shape of I and img_pil_out. They are all fine.</p>
<pre><code class="lang-auto">I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
img_pil_out.size: (256, 256)
img_pil_out.size: (256, 256)
img_pil_out.size: (256, 256)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
img_pil_out.size: (256, 256)
I.shape: (256, 256, 3)
img_pil_out.size: (256, 256)
img_pil_out.size: (256, 256)
I.shape: (256, 256, 3)
img_pil_out.size: (256, 256)
img_pil_out.size: (256, 256)
img_pil_out.size: (256, 256)
img_pil_out.size: (256, 256)
I.shape: (256, 256, 3)
img_pil_out.size: (256, 256)
img_pil_out.size: (256, 256)
I.shape: (256, 256, 3)
img_pil_out.size: (256, 256)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
I.shape: (256, 256, 3)
img_pil_out.size: (256, 256)
img_pil_out.size: (256, 256)
img_pil_out.size: (256, 256)
img_pil_out.size: (256, 256)
img_pil_out.size: (256, 256)
img_pil_out.size: (256, 256)
img_pil_out.size: (256, 256)
I.shape: (256, 256, 3)
img_pil_out.size: (256, 256)
img_pil_out.size: (256, 256)
img_pil_out.size: (256, 256)
img_pil_out.size: (256, 256)
Traceback (most recent call last):
  File "main.py", line 123, in &lt;module&gt;
    main(conf)
  File "main.py", line 85, in main

</code></pre>
<p>I also checked all the empty images in the input debug folder. Their corresponding images in the input directory are not empty. I also wrote a test script to load them from the input image.</p>
<p>For example, image whose name is 000023821.jpg in folder 203152. It is empty in debug folder, but it is not empty in input directory.</p>
<p><img src="https://discuss.pytorch.org/uploads/default/original/3X/1/0/10915df125f7aa84a1b65dedf8998b953a3e1005.png" alt="image" data-base62-sha1="2mz5nFWmmfuwfEK9UBWyyT4nEWN" width="465" height="106"></p>
<p><img src="https://discuss.pytorch.org/uploads/default/original/3X/e/3/e3566fdbef1ce18862f92102a9a40f06551495de.png" alt="image" data-base62-sha1="wr7zIxmxSExwYV5xGbfrsbAvhKe" width="367" height="54"></p>

username: AlphaBetaGamma96
cooked: <p>One thing you could try is that the line from where the error is originating is this line here.</p>
<aside class="quote no-group" data-username="KleinXin" data-post="1" data-topic="148943">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/letter_avatar_proxy/v4/letter/k/90db22/48.png" class="avatar"> KleinXin:</div>
<blockquote>
<pre><code class="lang-auto">    img_pil = self.transform(img_pil_out)
</code></pre>
</blockquote>
</aside>
<p>Some images work fine, and sometimes other images don’t. Potentially look at the images before they’re passed into <code>self.transform(img_pil_out)</code> via somthing like <code>plt.imshow</code> and see if there’s anything wrong with like <code>NaN</code> or <code>None</code> etc.</p>
<p>If I had to guess the precise error, <code>th</code> or <code>tw</code> is of type <code>None</code> most likely due to a fault in the input image as this is a standard function! Print out the images via <code>matplotlib.pyplot.imshow</code> and see if they’re ok. (Not via loading them from the directory)</p>
<p>An example would be,</p>
<pre><code class="lang-auto">import matplotlib.pyplot as plt

plt.imshow(img_pil_out)
plt.show()
</code></pre>
<p>You might find that it’s saved as an array of shape <code>(256,256)</code> but has all entries of <code>None</code> for example.</p>

username: KleinXin
cooked: <p>I am now working on a server which I access with MobaXterm. So I could not show the image with GUI. Instead I add some lines that do the transformation to the image to the end of <strong>init</strong> function. It has no problems with the two images saved by opencv and pillow. But ‘self.transform’ still gives the same error as below.</p>
<pre><code class="lang-auto">class HotelID(Dataset):
      def __init__(self,img_root_dir,mask_dir,transform):

         self.img_root_dir = img_root_dir
         
         self.transform = transform

         self.data_list = []

         folders = os.listdir(img_root_dir)
         folders = sorted(folders)

         for folder_idx,folder_ in enumerate(folders):

             files = os.listdir(os.path.join(img_root_dir,folder_))
             files = sorted(files)

             for file in files:
                 self.data_list.append([os.path.join(img_root_dir,folder_,file),folder_idx])

         self.num_imgs = len(self.data_list)
 
         img_folder = self.data_list[0][0].split('/')[-2]
         img_name = self.data_list[0][0].split('/')[-1]

         I = cv2.imread(self.data_list[0][0])
         cv2.imwrite(os.path.join('./debug',img_folder+'_'+img_name[:-4]+'_opencv.jpg'),I)
         I_pil = Image.fromarray(I[:,:,::-1])
         I_pil.save(os.path.join('./debug',img_folder+'_'+img_name[:-4]+'_pil.jpg')) 

        self.I = self.transform(I_pil)

</code></pre>
<pre><code class="lang-auto">File "datasets/hotel_id_2022.py", line 215, in get_dataset
    ds_train = HotelID(conf.train_folder,conf.mask_folder,transform_train)
  File "datasets/hotel_id_2022.py", line 96, in __init__
    self.I = self.transform(I_pil)
  File "/usr/local/lib/python3.6/dist-packages/torchvision/transforms/transforms.py", line 61, in __call__
    img = t(img)
  File "/usr/local/lib/python3.6/dist-packages/torch/nn/modules/module.py", line 1102, in _call_impl
    return forward_call(*input, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/torchvision/transforms/transforms.py", line 642, in forward
    i, j, h, w = self.get_params(img, self.size)
  File "/usr/local/lib/python3.6/dist-packages/torchvision/transforms/transforms.py", line 597, in get_params
    if h + 1 &lt; th or w + 1 &lt; tw:
TypeError: '&lt;' not supported between instances of 'int' and 'NoneType'

</code></pre>
<p>It looks so weird. Do you know why?</p>

username: KleinXin
cooked: <p>Maybe it is the problem of the transform I am using now?</p>
<pre><code class="lang-auto">transform_train = transforms.Compose([
        transforms.RandomCrop((conf.crop_size,conf.crop_size)),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))
    ])

</code></pre>