How to load Images without using 'ImageFolder'

username: alx
cooked: <p>Hey! In all my previous work I’ve always used:</p>
<pre><code class="lang-auto">torchvision.datasets.ImageFolder(root='', transform=trsfm)
</code></pre>
<p>I am now in a situation where my data is not split into subfolder:<br>
root/dog/xxx.png<br>
root/cat/asd932_.png</p>
<p>but rather:<br>
root/asd932_.png<br>
root/asd933_.png</p>
<p>What I’m trying to do is predict new images (with no labels) from a trained model.</p>
<p>How do people load there images when working on an unsupervised model?</p>

username: JuanFMontesinos
cooked: <p>You can write your custom dataset <a href="https://pytorch.org/docs/stable/data.html#torch.utils.data.Dataset" rel="nofollow noopener">https://pytorch.org/docs/stable/data.html#torch.utils.data.Dataset</a><br>
and to load any kind of data format.</p>

username: zimmer550
cooked: <p>Write your own dataset class:</p>
<pre><code class="lang-auto">class CustomDataSet(Dataset):
    def __init__(self, main_dir, transform):
        self.main_dir = main_dir
        self.transform = transform
        all_imgs = os.listdir(main_dir)
        self.total_imgs = natsort.natsorted(all_imgs)

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

    def __getitem__(self, idx):
        img_loc = os.path.join(self.main_dir, self.total_imgs[idx])
        image = Image.open(img_loc).convert("RGB")
        tensor_image = self.transform(image)
        return tensor_image
</code></pre>
<p>Then call the Dataset class and Dataloader:</p>
<pre><code class="lang-auto">my_dataset = CustomDataSet(img_folder_path, transform=trsfm)
train_loader = data.DataLoader(my_dataset , batch_size=batch_size, shuffle=False, 
                               num_workers=4, drop_last=True)
</code></pre>
<p>Then iterate:</p>
<pre><code class="lang-auto">for idx, img in enumerate(train_loader):
    #do your training now
</code></pre>

username: alx
cooked: <p><code>NameError: name 'Dataset' is not defined</code>?</p>

username: sperry
cooked: <p>from torch.utils.data import Dataset</p>

username: alx
cooked: <p>Thanks! I think there’s another mistake<br>
<code>self.total_imgs = natsort.natsorted(all_imgs)</code><br>
to<br>
<code>self.total_imgs = natsorted(all_imgs)</code></p>
<p>Do you have a custom loader as well?</p>

username: sperry
cooked: <p>Yes, it’s pretty common to write your own.</p>
<p>You have a lot of freedom to implement the <strong>len</strong> and <strong>getitem</strong> methods to accommodate your use case, folder structure, etc.</p>
<p><strong>len</strong> needs to return the size of the dataset</p>
<p><strong>getitem</strong> needs to return your image tensor for the image with index ‘idx’. You can also return labels, bounding boxes, etc as required for training.</p>
<p>Transforms can be leveraged, but aren’t required.</p>
<p>The sample code above should work… Just pass in your image folder path when you instantiate the DataSet.</p>
<p>ex:   my_dataset = CustomDataSet(“path/to/root/”, transform=your_transforms)</p>
<p>If you aren’t using transforms, remove the 3 references to transform in your CustomDataSet code.</p>

username: dcprime
cooked: <p>I know this is a bit of an old discussion at this point, but I’m looking for some similar help.</p>
<p>I need to load data into a 3D CNN. My data are sets of JPG images (“video frames”) that represent gestures being performed.</p>
<p>How can I create a custom Dataset class to accommodate this  situation? And how do my classification labels get added to my data for training purposes?</p>
<p>Thanks for your help!</p>

username: ptrblck
cooked: <p>It depends a bit on the current structure of your data.<br>
Generally, if you are implementing a custom <code>Dataset</code>, you would need to implement:</p>
<ul>
<li>the <code>__getitem__(self, index)</code> method, which uses the passed <code>index</code> to load a single “sample” of the dataset</li>
<li>the <code>__len__(self)</code> method, which returns the length of the dataset and thus defines the indices to be sampled from the range <code>[0, self.__len__()]</code>
</li>
<li>as well as the <code>__init__</code> method, if you want, to pass e.g. image paths, tansformations etc.</li>
</ul>
<p>If your images are all in a single folder and can be loaded sequentially, you could define a <code>window_length</code> in the <code>__init__</code> and load multiple frames in <code>__getitem__</code>. I assume the target would be a single class index for the complete sequence.</p>
<p>It’s a bit hard to give a good recommendation without knowing your use case.</p>

username: dcprime
cooked: <p>To describe my use case in a bit more detail:</p>
<p>We are attempting to classify gestures using a 3D CNN. Each gesture is captured as a series of JPG frames and indexed as a start_frame number and an end_frame number. There are 8 gestures to identify altogether.</p>
<p>Currently the data is saved in a separate directory for each Subject who performed the 8 gestures, but it’s our own dataset and we can alter the directory structure in any way we choose.</p>
<p>One aspect I don’t understand is how the network is made aware of the class labels. Are the classes (output targets) derived from the directory structure by DataLoader() somehow? And how can I separate my training and validation data appropriately?</p>

username: ptrblck
cooked: <p>You can define the targets as you wish. <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>
<p>The <code>DataLoader</code> is not responsible for the data and target creation, but allows you to automatically create batches, use multiprocessing to load the data in the background, use custom samplers, shuffle the dataset etc.</p>
<p>The <code>Dataset</code> defines how the data and target samples are created.<br>
<code>torchvision.datasets</code> provide some “standard approaches”, such as <code>ImageFolder</code>, which creates the targets based on the subfolders passed in the <code>root</code> argument (subfolders will be sorted and each folder will get an own class label).<br>
However, this use case might be too limited for your use case, so that I would recommend to implement a custom <code>Dataset</code>.<br>
<a href="https://pytorch.org/tutorials/beginner/data_loading_tutorial.html">This tutorial</a> gives you a good overview on creating a <code>Dataset</code> and use a <code>DataLoader</code>.</p>
<p>As described, the <code>__getitem__</code> method would be responsible to load the data and target (or create the target based on some properties).<br>
Before changing the data structure, let’s think about how the batches should be created.<br>
I.e. would it be possible to create a batch given a single index using the current data structure?</p>

username: dcprime
cooked: <p>Thanks for your help! I was able to write a custom Dataset object that worked for me.</p>
<p>I just needed to understand that Dataset’s job is to return a single training example, and how the target for that example is returned by Dataset.</p>

username: akib62
cooked: <p>Hello <a class="mention" href="/u/sperry">@sperry</a> <a class="mention" href="/u/zimmer550">@zimmer550</a> ,</p>
<p>I am using the same code you gave here for creating the custom dataset. Then, as per your guidance, I am giving the path of my dataset like below:</p>
<pre><code>train_data_dir = '/home/Houses-dataset-master'

# Transformation
transform = transforms.Compose([
transforms.Resize((256, 256)),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

# Giving the path 
train_data_tensor = CustomDataSet(train_data_dir, transform=transform)

# trying to  print the length of the train_data_tensor
print(len(train_data_tensor))
</code></pre>
<p>But, first I was getting an error for <code>natsort</code></p>
<pre><code> NameError: name 'natsort' is not defined
</code></pre>
<p>Then, I remove the <code>natsort</code> and replaced all <code>total_imgs</code> with <code>all_imags</code>.</p>
<p>But, getting another error:</p>
<pre><code> AttributeError: 'CustomDataSet' object has no attribute 'all_imgs'
</code></pre>
<p>Could you tell me, how can I solve this error?</p>
<p>Updated: Full error problem is given in <a href="https://discuss.pytorch.org/t/why-my-custom-dataset-is-not-working/105558">here</a></p>

username: kkris88
cooked: <p>you can pip install natsort</p>