Schritt 1: Importieren der Bibliotheken
Importieren Sie zunächst die erforderlichen Python-Bibliotheken, einschließlich MXNet, Gluon und Matplotlib. Dies stellt sicher, dass alle notwendigen Funktionen für die Bildverarbeitung und das Deep Learning zur Verfügung stehen.
import matplotlib.pyplot as plt
from mxnet import autograd, gluon, image, init, nd
from mxnet.gluon import model_zoo, nn
import time
Schritt 2: Vorbereiten der Bilder
Lesen Sie die Inhalts- und Stilbilder ein und führen Sie die erforderliche Vorverarbeitung durch, z. B. das Anpassen der Größe und Normalisieren der Pixelwerte. Eine konsistente Vorverarbeitung ist für optimale Ergebnisse unerlässlich.
content_img = image.imread('content_image.jpg')
style_img = image.imread('style_image.jpg')
# Bildgröße anpassen
image_shape = (300, 200)
content_img = image.imresize(content_img, *image_shape)
style_img = image.imresize(style_img, *image_shape)
# Normalisieren
rgb_mean = nd.array([0.485, 0.456, 0.406])
rgb_std = nd.array([0.229, 0.224, 0.225])
def transform(img, rgb_mean, rgb_std):
img = img.astype('float32') / 255
for i in range(3):
img[:, :, i] = (img[:, :, i] - rgb_mean[i]) / rgb_std[i]
img = img.transpose((2, 0, 1))
return img.expand_dims(axis=0)
content_img = transform(content_img, rgb_mean, rgb_std)
style_img = transform(style_img, rgb_mean, rgb_std)
Schritt 3: Definieren von Loss-Funktionen
Definieren Sie die Loss-Funktionen für Inhalt, Stil und Gesamtvarianz, um den Stilübertragungsprozess zu steuern. Diese Funktionen sind entscheidend für das Gleichgewicht zwischen Inhaltsbeibehaltung und Stilübertragung.
def content_loss(y_hat, y):
return nd.square(y_hat - y).mean()
def gram(x):
channels = int(x.shape[1])
features = x.reshape((channels, -1))
gram = nd.dot(features, features.T) / (x.size / channels)
return gram
def style_loss(y_hat, style_Y):
return nd.square(gram(y_hat) - gram(style_Y)).mean()
def tv_loss(y_hat):
return 0.5 * (nd.abs(y_hat[:, :, :-1, :] - y_hat[:, :, 1:, :]).mean() +
nd.abs(y_hat[:, :, :, :-1] - y_hat[:, :, :, 1:]).mean())
Schritt 4: Extrahieren von Funktionen
Verwenden Sie das vortrainierte VGG-Netzwerk, um die Inhalt- und Stilfunktionen aus den entsprechenden Layern zu extrahieren. Die richtigen Layer sorgen für die besten Ergebnisse.
style_layers, content_layers = [0, 5, 10, 19, 28], [25]
def get_contents(image_shape, ctx):
content_X = nd.random.normal(shape=(1, 3, image_shape[0], image_shape[1]), ctx=ctx)
content_Y = extract_features(content_X, content_layers, style_layers)[0]
return content_X, content_Y
def get_styles(image_shape, ctx):
style_X = preprocess(style_img, image_shape).copyto(ctx)
styles_Y = extract_features(style_X, content_layers, style_layers)[1]
styles_Y_gram = [gram(Y) for Y in styles_Y]
return style_X, styles_Y_gram
_, content_Y = get_contents(image_shape, ctx)
style_X, styles_Y_gram = get_styles(image_shape, ctx)
Schritt 5: Training
Initialisieren Sie das Verbundbild und trainieren Sie das Modell mithilfe des Algorithmus der Gradientenabstiegs. Verfeinern Sie die Parameter weiter, um das gewünschte gestilte Ergebnis zu erhalten.
ctx = d2l.try_gpu()
image_shape = (300, 200)
X, contents_Y = get_contents(image_shape, ctx)
style_X, styles_Y_gram = get_styles(image_shape, ctx)
# Initialisieren Sie das Verbundbild
gblend_img = nd.random.normal(shape=(1, 3, image_shape[0], image_shape[1]), ctx=ctx)
gblend_img.attach_grad()
# Definieren Sie den Trainingsteil
epochs = 100
lr = 0.01 # Anpassbare Lernrate
tv_weight = 10
content_weight = 1
style_weight = 1e3
def compute_loss(X, contents_Y_hat, styles_Y_hat, contents_Y, styles_Y_gram):
contents_l = [content_loss(Y_hat, Y) * content_weight for Y_hat, Y in zip(contents_Y_hat, contents_Y)]
styles_l = [style_loss(Y_hat, gram_Y) * style_weight for Y_hat, gram_Y in zip(styles_Y_hat, styles_Y_gram)]
tv_l = tv_loss(X) * tv_weight
return sum(styles_l + contents_l + [tv_l])
trainer = gluon.Trainer({"gblend_img": gblend_img}, 'sgd', {"learning_rate": lr})
for i in range(epochs):
with autograd.record():
contents_Y_hat, styles_Y_hat = extract_features(gblend_img, content_layers, style_layers)
loss = compute_loss(gblend_img, contents_Y_hat, styles_Y_hat, contents_Y, styles_Y_gram)
loss.backward()
trainer.step(1)
if (i + 1) % 10 == 0:
print('epoch %d, loss: %f' % (i+1, loss.asscalar()))
# Nachbearbeitung
output = postprocess(gblend_img).asnumpy()
plt.imshow(output)
plt.show()