Storing images as tensor?

I was thinking that would it be better to store and load images present as tensors?
In general I load images with opencv or PIL and converting them to tensors, if I converted my data into tensor and dump them would it be faster while loading??

You can try Dataloader, which doesn’t require to actually load all images in memory at any point.

You can read more about it here: https://pytorch.org/docs/stable/data.html
tutorial: https://github.com/pytorch/tutorials/blob/master/beginner_source/data_loading_tutorial.py

Yeah I know about it, I was thibking about optimizing everytime __geittem__ is called, you have to load images so what is better to load, image itself or image stored as a tensor

If you don’t want to transform your images, you could load them as tensors.
However, if you do need a transformation, you would have to transform the tensors back to PIL.Images, apply the augmentation/transformation, and transform them back to tensors.
This shouldn’t be too bad regarding the performance, but can be annoying.

On the other hand do you want to load single images/tensors?
If so, I think you won’t get any performance improvement:

x = torch.empty(3, 224, 224).uniform_(0, 1)
img = transforms.ToPILImage()(x)

# save
torch.save(x, 'tensor_image.pth')
img.save('pil_image.png')

%timeit torch.load('tensor_image.pth')
> 1000 loops, best of 3: 206 µs per loop
%timeit Image.open('pil_image.png')
> 10000 loops, best of 3: 86.6 µs per loop

I think you’ll be faster if you load a whole batch of tensors.

1 Like

Oh torch.load is slower! I thought it would have been efficient!
I guess due to pickle backend perhaps?!

I think you’ll be faster if you load a whole batch of tensors.

Yeah perhaps loading multiple images consecutively would (SHOULD!) be slower compared to loading tensor at once.

Thanks!

I think the tensor is just too small to get a significant performance boost.

That’s what I think, too.

Just as a followup modified the script for loading and comparing multiple images
Even for loading 19 images at once loading tensor greatly outperform other methods

from PIL import Image
import torch
import torchvision.transforms as transforms
import timeit
import cv2

K = 19

x = torch.zeros(3, 224, 224).uniform_(0, 1)
img = transforms.ToPILImage()(x)

for i in range(K):
	img.save(str(i) + ".png")


x = x.unsqueeze(0).expand(K,3,224,224)
torch.save(x, 'tensor_images.pth')

def loading1():
	torch.load('tensor_images.pth')

def loading2():
	for i in range(K):
		Image.open(str(i) + ".png")

def loading3():
	for i in range(K):
		cv2.imread(str(i) + ".png")

And the outputs

>>> timeit.timeit(loading1, number=100000)
14.435413494997192
>>> timeit.timeit(loading2, number=100000)
95.70677890698425

That’s great. What about the filesize? Is there any significant pytorch-specific overhead?

Stored only 19 images so can’t say much but yeah file sizes are smaller by factor of about 2

1 Like

Hey I am facing the same consideration. I think in your performance test you should really compare loading image stored as tensors vs as .PNG + CONVERTING to tensor because you will have to make this conversion eventually.

Also keep in mind that if you want to use .PNG files in a traditional Dataset class, you will have to load the tensors one by one in the get_item() method, possibly negating your detected performance boost as stated by @ptrblck

Here maybe some other things to consider as well:
-single image files are much easier to inspect and search for possible errors (e.g. by sorting images by size and looking at the extremes).
-copying/moving single image files is very slow compared to a single .pt file. You will essentially have to zip/unzip to move your dataset around to avoid the system having to handle every single file.
-single image files can be lazily loaded using Dataloaders, while a single .pt file needs to be loaded as a whole in a Datasets init method