'What is the correct way of loading NumPy images from npy file into a PyTorch tensor?

The following code loads a bunch of images (the Kaggle cats and dogs dataset) and stores those into a npy file. The file can then be loaded for further processing, which in my case is converting the data inside to PyTorch tensors and iterating over it using the PyTorch DataLoader.

Note: All images are loaded from JPG files as grayscale (uint8) and resized (see img_size class member)

class DataLoaderRaw():
    img_size = 50
    cats = 'PetImages/Cat'
    dogs = 'PetImages/Dog'
    pet_labels = {cats: 0, dogs: 1}
    data = []
    catcount = 0
    dogcount = 0


    def make_training_data(self):
        for pet_label in self.pet_labels:
            print('Loading pet data from', pet_label)

            for img_path in os.listdir(pet_label): # tqdm(...)
                pet_img_path = os.path.join(pet_label, img_path)
                try:    
                    pet_img = cv2.imread(pet_img_path, cv2.IMREAD_GRAYSCALE)
                    pet_img = cv2.resize(pet_img, (self.img_size, self.img_size), interpolation=cv2.INTER_CUBIC)

                    self.data.append([np.array(pet_img), np.eye(2)[self.pet_labels[pet_label]]])

                    if pet_label == self.cats:
                        self.catcount += 1
                    elif pet_label == self.dogs:
                        self.dogcount += 1

                except Exception as ex:
                    pass
                    #print('Failed to load', pet_img_path)

        self.data = np.array(self.data)
        np.random.shuffle(self.data)
        np.save('data.npy', self.data)        
        print('Dataset statistics:')
        print('Total samples:', len(self.data))
        print('Cat samples:', self.catcount)
        print('Dog samples:', self.dogcount)

    def from_np_file(path='data.npy'):
        data = np.load(path, allow_pickle=True)
        dlr = DataLoaderRaw()
        dlr.data = data
        return dlr

rebuild_data = False

if rebuild_data:
    print('Rebuilding data')
    dlr = DataLoaderRaw()
    dlr.make_training_data()
else:
    print('Loading data')
    dlr = DataLoaderRaw.from_np_file('data.npy')

Simply doing

data = torch.from_numpy(dlr.data)

yields

TypeError: can't convert np.ndarray of type numpy.object_. The only supported types are: float64, float32, float16, complex64, complex128, int64, int32, int16, int8, uint8, and bool.

I tried doing

data = torch.Tensor([torch.from_numpy(img[0]) for img in dlr.data])

where the first element of every element img is the large array that contains the pixel data, but I get a warning

Creating a tensor from a list of numpy.ndarrays is extremely slow. Please consider converting the list to a single numpy.ndarray with numpy.array() before converting to a tensor.

Printing the type of dlr.data yields object. And here is the first element so that you can get some perspective on what's inside:

[[array([[127, 137, 186, ...,  39,  36,  31],
         [127, 132, 166, ...,  31,  32,  38],
         [220, 207, 195, ...,  28,  40,  40],
         ...,
         [117, 115, 120, ..., 110,  30,  22],
         [113, 104, 110, ..., 184,  36,  26],
         [127, 129, 130, ..., 184,  27,  29]], dtype=uint8)
  array([1., 0.])]
  ...
]]

What is the correct way of loading NumPy images from npy file into a PyTorch tensor?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source