Apply transform on numpy arrays

username: deJQK
cooked: <p>If I have the dataset as two arrays X and y as images and labels, both are numpy arrays. I want to apply transforms (like those from models given by the pretrainedmodels package), how can apply them on my data, especially as the way as datasets.ImageFolder.</p>
<p>My numpy arrays are converted from PIL Images, and I found how to convert numpy arrays to dataset loaders <a href="https://stackoverflow.com/questions/44429199/how-to-load-a-list-of-numpy-arrays-to-pytorch-dataset-loader" rel="nofollow noopener">here</a>.</p>

username: yvanscher
cooked: <p>with not use toTensor() in your transform?</p>
<p>example here:</p>
<p><a href="https://pytorch.org/docs/master/torchvision/transforms.html#torchvision.transforms.Compose" class="onebox" target="_blank" rel="nofollow noopener">https://pytorch.org/docs/master/torchvision/transforms.html#torchvision.transforms.Compose</a></p>
<p>you can then reconvert your tensors to numpy using <code>.numpy()</code></p>
<p>example:</p>
<p><a href="https://pytorch.org/tutorials/beginner/former_torchies/tensor_tutorial.html#numpy-bridge" class="onebox" target="_blank" rel="nofollow noopener">https://pytorch.org/tutorials/beginner/former_torchies/tensor_tutorial.html#numpy-bridge</a></p>

username: deJQK
cooked: <p>Thanks <a class="mention" href="/u/yvanscher">@yvanscher</a>. But it seems that transforms accept img as input, not tensors. See the pil_loader function and DatasetFolder.__getitem__ method <a href="https://pytorch.org/docs/stable/_modules/torchvision/datasets/folder.html#ImageFolder" rel="nofollow noopener">here</a>.</p>

username: deJQK
cooked: <p>Now I decide to save the PIL image in the numpy arrays, without converting to numpy array with np.array(img). Then I might be able to use transform, and then TensorDataset and DataLoader …</p>

username: huangbiubiu
cooked: <p>You can also write a custom transformer which is very easy:</p>
<pre><code class="lang-auto">class Resize:
    def __init__(self, size):
        assert isinstance(size, int) or (isinstance(size, Iterable) and len(size) == 2)
        if isinstance(size, int):
            self._size = (size, size)
        else:
            self._size = size

    def __call__(self, img: np.ndarray):
        resize_image = skimage.transform.resize(img, self._size)
        # the resize will return a float64 array
        return skimage.util.img_as_ubyte(resize_image)
</code></pre>

username: Oli
cooked: <p>I love this image augmentation library called <a href="https://imgaug.readthedocs.io/en/latest/" rel="nofollow noopener">imgaug</a>. Sooooo nice!</p>

username: sytelus
cooked: <p>Docs says ToTensor() transform accepts PIL image or numpy array:</p>
<p><a href="https://pytorch.org/docs/stable/torchvision/transforms.html#torchvision.transforms.ToTensor" class="onebox" target="_blank" rel="nofollow noopener">https://pytorch.org/docs/stable/torchvision/transforms.html#torchvision.transforms.ToTensor</a></p>

username: nabsabs
cooked: <p>I’m super late to the party but I came across <a href="https://github.com/mlagunas/pytorch-nptransforms" rel="nofollow noopener">this great repo</a> that rewrote the base class to just use numpy arrays for the transformations</p>

username: farshid
cooked: <p>Please look at the following example:</p>
<pre><code class="lang-auto">import numpy as np
from torchvision import transforms

X = np.random.randint(low=0, high=255, size=(32,32,3), dtype=np.unit8)  # an image in ndarray format
your_transforms = transforms.Compose([transforms.CenterCrop(10),transforms.ToTensor(),])  # a set of transformations
if isinstance(X, np.ndarray):
    your_transforms.transforms.insert(0, transforms.ToPILImage())
</code></pre>
<p>Now given what you found on the other page, we can do this:</p>
<pre><code class="lang-auto">from torchvision.datasets import VisionDataset

class BasicVisionDataset(VisionDataset):
    def __init__(self, images, targets, transform=None, target_transform=None):
        if isinstance(images, np.ndarray):
            transform.transforms.insert(0, transforms.ToPILImage())
        super(BasicVisionDataset, self).__init__(root=None, transform=transform, target_transform=target_transform)
        assert len(images) == len(targets)

        self.images = images
        self.targets = targets

    def __getitem__(self, index):
        return self.transform(self.images[index]), self.targets[index]

    def __len__(self):
        return len(self.targets)
</code></pre>
<p>Please let me know if this works.</p>