How to load png using dataloader

The easiest way would be to use torchvision.ImageFolder. This class uses assigns different classes to your folders.

The DataLoder class wraps the Dataset and provides more functionalities like multi-processed loading, shuffling and batching.

Here is an example how your code might look like:

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
1 Like

i still not clear with applying transformations for images here.

Hi Patrick,

When we pass png images through the loader does it load as 28x28?

Thanks

Ian

The DataLoader calls into Dataset.__getitem__ to get the current sample and creates a batch out of these samples. It can also use different samplers, a custom collate_fn, multiple workers etc.

The image tensor shape if defined in your Dataset, 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 torchvision.transforms.Resize inside Dataset.__getitem__.

Hi Patrick,

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.

Note, and it goes without saying I am a very beginner in the world of deep learning.

Ian

We all had to start at one point. :wink:

Let me know, how it goes and if you get stuck.

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 transform.ToTensor I get an error

    testing_dataset = ImageFolder(root=data_conf["demo_in_image_dir"], transform=transforms.Compose([transforms.ToTensor]))

error

  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

EDIT:
I found the solution, seems I need to call toTensor()

Hi Patrick,

If i have a array which is ( 40,1) can I still use a 2d CNN?

Ian

It depends a bit what the dimensions represent.
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.
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 [batch_size, 1, 8, 5] and create a custom CNN which could deal with these tiny images.

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.

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)

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.

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.
Figure 2020-05-05 221119

Thanks

Ian

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

But if I make a spectogram , do i then use a 1d cnn ? of still can do the 2d cnn?

Ian

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

The spectrums might not work because its is a 4hz signal

Hi Patrick,

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:

PicklingError: Can’t pickle <class ‘main.MyDataset’>: it’s not the same object as main.MyDataset

My pipeline so far is below:

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

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] )])

Open and transform the data

transformed_dataset = MyDataset(csv_file='metadata.csv',
                                       root_dir="C:/Users/JOBS/Desktop/comp 8420 NN/Assignment_2/figures/",
                                       transform = transformed_dataset)    

Load data

dataloader = DataLoader(transformed_dataset, batch_size=4,
                    shuffle=True, num_workers=4)

Could you use num_workers=0 and check, if the code is working?
If yes, then you might have forgotten the if-clause protection for Windows as explained here.

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.

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?

if I print right after input, i get a torch.Size([1, 256, 256]) and the output is just a integer.

I did some transformations, but i think i am doing the wrong thing because my train loss is fixed.

Why are the labels not loaded properly as a long encode when using image folder?

I did this:

    inputs = inputs.unsqueeze(0)
    labels = torch.tensor(labels).unsqueeze(0)

Ian

But i think the shape of the target is not right.

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

I sent you a comprehensive answer on the other post. Cheers

Was there changes in DataImageFolder after 2019? I have this DL program which I made 2019, and I need to revisit it and actually use the then taught NN to classify new data. I didn’t have then any sub-folders, but all images were in root image dir. “path/to/images/” Now using the same code, it complains it cannot find any sub-folders. Is there some quick method to use the old way of working?
“FileNotFoundError: Couldn’t find any class folder in ./path/to/images/.”