Deep Learning erfordert eine große Datenmenge, um für effektives Lernen vorbereitet zu sein. Wenn es jedoch schwierig ist, eine große Datenmenge vorzubereiten, kann eine als Datenerweiterung bezeichnete Technik verwendet werden, um eine kleine Datenmenge aufzublasen (zu vermehren) und für das Training zu verwenden.
Wenn die Daten "Bild" sind, ** parallele Bewegung **, ** Drehung **, ** Vergrößerung / Verkleinerung **, ** verkehrt herum **, ** Links / Rechts-Inversion **, ** Helligkeitsanpassung wie folgt Daten werden durch Bildverarbeitung erweitert, die Verformung und Verarbeitung wie ** kombiniert.
In der Umgebung von Tensorflow (2.x) + Keras wird eine Klasse namens "ImageDataGenerator" für die Datenerweiterung vorbereitet. Wenn Sie diese verwenden, können Sie ** Daten mit zufälliger Bildverarbeitung verwenden (dies wird in diesem Artikel erweitert. Es ist relativ einfach, ein Bild zu erzeugen. Dieser Artikel beschreibt die Datenerweiterung mit diesem "ImageDataGenerator".
Ohne Verwendung von ImageDataGenerator können Bibliotheken wie ** OpenCV ** und ** tf.keras ** ** affine Transformationen ** (cv2.warpAffine
undtensorflow.keras.preprocessing.image.apply_affine_transform "verwenden. Verwenden Sie
), um ** parallele Bewegung, Drehung und Skalierung ** durchzuführen und eine manuelle Datenerweiterung zu versuchen. Vergleichen Sie auch die Verarbeitungsgeschwindigkeiten beider Bibliotheken (das Ergebnis ist ein überwältigender Sieg für OpenCV).
Wir überprüfen die Ausführung in der Google Colab. Umgebung.
opencv-python 4.1.2.30
tensorflow 2.1.0rc1
Wechseln Sie die Version von Tesorflow und importieren Sie die Bibliothek. Es verwendet auch matplotlib, um die Bilder vor und nach der Verarbeitung anzuzeigen. Importieren Sie diese also ebenfalls.
Vorbereitung: Bibliothek importieren
%tensorflow_version 2.x
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
Erfassen Sie die Zieldaten zur Verarbeitung. Hier verwenden wir die Trainingsdaten von "** CIFAR-10 **". CIFAR-10 ist ein Datensatz, der aus 10 Arten von Bildern besteht: "Flugzeug", "Automobil", "Vogel", "Katze", "Hirsch", "Hund", "Frosch", "Pferd", "Schiff" und "LKW".
Vorbereitung: Vorbereitung der Bilddaten
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()
img_cifar10 = x_train/255.
print(img_cifar10.shape) # -> (50000, 32, 32, 3) 32x32 3ch RGB
img_cifar10
enthält $ 3 $ ch-RGB $ 50.000 $ Bilder von $ 32 \ times 32 $ px im numpy.ndarray-Format.
Erstellen Sie eine Funktion zum Anzeigen des Bildes. Definieren Sie "showImage (...)", um nur ein Bild anzuzeigen, und "showImageArray (...)", um mehrere Bilder gleichzeitig anzuzeigen, indem Sie ein Bildarray angeben.
Vorbereitung: Definition der Bildanzeigefunktion
def showImage(img,title=None):
plt.figure(figsize=(3, 3))
plt.gcf().patch.set_facecolor('white')
plt.xticks([])
plt.yticks([])
plt.title(title)
plt.imshow(img)
plt.show()
plt.close()
def showImageArray(img_arry):
n_cols = 8
n_rows = ((len(img_arry)-1)//n_cols)+1
fig, ax = plt.subplots(nrows=n_rows, ncols=n_cols, figsize=(10, 1.25*n_rows))
fig.patch.set_facecolor('white')
for i,ax in enumerate( ax.flatten() ):
if i < len(img_arry):
ax.imshow(img_arry[i])
ax.set_xticks([])
ax.set_yticks([])
else :
ax.axis('off') #Margin-Verarbeitung
plt.show()
plt.close()
Rufen Sie diese Funktionen wie folgt auf:
Aufrufen einer Bildanzeigefunktion
# img_Zeigen Sie das 12. Bild von cifar10 an
showImage(img_cifar10[12],title='CIFAR-10 Train Data [12]')
#Bilder vom 0. bis 39. (=40 Blatt) wird angezeigt
showImageArray(img_cifar10[:40])
Geben Sie für "showImage (...)" numpy.ndarray mit der Form "(32,32,3)" als Argument an. Geben Sie für "showImageArray (...)" numpy.ndarray mit der Form "(arr_len, 32,32,3)" als Argument an (wobei "arr_len" die Länge des Bildarrays ist).
Das Ausführungsergebnis ist wie folgt.
ImageDataGenerator-Klasse Kann Bilddateien in das angegebene Verzeichnis laden und die Daten erweitern. Hier wird es zur Datenerweiterung verwendet.
Geben Sie bei Verwendung zur Datenerweiterung den Parameter "** Welche Art der Verarbeitung (Verschieben, Drehen, Vergrößern?) Wird zum Zeitpunkt der Initialisierung zufällig mit welcher Intensität durchgeführt **" an. Initialisieren Sie es beispielsweise mit den folgenden Parametern.
ImageDataGenerator-Initialisierung
ImageDataGenerator = tf.keras.preprocessing.image.ImageDataGenerator
image_data_generator = ImageDataGenerator(
rotation_range=20, #Nach dem Zufallsprinzip innerhalb von ± 20 Grad drehen
width_shift_range=8, #Bewegen Sie sich zufällig nach links und rechts innerhalb des Bereichs von ± 8 Pixel
height_shift_range=4, #Bewegen Sie sich zufällig innerhalb eines Bereichs von ± 4 Pixel auf und ab
zoom_range=(0.8, 1.2), #Zufällig 0.8~1.Vergrößern Sie den 2-fachen Bereich
horizontal_flip=True, #Nach dem Zufallsprinzip nach links und rechts drehen
channel_shift_range=0.2) #Zufälliger Verschiebungsbereich des Kanalwerts (Helligkeit)
Wenn width_shift_range
und height_shift_range
als Dezimalwerte unter $ 1 $ angegeben werden, können Sie einen zufälligen Bereich als Prozentsatz der Bildgröße angeben. Auch wenn Sie diesmal nicht verwendet werden, können Sie die verkehrte Verarbeitung mit vertical_flip = True
hinzufügen.
Mit diesem Generator werde ich versuchen, die Daten für das "Pferde" -Bild von "img_cifar10 [12]" zu erweitern (zuerst wird ** nur ein ** erweitertes Bild generiert). Wenn Sie den folgenden Code ausführen, wird die Bildverarbeitung zufällig innerhalb des in der obigen Initialisierung angegebenen Parameterbereichs ausgeführt.
Generieren Sie nur ein erweitertes Bild
org_img = img_cifar10[12].copy() #Das Ziel ist das 12. "Pferd"
ex_img = image_data_generator.flow( org_img.reshape(1,32,32,3), batch_size=1)[0][0]
print(ex_img.shape) # -> (32, 32, 3)
showImage(ex_img,title='CIFAR-10 Train Data [12] Ex')
Verwenden Sie die Methode flow (...)
, um das erweiterte Bild zu erhalten. Geben Sie als Argument das Originalbild ** array ** an (konvertiert in ein Array mit einem Element mit .reshape (1,32,32,3)
, da es keine einzelne Eingabe unterstützt). Der Rückgabewert ist NumpyArrayIterator. Bewerten Sie ihn daher mit [0] [0]
und dem 0. Element. Wird in ex_img
erfasst und gespeichert.
Das Ausführungsergebnis ist wie folgt. Links und rechts werden gespiegelt, die horizontale Bewegung wird angewendet und sie ist insgesamt heller (die Ausführungsergebnisse ändern sich mit jeder Ausführung).
Übrigens, wenn Sie das Bild drehen oder nach oben / unten / links / rechts verschieben, wird eine Lücke erstellt, aber der Rand des Bildes wird automatisch gedehnt und gefüllt (das Ergebnis ist ein natürliches Bild). Wenn Sie nicht möchten, dass dies angewendet wird, geben Sie in der Initialisierung fill_mode = 'Konstante'
an. Dann werden die Ränder wie unten gezeigt mit Schwarz gefüllt. Außerdem können Sie "fill_mode =" Reflect "," fill_mode = "wrap" und "fill_mode =" next "(Standard) angeben.
Generieren Sie als Nächstes 39 erweiterte Bilder aus dem "Pferde" -Bild von "img_cifar10 [12]". image_data_generator.flow (...)
gibt NumpyArrayIterator
zurück. Verwenden Sie also next ()
, um die Bilder nacheinander abzurufen.
Generieren Sie ein oder mehrere erweiterte Bilder
org_img = img_cifar10[12].copy()
ex_img = np.empty([40, 32, 32, 3]) #Bereiten Sie einen Bereich vor, in dem 40 Blatt einschließlich des Originals aufbewahrt werden können
ex_img[0,:,:,:] = org_img #Bewahren Sie das Original auf dem 0. Blatt auf
iter_ = image_data_generator.flow( org_img.reshape(1,32,32,3), batch_size=1)
for i in range(1,40):
ex_img[i,:,:,:] = iter_.next()[0] #Speichern Sie die generierten Bilder nacheinander
showImageArray(ex_img)
Das Ausführungsergebnis ist wie folgt.
Im vorherigen Abschnitt haben wir mehrere erweiterte Bilder für ein Bild generiert. Dieses Mal wird für jedes der 40 Bilder vom 0. bis zum 23. der Trainingsdaten von CIFAR-10 ein erweitertes Bild erzeugt.
Generieren Sie ein erweitertes Bild für jedes Bildarray
showImageArray(img_cifar10[:24]) # CIFAR-10 Zeigen Sie das 0. bis 23. Originalblatt an
ex_img = np.empty([24, 32, 32, 3])
ex_img = image_data_generator.flow(img_cifar10[:24], batch_size=24, shuffle=False)[0]
showImageArray(ex_img) # CIFAR-10 Erweitern Sie 0 bis 23 wird angezeigt
Das Ausführungsergebnis ist wie folgt. Hier sind zunächst die Originaldaten vom 0. bis zum 23. Trainingsdaten von CIFAR-10.
Als nächstes wird hier das mit ImageDataGenerator erweiterte Bild angezeigt. Sie können sehen, dass auf jedes Bild eine andere Verarbeitung (Kombination aus Bewegung, Drehung, Skalierung, Spiegeln usw.) angewendet wird.
Wenn Sie im Argument von "flow (...)" nicht "shuffle = False" angeben, wird die Reihenfolge der Ausgabebildsequenzen gemischt.
Geben Sie den Bewegungsumfang, den Drehwinkel und die Vergrößerung manuell an und generieren Sie erweiterte Bilder mit den Bibliotheken OpenCV und tf.keras. Vergleichen Sie auch die Verarbeitungszeit.
Das Bild wird ** gegen den Uhrzeigersinn </ font> um 45 Grad gedreht **. Die Drehachse ist die Bildmitte.
Ein Programm, das die OpenCV-Bibliothek verwendet, sieht folgendermaßen aus: In OpenCV ist die Richtung gegen den Uhrzeigersinn "positiv", daher wird der Drehwinkel "45" so wie er ist angegeben. cv2.warpAffine (...)
ist der Hauptteil des Prozesses. Wenn Sie nicht "borderMode = cv2.BORDER_REPLICATE" angeben, wird die Lücke mit Schwarz gefüllt.
OpenCV-Version von CIFAR10 50,Rotationsbearbeitung von 000 Blatt
import time
import cv2
deg = 45 #Gegen den Uhrzeigersinn ist "positiv"
w, h = 32, 32 #Bildgröße
m = cv2.getRotationMatrix2D((w/2,h/2), deg, 1) #Transformationsmatrix
img_cifar10_ex = np.empty_like(img_cifar10) #Ergebnis Speicherort np.empty([50000,32,32,3])Gleich wie
t1 = time.time()
for i,img in enumerate( img_cifar10 ) :
img = cv2.warpAffine(img, m, (w,h), borderMode=cv2.BORDER_REPLICATE)
img_cifar10_ex[i,:,:,:] = img
t2 = time.time()
print(f'Verarbeitungszeit{t2-t1:.1f}[sec]')
showImageArray(img_cifar10_ex[:24]) #Zeigen Sie nur 24 Blätter an
Das Ausführungsergebnis ist wie folgt. Die Verarbeitungszeit betrug ** 1,3 [s] **.
Auf der anderen Seite sieht ein Programm, das die tf.keras-Bibliothek verwendet, folgendermaßen aus: Hier ist die Richtung gegen den Uhrzeigersinn "negativ", daher wird der Drehwinkel als "-45" angegeben.
tf.50 von Keras Version von CIFAR10,Rotationsbearbeitung von 000 Blatt
import time
from tensorflow.keras.preprocessing.image import apply_affine_transform
deg = -45 #Gegen den Uhrzeigersinn ist "negativ"
img_cifar10_ex = np.empty_like(img_cifar10) #Ergebnis Speicherort
t1 = time.time()
for i,img in enumerate( img_cifar10 ) :
img = apply_affine_transform(img, theta=deg)
img_cifar10_ex[i,:,:,:] = img
t2 = time.time()
print(f'Verarbeitungszeit{t2-t1:.1f}[sec]')
showImageArray(img_cifar10_ex[:24])
Das Ausführungsergebnis ist wie folgt. Die Verarbeitungszeit betrug ebenfalls ** 16,2 [s] **. Die Verarbeitungsgeschwindigkeit war mit OpenCV </ font> überwiegend ** schneller **.
Verschiebt das Bild um $ 2 $ px nach ** rechts ** und um $ 5 $ px ** nach unten **.
Erstens ist die OpenCV-Version. Der Vorgang ist der gleiche wie bei der vorherigen "Drehung", nur der Inhalt der Umwandlungsmatrix "m" ist unterschiedlich.
OpenCV-Version von CIFAR10 50,Verschieben von 000 Blättern
import time
import cv2
tx, ty = 2, 5
w, h = 32, 32 #Bildgröße
m = np.float32([[1,0,tx],[0,1,ty]]) #Transformationsmatrix
img_cifar10_ex = np.empty_like(img_cifar10) #Ergebnis Speicherort
t1 = time.time()
for i,img in enumerate( img_cifar10 ) :
img = cv2.warpAffine(img, m, (w,h), borderMode=cv2.BORDER_REPLICATE)
img_cifar10_ex[i,:,:,:] = img
t2 = time.time()
print(f'Verarbeitungszeit{t2-t1:.1f}[sec]')
showImageArray(img_cifar10_ex[:24])
Das Ausführungsergebnis ist wie folgt. Die Verarbeitungszeit betrug ** 1,3 [Sek] ** (da die wesentliche Verarbeitung mit "Rotation" identisch ist, ändert sich die Ausführungszeit nicht).
Als nächstes kommt die tf.keras-Version. Ich habe nicht verstanden, warum es so entworfen wurde, aber es sieht aus wie "apply_affine_transform (img, tx = -5, ty = -2)", um 2px nach rechts und 5px nach unten zu verschieben. Muss angegeben werden. Geheimnis ist.
--Referenz: [Die Keras ImageDataGenerator apply_transform () -Methode verschiebt das Bild in die entgegengesetzte Richtung](https://stackoverflow.com/questions/56580076/keras-imagedatagenerator-apply-transform-method-shifts-the-image-in-opposite- d)
tf.50 von Keras Version von CIFAR10,Rotationsbearbeitung von 000 Blatt
import time
from tensorflow.keras.preprocessing.image import apply_affine_transform
tx, ty = 2, 5
img_cifar10_ex = np.empty_like(img_cifar10) #Ergebnis Speicherort
t1 = time.time()
for i,img in enumerate( img_cifar10 ) :
img = apply_affine_transform(img, tx=-ty, ty=-tx) #Achten Sie darauf, wie Sie Argumente vorbringen
img_cifar10_ex[i,:,:,:] = img
t2 = time.time()
print(f'Verarbeitungszeit{t2-t1:.1f}[sec]')
showImageArray(img_cifar10_ex[:24])
Das Ausführungsergebnis ist wie folgt. Die Verarbeitungszeit beträgt ** 13,9 [Sek] **, was ungefähr 10 Mal länger ist als die Verarbeitungszeit von OpenCV wie zuvor.
Das Bild wird 1,2-fach vergrößert (die Bildgröße ändert sich auch bei Vergrößerung nicht).
Erstens ist die OpenCV-Version. Vergrößern Sie mit "Größe ändern" und schneiden Sie dann auf $ 32 \ mal 32 $ px.
OpenCV-Version von CIFAR10 50,Erweiterungsverarbeitung von 000 Blatt
import cv2
f = 1.2
w, h = 32, 32 #Bildgröße
w2, h2 = int(w*f), int(h*f) #Vergrößerte Bildgröße
tx, ty = int((w2-w)/2),int((h2-h)/2) #Startkoordinaten trimmen
m = np.float32([[1,0,tx],[0,1,ty]]) #Transformationsmatrix
img_cifar10_ex = np.empty_like(img_cifar10) #Ergebnis Speicherort
t1 = time.time()
for i,img in enumerate( img_cifar10 ) :
img = cv2.resize(img,(w2,h2))
img_cifar10_ex[i,:,:,:] = img[tx:tx+w,ty:ty+h,:] #Schneiden Sie 32x32 aus dem vergrößerten Bild
t2 = time.time()
print(f'Verarbeitungszeit{t2-t1:.1f}[sec]')
showImageArray(img_cifar10_ex[:24])
Das Ausführungsergebnis ist wie folgt. Die Verarbeitungszeit betrug ** 1,2 [s] **.
Als nächstes kommt die tf.keras-Version. Es ist auch sehr verwirrend wie zuvor, aber wie bei "apply_affine_transform (img, zx = 1 / f, zy = 1 / f)" haben die Argumente "zx" und "zy" "** Umkehrung der Vergrößerung **". Ist gegeben.
tf.50 von Keras Version von CIFAR10,Erweiterungsverarbeitung von 000 Blatt
import time
from tensorflow.keras.preprocessing.image import apply_affine_transform
f = 1.2
img_cifar10_ex = np.empty_like(img_cifar10) #Ergebnis Speicherort
t1 = time.time()
for i,img in enumerate( img_cifar10 ) :
img = apply_affine_transform(img, zx=1/f, zy=1/f) #Argument Aufmerksamkeit
img_cifar10_ex[i,:,:,:] = img
t2 = time.time()
print(f'Verarbeitungszeit{t2-t1:.1f}[sec]')
showImageArray(img_cifar10_ex[:24])
Die Verarbeitungszeit beträgt 13,4 [Sek.] Und das Ergebnis ist wie folgt.
Recommended Posts