Pytorch: загрузка набора данных изображений в градациях серого - PullRequest
1 голос
/ 07 февраля 2020

Я хочу загрузить набор изображений в градациях серого. Я использовал ImageFolder, но по умолчанию он не загружает серые изображения, поскольку он преобразует изображения в RGB.

Я нашел решения, которые загружают изображения с помощью ImageFolder и после преобразования изображений в оттенках серого, используя:

transforms.Grayscale(num_output_channels=1)

или

ImageOps.grayscale(image)

Это правильно? Как я могу загрузить изображения в градациях серого без преобразования? Я пытаюсь ImageDataBunch, но у меня проблемы с импортом fastai.vision

Ответы [ 3 ]

1 голос
/ 21 марта 2020

Предполагая, что набор данных хранится в папке «Набор данных», как указано ниже, установите для каталога root значение «Набор данных»:

Набор данных

  • class_1
    • img1.png
    • img2.png
  • class_2
    • img1.png
    • img2.png
from torchvision.datasets import ImageFolder
from torch.utils.data import DataLoader, random_split
from torchvision import transforms

root = 'Dataset/'

data_transform = transforms.Compose([transforms.Grayscale(num_output_channels=1),
                                     transforms.ToTensor()])
dataset = ImageFolder(root, transform=data_transform)

Для справки набор данных о поездах и тестах делится на 70% и 30% соответственно.

# Split test and train dataset 
train_size = int(0.7 * len(dataset))
test_size = len(dataset) - train_size
train_data, test_data = random_split(dataset, [train_size, test_size])

Этот набор данных может быть далее разделен на поезда и тесты загрузчики данных, как указано ниже, для выполнения операций в пакетном режиме.

Обычно вы увидите, что для набора данных один раз назначен batch_size, который будет использоваться как для поезда, так и для тестовых загрузчиков. Но я пытаюсь определить это отдельно. Идея состоит в том, чтобы задать размер batch_size таким, чтобы он определял размер загрузчика данных поезда / теста, иначе он выдаст ошибку.

# Set batch size of train data loader
batch_size_train = 20

# Set batch size of test data loader
batch_size_test = 22

# load the split train and test data into batches via DataLoader()
train_loader = DataLoader(train_data, batch_size=batch_size_train, shuffle=True)
test_loader = DataLoader(test_data, batch_size=batch_size_test, shuffle=True)
1 голос
/ 07 февраля 2020

Да, это правильно, и AFAIK pillow по умолчанию загружает изображения в RGB, см., Например, ответы на этот вопрос . Таким образом, преобразование в grayscale является единственным способом, хотя и требует времени.

Решение Pure Pytorch (если ImageFolder не подходит)

Вы можете развернуть собственную загрузку данных функциональности и на вашем месте я бы не стал go fastai прокладывать маршрут, так как он довольно высокого уровня и отнимает у вас контроль (вам, возможно, не понадобятся эти функции в любом случае).

В принципе, все, что у вас есть Чтобы сделать это, создайте что-то вроде этого ниже:

import pathlib

import torch
from PIL import Image


class ImageDataset(torch.utils.data.Dataset):
    def __init__(self, path: pathlib.Path, images_class: int, regex="*.png"):
        self.files = [file for file in path.glob(regex)]
        self.images_class: int = images_class

    def __getitem__(self, index):
        return Image.open(self.files[index]).convert("LA"), self.images_class


# Assuming you have `png` images, can modify that with regex
final_dataset = (
    ImageDataset(pathlib.Path("/path/to/dogs/images"), 0)
    + ImageDataset(pathlib.Path("/path/to/cats/images"), 1)
    + ImageDataset(pathlib.Path("/path/to/turtles/images"), 2)
)

Выше вы получите изображения по указанным выше путям, и каждое изображение вернет соответствующий предоставленный класс.

Это дает вам больше гибкости ( настройка папки отличается от torchvision.datasets.ImageFolder) для нескольких строк.

Из c, вы можете добавить больше или использовать l oop или что-то еще. Вы также можете применить torchvision.transforms, например, преобразовав изображения выше в тензоры, прочитав

Torchdata Solution

Отказ от ответственности, автор здесь . Если вы обеспокоены временем загрузки ваших данных и преобразованием grayscale, вы можете использовать torchdata стороннюю библиотеку для pytorch.

Используя ее, можно создать то же самое, что и выше, но используйте cache или map (чтобы легко использовать torchvision.transforms или другие преобразования) и некоторые другие известные вещи, например, из модуля tensorflow.data, см. ниже:

import pathlib

from PIL import Image

import torchdata


# Change inheritance
class ImageDataset(torchdata.Dataset):
    def __init__(self, path: pathlib.Path, images_class: int, regex="*.png"):
        super().__init__()  # And add constructor call and that's it
        self.files = [file for file in path.glob(regex)]
        self.images_class: int = images_class

    def __getitem__(self, index):
        return Image.open(self.files[index]), self.images_class


final_dataset = (
    ImageDataset(pathlib.Path("/path/to/dogs/images"), 0)
    + ImageDataset(pathlib.Path("/path/to/cats/images"), 1)
    + ImageDataset(pathlib.Path("/path/to/turtles/images"), 2)
).cache()  # will cache data in-memory after first pass
# You could apply transformations after caching for possible speed-up

torchvision ImageFolder loader

Как правильно указано @jodag в комментариях, можно использовать loader, вызываемый с одним аргументом path, чтобы сделать настраиваемое открытие данных, например, для оттенков серого это может быть:

from PIL import Image

import torchvision

dataset = torchvision.datasets.ImageFolder(
    "/path/to/images", loader=lambda path: Image.open(path).convert("LA")
)

Обратите внимание, что вы также можете использовать его для других типов файлов, это не обязательно изображения.

0 голосов
/ 04 апреля 2020

Создание пользовательского загрузчика, подача его в ImageFolder:

import numpy as np
from PIL import Image, ImageOps

def gray_reader(image_path):
    im = Image.open(image_path)
    im2 = ImageOps.grayscale(im)
    im.close()
    return np.array(im2)   # return np array
    # return im2           # return PIL Image

some_dataset = ImageFolder(image_root_path, loader=gray_reader)

Редактирование:

Ниже код намного лучше, чем предыдущий, получите цветное изображение и преобразуйте в оттенки серого в transform ()

def get_transformer(h, w):
    valid_transform = transforms.Compose([            
        transforms.ToPILImage(),                                    
        transforms.Grayscale(num_output_channels=1),
        transforms.Resize((h, w)),                                    
        transforms.ToTensor(),                                    
        transforms.Normalize([0.5], [0.5]) ])
    return valid_transform
...