Большинству моделей требуется хороший объем данных для обучения, тестирования и проверки. Эти данные не всегда легко доступны для удовлетворения потребностей созданной вами модели. Расширение данных — это отличный способ получить больше от уже имеющихся данных.
Недавно мне нужно было создать модель оптического распознавания символов для сценария, который был необычным и над которым раньше особо не работали, поэтому мне нужно было получить рукописные образцы, но я не мог получить достаточное количество рукописных образцов, попросив друзей за помощь или аутсорсинг работы.
В дело вступает магия аугментации: вместо того, чтобы рисовать все возможные вариации персонажа в сценарии, вы рисуете несколько из них вручную и выполняете аугментацию. Мы сможем получить множество изображений из одного изображения, используя увеличение изображения.
PyTorch имеет доступный модуль под названием torchvision.transforms, который позволяет нам дополнять изображения различными способами, позволяя нам создавать несколько изображений из одного изображения, что, в свою очередь, помогает нам создавать более плотный набор данных. Во-первых, мы рассмотрим некоторые базовые дополнения с помощью torchvision.transforms, а в конце закончим скриптом, который позволит вам анализировать иерархические папки изображений, дополнять их, а затем сохранять в той же иерархической структуре. . Модуль torchvision.transforms делает выполнение аугментации очень плавным и простым.
Все это можно сделать и с библиотекой OpenCV, но мы ее использовать не будем.
Прежде чем двигаться дальше, убедитесь, что все эти библиотеки установлены, импортированы и готовы к работе. (используя блокнот ipython)
import PIL import torch from PIL import Image from pathlib import Path import matplotlib.pyplot as plt import numpy as np import sys import torchvision.transforms as T
Очевидно, нам понадобится изображение для работы, иначе вся статья будет лишней. Поскольку я хотел бы думать, что у меня есть немного радости в жизни, я не буду использовать рукописное письмо или что-то скучное вместо этого, мы будем использовать изображение милого золотистого ретривера.
Давайте откроем изображение с помощью библиотеки PIL.Image и сохраним его в переменной с именем orig_img.
orig_img = PIL.Image.open(Path('dog.png'))
Теперь давайте покажем изображение, с которым мы будем работать, используя библиотеку matplotlib.pyplot (plt.imshow(path)).
np.asarray(orig_img).shape plt.imshow(orig_img) orig_img.show()
Теперь давайте повозимся и расчленим это изображение.
1. Измените размер изображения
Иногда изображения слишком велики для обработки, поэтому мы изменяем их размер, чтобы наши модели можно было эффективно обучать. Имейте в виду, что этот процесс необходимо выполнять для всех изображений, даже после увеличения, поскольку сверточные нейронные сети обучаются только на данных изображений одинакового размера. С другой стороны, рекуррентные нейронные сети — это то, с чем вы можете весело провести время, они будут обучаться на любом размере.
resize_transform = T.Resize((32,32)) resized_image=resize_transform(orig_img) plt.imshow(resized_image)
2. Преобразование изображения в оттенки серого
Преобразование изображения в представление в градациях серого используется для извлечения дескрипторов из изображения, преобразование изображения в градации серого требует меньше вычислительных ресурсов, чем обработка изображения в цвете. В OpenCV также есть очень простой способ преобразования изображений в оттенки серого, я бы сказал, что это примерно столько же усилий, но это для другой статьи.
grayscale_transform = T.Grayscale(3) grayscaled_image=grayscale_transform(orig_img) plt.imshow(grayscaled_image)
3. Вращение изображения
Поворот изображения — это обычная процедура обработки изображений, которая дает модели различные функции для извлечения и сопоставления. Это также помогает увеличить размер обучающих данных за счет создания различных точек зрения для модели, на которой она будет обучаться. Я выполнил 3 поворота на 45°, 65° и 85° соответственно, вы можете установить его случайным образом или указать свои собственные углы поворота.
random_rotation_transformation_45 = T.RandomRotation(45) random_rotation_transformation_85 = T.RandomRotation(85) random_rotation_transformation_65 = T.RandomRotation(65) plt.imshow(random_rotation_transformation_45(orig_img))
plt.imshow(random_rotation_transformation_85(orig_img))
plt.imshow(random_rotation_transformation_65(orig_img))
4 . Случайный урожай
В ситуациях реального времени объекты не всегда полностью видны на изображении или в том же масштабе, что и наши обучающие данные, поэтому, когда мы обучаем нашу модель, мы хотим добавить немного разнообразия в набор данных, просто обучая модель на части изображения, чтобы он мог сделать точный прогноз, даже когда весь объект не виден (да, я знаю, что не могу назвать собаку объектом, но сейчас не время быть политкорректным), поэтому мы обрезать изображение и создать новое изображение из обрезанной части.
size_of_crop = 560 random_crops = T.RandomCrop(size = size_of_crop) required_image = random_crops(orig_img) plt.imshow(required_image)
5. Размытие по Гауссу
Размытие по Гауссу используется для удаления шума и пятен с изображения. Размытие по Гауссу выполняется путем сглаживания вектора изображения с помощью функции Гаусса. Это помогает удалить высокочастотные компоненты, которые вызывают обучение ложных функций. Мы можем контролировать уровень сглаживания, изменяя значение сигмы при передаче параметра в функцию.
gausian_blur_transformation_13 = T.GaussianBlur(kernel_size = (7,13), sigma = (6 , 7)) gausian_blur_transformation_56 = T.GaussianBlur(kernel_size = (7,13), sigma = (2 , 9)) gausian_blurred_image_13 = gausian_blur_transformation_13(orig_img) gausian_blurred_image_56 = gausian_blur_transformation_56(orig_img) plt.imshow(gausian_blurred_image_13)
plt.imshow(gausian_blurred_image_56)
6. Гауссовский шум
Добавление гауссова шума к изображению поможет изображению иметь стратегические вариации результатов в обучающих данных. Функция шума Гаусса, предоставляемая torchvision.transforms, поможет создать шум с распределением Гаусса на изображении. Функция гауссовского шума в torchvision.transforms будет работать только с тензорами, поэтому, как вы можете видеть ниже, нам нужно создать небольшую функцию-оболочку для преобразования изображения в тензор и обратно. Мы можем изменить уровень шума, изменив значение параметра шума, переданного в функцию.
def addnoise(input_image, noise_factor = 0.3): inputs = T.ToTensor()(input_image) noise = inputs + torch.rand_like(inputs) * noise_factor noise = torch.clip (noise,0,1.) output_image = T.ToPILImage() image = output_image(noise) return image gausian_image_3 = addnoise(orig_img) gausian_image_6 = addnoise(orig_img,0.6) gausian_image_9 = addnoise(orig_img,0.9) plt.imshow(gausian_image_3)
plt.imshow(gausian_image_6)
plt.imshow(gausian_image_9)
7. Дрожание цвета
Функция цветового дрожания от torchvision.transforms помогает варьировать яркость, контрастность, оттенок и насыщенность изображения, создавая вариации в этих аспектах изображения, позволяя модели находить в нем больше функций. Это также позволяет распознавать объект в различном окружении. На этом изображении выполняются три итерации цветового дрожания, вы можете сделать больше, изменив значения, которые передаются в качестве параметров в функцию.
colour_jitter_transformation_1 = T.ColorJitter(brightness=(0.5,1.5),contrast=(3),saturation=(0.3,1.5),hue=(-0.1,0.1)) colour_jitter_transformation_2 = T.ColorJitter(brightness=(0.7),contrast=(6),saturation=(0.9),hue=(-0.1,0.1)) colour_jitter_transformation_3 = T.ColorJitter(brightness=(0.5,1.5),contrast=(2),saturation=(1.4),hue=(-0.1,0.5)) colour_jitter_image_1 = colour_jitter_transformation_1(orig_img) colour_jitter_image_2 = colour_jitter_transformation_2(orig_img) colour_jitter_image_3 = colour_jitter_transformation_3(orig_img) plt.imshow(colour_jitter_image_1)
plt.imshow(colour_jitter_image_2)
plt.imshow(colour_jitter_image_3)
8. Случайное инвертирование
Функция случайного инвертирования инвертирует заданное изображение случайным образом с заданной вероятностью. Эта функция помогает внести разнообразие в набор данных.
transform = T.RandomInvert(p = 0.25) inverted_img = transform(orig_img) plt.imshow(inverted_img)
Скрипт для эффективной аугментации классифицированных изображений
Теперь мы видели все эти преобразования по отдельности, но не имеет смысла выполнять все эти аугментации по отдельности на каждом отдельном изображении, если вы не любите боль, оно того не стоит.
Приведенный ниже скрипт просматривает файлы с тренировочными изображениями, создает все дополнения изображений, а затем сохраняет их в другой папке в той же файловой структуре. Убедитесь, что у вас есть папка с тренировочными изображениями (с тренировочной меткой каждого типа в качестве имени папки). Создайте новую папку для дополненных изображений. Укажите путь к папке с изображениями для дополнения в переменной master_dataset и путь к папке, где будут храниться дополненные изображения в переменной augmented dataset. Затем запустите скрипт, и вуаля, у вас есть все дополненные изображения в новой папке.
Перед запуском скрипта указанная папка для дополненных изображений пуста:
Сценарий:
# This script aims to create augmented images from one image to create a larger dataset for our cnn model # The augmentation this script will perform on each object is # orig_img,grayscaled_image,random_rotation_transformation_45_image,random_rotation_transformation_65_image,random_rotation_transformation_85_image,gausian_blurred_image_13_image,gausian_blurred_image_56_image,gausian_image_3,gausian_image_6,gausian_image_9,colour_jitter_image_1,colour_jitter_image_2,colour_jitter_image_3 #call the function creating file with augmented image give path of dataset and path of folder where you want the augmented images to be stored import PIL import torch from PIL import Image from pathlib import Path import matplotlib.pyplot as plt import numpy as np import sys import torchvision.transforms as T import os #torch.transforms #grayscale grayscale_transform = T.Grayscale(3) #random rotation random_rotation_transformation_45 = T.RandomRotation(45) random_rotation_transformation_85 = T.RandomRotation(85) random_rotation_transformation_65 = T.RandomRotation(65) #Gausian Blur gausian_blur_transformation_13 = T.GaussianBlur(kernel_size = (7,13), sigma = (6 , 9)) gausian_blur_transformation_56 = T.GaussianBlur(kernel_size = (7,13), sigma = (5 , 8)) #Gausian Noise def addnoise(input_image, noise_factor = 0.3): inputs = T.ToTensor()(input_image) noisy = inputs + torch.rand_like(inputs) * noise_factor noisy = torch.clip (noisy,0,1.) output_image = T.ToPILImage() image = output_image(noisy) return image #Colour Jitter colour_jitter_transformation_1 = T.ColorJitter(brightness=(0.5,1.5),contrast=(3),saturation=(0.3,1.5),hue=(-0.1,0.1)) colour_jitter_transformation_2 = T.ColorJitter(brightness=(0.7),contrast=(6),saturation=(0.9),hue=(-0.1,0.1)) colour_jitter_transformation_3 = T.ColorJitter(brightness=(0.5,1.5),contrast=(2),saturation=(1.4),hue=(-0.1,0.5)) #Random invert random_invert_transform = T.RandomInvert() #Main function that calls all the above functions to create 11 augmented images from one image def augment_image(img_path): #orig_image orig_img = Image.open(Path(img_path)) #grayscale grayscaled_image=grayscale_transform(orig_img) #grayscaled_image.show() #random rotation random_rotation_transformation_45_image=random_rotation_transformation_45(orig_img) #random_rotation_transformation_45_image.show() random_rotation_transformation_85_image=random_rotation_transformation_85(orig_img) #random_rotation_transformation_85_image.show() random_rotation_transformation_65_image=random_rotation_transformation_65(orig_img) #random_rotation_transformation_65_image.show() #Gausian Blur gausian_blurred_image_13_image = gausian_blur_transformation_13(orig_img) #gausian_blurred_image_13_image.show() gausian_blurred_image_56_image = gausian_blur_transformation_56(orig_img) #gausian_blurred_image_56_image.show() #Gausian Noise gausian_image_3 = addnoise(orig_img) #gausian_image_3.show() gausian_image_6 = addnoise(orig_img,0.6) #gausian_image_6.show() gausian_image_9 = addnoise(orig_img,0.9) #gausian_image_9.show() #Color Jitter colour_jitter_image_1 = colour_jitter_transformation_1(orig_img) #colour_jitter_image_1.show() colour_jitter_image_2 = colour_jitter_transformation_2(orig_img) #colour_jitter_image_2.show() colour_jitter_image_3 = colour_jitter_transformation_3(orig_img) #colour_jitter_image_3.show() return [orig_img,grayscaled_image,random_rotation_transformation_45_image,random_rotation_transformation_65_image,random_rotation_transformation_85_image,gausian_blurred_image_13_image,gausian_blurred_image_56_image,gausian_image_3,gausian_image_6,gausian_image_9,colour_jitter_image_1,colour_jitter_image_2,colour_jitter_image_3] #augmented_images = augment_image(orig_img_path) def creating_file_with_augmented_images(file_path_master_dataset,file_path_augmented_images): master_dataset_folder = file_path_master_dataset files_in_master_dataset = os.listdir(file_path_master_dataset) augmented_images_folder = file_path_augmented_images counter=0 for element in files_in_master_dataset: os.mkdir(f"{augmented_images_folder}/{element}") images_in_folder= os.listdir(f"{master_dataset_folder}/{element}") counter = counter+1 counter2 = 0 for image in images_in_folder: counter required_images = augment_image(f"{master_dataset_folder}/{element}/{image}") counter2=counter2+1 counter3 = 0 for augmented_image in required_images: counter3 = counter3 +1 augmented_image = augmented_image.save(f"{augmented_images_folder}/{element}/{counter}_{counter2}_{counter3}_{image}") """images = augment_image("dog.png") for element in images: element.show()""" #augmented dataset path augmented_dataset = "/Users/software/Desktop/sem_6/Hieroglyphics_nlp/Code_image_augmentation/augmented_images_dataset" # master dataset path master_dataset = "/Users/software/Desktop/sem_6/Hieroglyphics_nlp/Code_image_augmentation/Master_dataset" # run the program creating_file_with_augmented_images(master_dataset,augmented_dataset)
После запуска скрипта все дополненные изображения сохраняются в указанной папке с одинаковой файловой структурой:
Надеюсь, скрипт работал на вашем компьютере. Если у вас возникли проблемы, просмотрите комментарии к скрипту, а также убедитесь, что все библиотеки, используемые в скрипте, установлены и готовы к работе.
Счастливого увеличения... (морщится в тишине).
Использованная литература :