Augmentation des données de vision par ordinateur : exemple de code

Posté le : 14/01/2022

Partager

Découvrez les étapes de l’augmentation des données de vision par ordinateur

 

J’ai récemment utilisé Azure Custom Vision pour entraîner un classificateur d’images et exporter un modèle entraîné au format tensorflow. À l’aide de l’apprentissage par transfert, il permet d’entraîner un modèle avec seulement quelques échantillons (au moins 50 images par classe). Super, n’est-ce pas ?

 

Cependant, si vous démarrez votre projet à partir de zéro, vous n’aurez peut-être même pas 50 images par classe. Ou, vous pouvez avoir un nombre suffisant d’articles pour une classe et seulement quelques-uns pour l’autre. Dans ce court article, nous allons explorer quelques extraits de code qui nous permettront de générer facilement des données synthétiques.

En lieu d’introduction :

  • Les techniques d’augmentation des données dans l’analyse des données sont utilisées pour augmenter la quantité de données en ajoutant des copies légèrement modifiées de données déjà existantes ou de données synthétiques nouvellement créées à partir de données existantes. Cela agit comme un régularisateur et aide à réduire le surapprentissage lors de la formation d’un modèle d’apprentissage automatique. C’est étroitement lié au suréchantillonnage dans l’analyse des données… Les transformations géométriques, le retournement, la modification des couleurs, le recadrage, la rotation, l’injection de bruit et l’effacement aléatoire sont utilisés pour augmenter l’image dans l’apprentissage en profondeur.

Wikipedia « Data augmentation »

 

Alors, allons y !


Étape 1 : Créer un dossier avec des classes

Pour cette expérience, j’ai créé un seul dossier appelé images avec de nombreux sous-dossiers, chacun correspondant à une classe.

Quelque chose comme ça :

-\images

image_augmentation.py

—-\class1

—-\class2

—-\class3

—-\class4

Rien de compliqué, n’est ce pas ?

 

Étape 2 : placez vos données dans les dossiers

Encore une fois, placez simplement vos échantillons dans un dossier correspondant. Par exemple, j’ai créé un simple classificateur d’interrupteurs électriques et préparé 2 images par classe, 2 pour la classe « ON » et deux pour la classe « OFF »

Augmentation des données de vision par ordinateur : exemple de code OFF

Dossier OFF

 

Computer Vision Data Augmentation: Code Sample ON

Dossier ON

 

Étape 3 Préparer les fonctions communes

Voici quelques fonctions utiles qui peuvent être utilisées dans différents projets, comme l’enregistrement d’images ou la reconnaissance de sous-dossiers

 

import os

import cv2

import imageio

import numpy as np

import imgaug as ia

import imgaug.augmenters as iaa

from PIL import Image

from datetime import datetime

from imgaug.augmentables.batches import UnnormalizedBatch

def count_files_in_folder(folder):

files_count = len([name for name in os.listdir(folder) if os.path.isfile(os.path.join(folder, name))])

return(files_count)

def save_image(image, folder):

«  » »Save an image with unique name

Arguments:

image {Pillow} — image object to be saved

folder {string} — output folder

«  » »

# check whether the folder exists and create one if not

if not os.path.exists(folder):

os.makedirs(folder)

# to not erase previously saved photos counter (image name) = number of photos in a folder + 1

image_counter = count_files_in_folder(folder)+1

# save image to the dedicated folder (folder name = label)

image_name = folder + ‘/’ + str(image_counter) + ‘.png’

image.save(image_name)

def get_files_in_folder(folder):

return [os.path.join(folder, name) for name in os.listdir(folder) if os.path.isfile(os.path.join(folder, name))]

def list_oversample(initial_list, max_size):

«  » »duplicate a list n times or take a part of a list

Arguments:

initial_list {list} — array to be resized

max_size {int} — majority class size

«  » »

resized_array = []

initial_length = len(initial_list)

new_size = max_size – initial_length

if new_size >= initial_length:

augment_rate = int(new_size/initial_length)

resized_array = initial_list*augment_rate

else:

resized_array = initial_list[:new_size]

return resized_array

def save_image_array(image_array, folder):

for image in image_array:

save_image(Image.fromarray(image), folder)

 

Étape 4 : paramétrer les augmentateurs

# Set augmenters

ia.seed(1)

seq = iaa.Sequential([

iaa.Fliplr(0.5), # horizontal flips

iaa.Crop(percent=(0, 0.1)), # random crops

# Small gaussian blur with random sigma between 0 and 0.5.

# But we only blur about 50% of all images.

iaa.Sometimes(

0.5,

iaa.GaussianBlur(sigma=(0, 0.5))

),

# Strengthen or weaken the contrast in each image.

iaa.LinearContrast((0.75, 1.5)),

# Add gaussian noise.

# For 50% of all images, we sample the noise once per pixel.

# For the other 50% of all images, we sample the noise per pixel AND

# channel. This can change the color (not only brightness) of the

# pixels.

iaa.AdditiveGaussianNoise(loc=0, scale=(0.0, 0.05*255), per_channel=0.5),

# Make some images brighter and some darker.

# In 20% of all cases, we sample the multiplier once per channel,

# which can end up changing the color of the images.

iaa.Multiply((0.8, 1.2), per_channel=0.2),

# Apply affine transformations to each image.

# Scale/zoom them, translate/move them, rotate them and shear them.

iaa.Affine(

scale={« x »: (0.8, 1.2), « y »: (0.8, 1.2)},

translate_percent={« x »: (-0.2, 0.2), « y »: (-0.2, 0.2)},

rotate=(-25, 25),

shear=(-8, 8)

)

], random_order=True) # apply augmenters in random order

 

Étape 5 (option 1) : Définissez manuellement le nombre d’articles souhaités

Ici, le processus est assez simple, j’ordonne simplement à l’augmenter de générer N éléments par classe, disons 50 par classe

# input image

IMAGE_FOLDER = ‘images’

# all subfolders in the initial directory

image_subfolders = [os.path.join(IMAGE_FOLDER, subfolder) for subfolder in os.listdir(IMAGE_FOLDER)]

max_image_count = 50

image_target_subfolders = [subfolder for subfolder in image_subfolders if count_files_in_folder(subfolder) < max_image_count]

 

Étape 5 (option 2) : Définissez le nombre d’articles par classe en fonction de la classe majoritaire

Celui-ci est plus intéressant. Par exemple, nous avons 100k images pour la classe A, et seulement <1k images pour les autres classes (B, C, D etc). Il n’est pas nécessaire de générer plus de données synthétiques pour la classe majoritaire, nous définissons donc automatiquement le nombre d’éléments pour chaque classe minoritaire, en fonction de la taille de la plus grande

# input image

IMAGE_FOLDER = ‘../data/categories_resized’

# all subfolders in the initial directory

image_subfolders = [os.path.join(IMAGE_FOLDER, subfolder) for subfolder in os.listdir(IMAGE_FOLDER)]

# number of instances in the majority class

max_image_count = max([count_files_in_folder(subfolder) for subfolder in image_subfolders])

image_target_subfolders = [subfolder for subfolder in image_subfolders if count_files_in_folder(subfolder) < max_image_count]

 

Étape 6 : générer des données synthétiques

for subfolder in image_target_subfolders:

print (subfolder)

# =============Time calculation===============

start_time = datetime.now()

# =============Time calculation===============

# create images array per folder

image_files = get_files_in_folder(subfolder)

synthetic_image_files = list_oversample(image_files, 50)

images = [imageio.imread(image_file) for image_file in synthetic_image_files]

# apply imge augmentation on a subfolder

augmented_images = seq(images=images)

save_image_array(augmented_images, subfolder)

# =============Time calculation===============

# check the endtime

end_time = datetime.now()

# get the total time spent

time_spent = end_time – start_time

spent_minutes, spent_seconds = divmod(

time_spent.days * 86400 + time_spent.seconds, 60)

print(« {} min {} sec ».format(spent_minutes, spent_seconds))

# =============Time calculation===============

 

Voyons maintenant nos dossiers initiaux

Computer Vision Data Augmentation: Code Sample OFF folder augmented

Dossier OFF augmenté

Computer Vision Data Augmentation: Code Sample ON folder augmented

Dossier ON augmenté

Nous pouvons désormais tout apporter à Azure Custom Vision pour former un classificateur.


J’espère vous avoir été utile, amusez-vous bien!

 

Ecrit par Alibek Jakupov, Data scientist et Microsoft MVP Artifical Intelligence.

Contactez-nous Postuler Nos offres d'emploi