How to load png using dataloader

TellonUK: <p>Could someone provide me some starter code for dataloader to load the following into pytorch</p>
<p>Folder - Data<br>
Folder - train<br>
Folder - 0<br>
3.png<br>
10.png<br>
13.png<br>
…<br>
Folder - 1<br>
2.png<br>
9.png<br>
16.png<br>
…<br>
…<br>
…</p>
<p>The folder name is the label for the data, each file is a 28x28 size png.</p>

ptrblck: <p>The easiest way would be to use <a href="http://pytorch.org/docs/master/torchvision/datasets.html#imagefolder">torchvision.ImageFolder</a>. This class uses assigns different classes to your folders.</p>
<p>The <a href="http://pytorch.org/docs/master/data.html#torch.utils.data.DataLoader">DataLoder</a> class wraps the <code>Dataset</code> and provides more functionalities like multi-processed loading, shuffling and batching.</p>
<p>Here is an example how your code might look like:</p>
<pre><code class="lang-auto">data_path = 'YOUR_PATH'
train_dataset = torchvision.ImageFolder(
    root=data_path,
    transform=torchvision.transforms.ToTensor()
)
train_loader = DataLoader(
    train_dataset,
    batch_size=64,
    num_workers=1,
    shuffle=True
)

for batch_idx, (data, target) in enumerate(train_loader):
    # your training procedure
</code></pre>

dimple: <p>i still not clear with applying transformations for images here.</p>

ianweb100: <p>Hi Patrick,</p>
<p>When we pass png images through the loader does it load as 28x28?</p>
<p>Thanks</p>
<p>Ian</p>

ptrblck: <p>The <code>DataLoader</code> calls into <code>Dataset.__getitem__</code> to get the current sample and creates a batch out of these samples. It can also use different samplers, a custom <code>collate_fn</code>, multiple workers etc.</p>
<p>The image tensor shape if defined in your <code>Dataset</code>, i.e. how you are loading and preprocessing the images. If you want to resize the tensors to a specific shape, you could use transformation such as  <code>torchvision.transforms.Resize</code> inside <code>Dataset.__getitem__</code>.</p>

ianweb100: <p>Hi Patrick,</p>
<p>Thank you for your explanation. What I have done is transformed body signals ( 4hz) into a graph using mathplotlib. I then save them as a png, so I have like 200 png files. I will try later today to load them using your tips. Let’s see how I go.</p>
<p>Note, and it goes without saying I am a very beginner in the world of deep learning.</p>
<p>Ian</p>

ptrblck: <aside class="quote no-group" data-username="ianweb100" data-post="6" data-topic="17079">
<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/i/9dc877/48.png" class="avatar"> ianweb100:</div>
<blockquote>
<p>Note, and it goes without saying I am a very beginner in the world of deep learning.</p>
</blockquote>
</aside>
<p>We all had to start at one point. <img src="https://discuss.pytorch.org/images/emoji/apple/wink.png?v=12" title=":wink:" class="emoji" alt=":wink:" loading="lazy" width="20" height="20"></p>
<p>Let me know, how it goes and if you get stuck.</p>

emcp: <p>I am attempting to take up this dataset ImageFolder… and my model expects a Tensor instead of the raw PNG Binary… but when I attempt to add the <code>transform.ToTensor</code> I get an error</p>
<pre><code class="lang-auto">    testing_dataset = ImageFolder(root=data_conf["demo_in_image_dir"], transform=transforms.Compose([transforms.ToTensor]))
</code></pre>
<p>error</p>
<pre><code class="lang-auto">  File "/home/emcp/anaconda3/envs/pytorch_150/lib/python3.7/site-packages/torchvision/transforms/transforms.py", line 61, in __call__
    img = t(img)
TypeError: ToTensor() takes no arguments
</code></pre>
<p><strong>EDIT:</strong><br>
I found the solution, seems I need to call <code>toTensor()</code></p>
<aside class="quote" data-post="1" data-topic="12663">
  <div class="title">
    <div class="quote-controls"></div>
    <img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/prateekagarwal3/48/3183_2.png" class="avatar">
    <a href="https://discuss.pytorch.org/t/torchvision-transforms-totensor-img-not-working/12663">torchvision.transforms.ToTensor(img) not working</a> 
  </div>
  <blockquote>
    imgTensor = torchvision.transforms.ToTensor(img) 
TypeError: object() takes no parameters 
getting this issue, but when I checked the documentation the function is suppose to use image as a parameter
  </blockquote>
</aside>


ianweb100: <p>Hi Patrick,</p>
<p>If i have a array which is ( 40,1) can I still use a 2d CNN?</p>
<p>Ian</p>

ptrblck: <p>It depends a bit what the dimensions represent.<br>
If dim0 is the batch dimension and you are only dealing with a single feature, you could try to use transposed convolutions to upsample the single sample.<br>
On the other hand, if both dimensions represent some kind of features, you could try to reshape the input to e.g. an image tensor of <code>[batch_size, 1, 8, 5]</code> and create a custom CNN which could deal with these tiny images.</p>
<p>Note that CNNs try to use the spatial features of your data. If your data doesn’t contain any correlation between neighboring values, I would rather stick to linear layers.</p>

ianweb100: <p>Hi Patrick, I am dealing with body signals as responses from certain stimuli, and I need to use this stimulus to classify a class. So far I manage to get the 1d working Thank so much)</p>
<p>But for example, you can use libraries such as librosa to transform the sound into signals representations. Its is just a time series of 40 or 80 points, but there is a time attached, so they correlate.</p>
<p>When Inspect the images which are a time series, there are not really a lot of similarities in the curves. So what I am doing is trying to normalize and centre all the signals first. Once this is done I am planning to save these images as png in a folder. Load as a picture and then classify using a conv2d.<br>
<img src="https://discuss.pytorch.org/uploads/default/original/3X/f/7/f7ca06fe2f4bfe5ed642acda217580a5ca1b2dac.png" alt="Figure 2020-05-05 221119" data-base62-sha1="zm2M9KliZSk5P00bs3sgl0rFBec" width="370" height="262"></p>
<p>Thanks</p>
<p>Ian</p>

ptrblck: <p>Are you planning on saving images of the waveform and classify it with a CNN?<br>
This might work, if you see that these waveforms differ enough between classes.<br>
However, I would also recommend to check, if creating spectra wouldn’t work better.</p>

ianweb100: <p>But if I make a spectogram , do i then use a 1d cnn ? of still can do the 2d cnn?</p>
<p>Ian</p>

ptrblck: <p>The spectrogram should have a fequency and time axis and would contain the amplitude in each “pixel”, so you could use a 2D CNN.</p>

ianweb100: <p>The spectrums might not work because its is a 4hz signal</p>

ianweb100: <p>Hi Patrick,</p>
<p>Saved the images as png to try fitting a 2d CNN, really struggling to load a png properly. I think im not that far. I’ve followed the PyTorch tutorial then had a PIL error, got some help and fix that, now another error:</p>
<p>PicklingError: Can’t pickle &lt;class ‘<strong>main</strong>.MyDataset’&gt;: it’s not the same object as <strong>main</strong>.MyDataset</p>
<p>My pipeline so far is below:</p>
<pre><code>class MyDataset(Dataset):
"""Face Landmarks dataset."""

def __init__(self, csv_file, root_dir, transform=None):

    self.image_frame = pd.read_csv(csv_file)
    self.root_dir = root_dir
    self.transform = transform

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

def __getitem__(self, idx):
    if torch.is_tensor(idx):
        idx = idx.tolist()

    img_name = os.path.join(self.root_dir,
                            self.image_frame.iloc[idx, 0])
    
    image = Image.open(img_name)
    sample = {'image': image}

    if self.transform:
        sample = self.transform(sample)

    return sample
 
## Data transforms
</code></pre>
<h1></h1>
<pre><code>data_transforms = transforms.Compose([
    transforms.Grayscale(num_output_channels=1),
    transforms.Resize(256),
    transforms.CenterCrop(256),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],
                     std=[0.229, 0.224, 0.225] )])
</code></pre>
<h2>Open and transform the data</h2>
<h1></h1>
<pre><code>transformed_dataset = MyDataset(csv_file='metadata.csv',
                                       root_dir="C:/Users/JOBS/Desktop/comp 8420 NN/Assignment_2/figures/",
                                       transform = transformed_dataset)    
</code></pre>
<h2>Load data</h2>
<h1></h1>
<pre><code>dataloader = DataLoader(transformed_dataset, batch_size=4,
                    shuffle=True, num_workers=4)</code></pre>

ptrblck: <p>Could you use <code>num_workers=0</code> and check, if the code is working?<br>
If yes, then you might have forgotten the if-clause protection for Windows as explained <a href="https://pytorch.org/docs/stable/notes/windows.html#multiprocessing-error-without-if-clause-protection">here</a>.</p>

ianweb100: <p>Sort of worked but having issues with the target variable, I thought by setting the images on folder 1/2/3 respectively would’ve loaded the target correctly.</p>
<p>I followed some of the other comments you had for other people on how to unsqueeze the data and so on, But my target comes out of the loader as an int, not an an ‘I guess’ hot encode PyTorch tensor?</p>
<p>if I print right after input, i get a torch.Size([1, 256, 256]) and the output is just a integer.</p>
<p>I did some transformations, but i think i am doing the wrong thing because my train loss is fixed.</p>
<p>Why are the labels not loaded properly as a long encode when using image folder?</p>
<p>I did this:</p>
<pre><code>    inputs = inputs.unsqueeze(0)
    labels = torch.tensor(labels).unsqueeze(0)
</code></pre>
<p>Ian</p>
<p>But i think the shape of the target is not right.</p>

ptrblck: <p>Could you print the shape of your input, output, and target tensors?<br>
By “output is just an integer”, do you mean a scalar tensor or a Python integer?<br>
How did you set the folders to 1/2/3?</p>

ianweb100: <p>I sent you a comprehensive answer on the other post. Cheers</p>