[PYTHON] Convertissez une véritable image de crocodile féroce en un style neuronal souriant de 100 crocodiles avec Keras

Qu'est-ce que la conversion de style neuronal?

La conversion de style neuronal est l'une des techniques d'apprentissage automatique qui convertit une image cible dans le style (texture) d'une autre image pour générer une nouvelle image. C'est une technologie utilisée dans les applications qui changent les images des villes et des gens dans un style Goch. スクリーンショット 2020-03-24 15.13.40.png Maintenant, en utilisant cette technologie, j'aimerais essayer de convertir une image de crocodile réelle et féroce qui semble manger les gens en un style de crocodile qui mourra dans 100 jours et la convertira en un crocodile souriant et doux. (Même ainsi, est-ce que Nii-chan dans cette image va bien? Si vous ne faites pas attention, vous mourrez!) wani_plus_wani.png Ce que vous faites est essentiellement de conserver le contenu de l'image d'origine (structure macro telle que le squelette de l'image), puis d'incorporer un style tactile de dessin animé de 100 crocodiles (texture). Dans l'apprentissage en profondeur, nous visons toujours à atteindre l'objectif en définissant une fonction de perte qui spécifie ce que nous voulons atteindre et en minimisant cette fonction de perte. Voici une image de la fonction de perte que je veux minimiser, qui est très approximative dans cet exemple.

Fonction de perte = (contenu d'image généré par le contenu de l'image de crocodile réel) + (style d'image généré par le style 100 crocodile)

Le code source est tiré de ce livre ↓ par le créateur de Keras. C'est presque comme ce livre, donc si vous êtes intéressé par les détails, veuillez l'acheter. [Apprentissage en profondeur avec Python et Keras](https://www.amazon.co.jp/Python%E3%81%A8Keras%E3%81%AB%E3%82%88%E3%82%8B%E3%83] % 87% E3% 82% A3% E3% 83% BC% E3% 83% 97% E3% 83% A9% E3% 83% BC% E3% 83% 8B% E3% 83% B3% E3% 82% B0 -Francois-Chollet / dp / 4839964262 / ref = sr_1_1? __Mk_ja_JP =% E3% 82% AB% E3% 82% BF% E3% 82% AB% E3% 83% 8A & crid = 1HSLD7YJT37UJ & dchild = 1 & mots-clés = python + q5030 livres & sprefix = python + keras% 2Caps% 2C268 & sr = 1-1) Code source

environnement

Utilisez Google Colab. Aucune configuration n'est requise et vous pouvez accéder gratuitement au GPU, ce qui vous permet de traiter facilement les images. Enregistrez l'image que vous souhaitez utiliser dans Google Drive et chargez l'image à partir de Google Colab.

Conversion de style neuronal à l'aide de Keras dans Google Colab

Tout d'abord, enregistrez l'image cible et l'image de style que vous souhaitez traiter dans Google Drive. Après l'enregistrement, ouvrez le notebook avec google colab. Par conséquent, exécutez ↓ pour accéder à google drive et autorisez l'accès côté google drive. Ensuite, vous obtiendrez le code d'autorisation, alors entrez-le dans le formulaire qui apparaît après avoir exécuté le code ci-dessous.

from google.colab import drive
drive.mount('/content/drive')

Ensuite, définissez le chemin de l'image. Traitez les images traitées afin qu'elles aient la même taille.

import keras
keras.__version__
from keras.preprocessing.image import load_img, img_to_array

#Le chemin de l'image cible. Réécrivez le chemin vers l'emplacement que vous avez enregistré.
target_image_path = '/content/drive/My Drive/Colab Notebooks/wani/wani2.png'
#Chemin de l'image de style. Réécrivez le chemin vers l'emplacement que vous avez enregistré.
style_reference_image_path = '/content/drive/My Drive/Colab Notebooks/wani/100wani.png'

#Taille de l'image générée
width, height = load_img(target_image_path).size
img_height = 400
img_width = int(width * img_height / height)

Ensuite, créez une fonction auxiliaire qui lit, prétraite et post-traite les images échangées avec VGG19.

import numpy as np
from keras.applications import vgg19

def preprocess_image(image_path):
    img = load_img(image_path, target_size=(img_height, img_width))
    img = img_to_array(img)
    img = np.expand_dims(img, axis=0)
    img = vgg19.preprocess_input(img)
    return img

def deprocess_image(x):
    x[:, :, 0] += 103.939
    x[:, :, 1] += 116.779
    x[:, :, 2] += 123.68
    x = x[:, :, ::-1]
    x = np.clip(x, 0, 255).astype('uint8')
    return x

Ensuite, définissez VGG19.

from keras import backend as K

target_image = K.constant(preprocess_image(target_image_path))
style_reference_image = K.constant(preprocess_image(style_reference_image_path))

#Espace réservé pour contenir l'image générée
combination_image = K.placeholder((1, img_height, img_width, 3))

#Combinez trois images en un seul lot
input_tensor = K.concatenate([target_image,
                              style_reference_image,
                              combination_image], axis=0)

#Construisez VGG19 en utilisant un lot de 3 images en entrée
#Ce modèle charge les poids ImageNet formés
model = vgg19.VGG19(input_tensor=input_tensor,
                    weights='imagenet',
                    include_top=False)
print('Model loaded.')

Définissez la fonction de perte.

#Fonction de perte de contenu
def content_loss(base, combination):
    return K.sum(K.square(combination - base))

#Fonction de perte de style
def gram_matrix(x):
    features = K.batch_flatten(K.permute_dimensions(x, (2, 0, 1)))
    gram = K.dot(features, K.transpose(features))
    return gram

def style_loss(style, combination):
    S = gram_matrix(style)
    C = gram_matrix(combination)
    channels = 3
    size = img_height * img_width
    return K.sum(K.square(S - C)) / (4. * (channels ** 2) * (size ** 2))

#Fonction de perte de fluctuation totale
def total_variation_loss(x):
    a = K.square(
        x[:, :img_height - 1, :img_width - 1, :] - x[:, 1:, :img_width - 1, :])
    b = K.square(
        x[:, :img_height - 1, :img_width - 1, :] - x[:, :img_height - 1, 1:, :])
    return K.sum(K.pow(a + b, 1.25))

Définissez la fonction de perte finale (moyenne pondérée de ces trois fonctions) à minimiser.

outputs_dict = dict([(layer.name, layer.output) for layer in model.layers])
content_layer = 'block5_conv2'
style_layers = ['block1_conv1',
                'block2_conv1',
                'block3_conv1',
                'block4_conv1',
                'block5_conv1']

total_variation_weight = 1e-4
style_weight = 1.
content_weight = 0.025

loss = K.variable(0.)
layer_features = outputs_dict[content_layer]
target_image_features = layer_features[0, :, :, :]
combination_features = layer_features[2, :, :, :]
loss += content_weight * content_loss(target_image_features,
                                      combination_features)
for layer_name in style_layers:
    layer_features = outputs_dict[layer_name]
    style_reference_features = layer_features[1, :, :, :]
    combination_features = layer_features[2, :, :, :]
    sl = style_loss(style_reference_features, combination_features)
    loss += (style_weight / len(style_layers)) * sl
loss += total_variation_weight * total_variation_loss(combination_image)

Définir le processus de descente de gradient

grads = K.gradients(loss, combination_image)[0]
fetch_loss_and_grads = K.function([combination_image], [loss, grads])

class Evaluator(object):

    def __init__(self):
        self.loss_value = None
        self.grads_values = None

    def loss(self, x):
        assert self.loss_value is None
        x = x.reshape((1, img_height, img_width, 3))
        outs = fetch_loss_and_grads([x])
        loss_value = outs[0]
        grad_values = outs[1].flatten().astype('float64')
        self.loss_value = loss_value
        self.grad_values = grad_values
        return self.loss_value

    def grads(self, x):
        assert self.loss_value is not None
        grad_values = np.copy(self.grad_values)
        self.loss_value = None
        self.grad_values = None
        return grad_values

evaluator = Evaluator()

Enfin c'est fait!

from scipy.optimize import fmin_l_bfgs_b
#from scipy.misc import imsave
import imageio
import time

result_prefix = 'style_transfer_result'
iterations = 30

# Run scipy-based optimization (L-BFGS) over the pixels of the generated image
# so as to minimize the neural style loss.
# This is our initial state: the target image.
# Note that `scipy.optimize.fmin_l_bfgs_b` can only process flat vectors.
x = preprocess_image(target_image_path)
x = x.flatten()
for i in range(iterations):
    print('Start of iteration', i)
    start_time = time.time()
    x, min_val, info = fmin_l_bfgs_b(evaluator.loss, x,
                                     fprime=evaluator.grads, maxfun=20)
    print('Current loss value:', min_val)
    # Save current generated image
    img = x.copy().reshape((img_height, img_width, 3))
    img = deprocess_image(img)
    fname = result_prefix + '_at_iteration_%d.png' % i
    #imsave(fname, img)
    imageio.imwrite(fname, img)
    end_time = time.time()
    print('Image saved as', fname)
    print('Iteration %d completed in %ds' % (i, end_time - start_time))

Image de sortie

from scipy.optimize import fmin_l_bfgs_b
from matplotlib import pyplot as plt

#Image de contenu
plt.imshow(load_img(target_image_path, target_size=(img_height, img_width)))
plt.figure()

#Image de style
plt.imshow(load_img(style_reference_image_path, target_size=(img_height, img_width)))
plt.figure()

#Image générée
plt.imshow(img)
plt.show()

Résultat de sortie

Le résultat de sortie est ,,,,,,,, wani_result.png C'est différent de ce que j'avais imaginé! !! !! !! !! Pas de pop et de douce sensation de crocodile! !! !! !! !! !! Eh bien, il y a l'apprentissage en profondeur, mais pour le moment, je pense que vous auriez pu découvrir que vous pouvez essayer l'apprentissage en profondeur en utilisant facilement Google Colab ou Keras. Vous pouvez essayer différents traitements d'images par vous-même avec ce code, alors essayez-le.

Vraiment Keras est incroyable. Encore une fois, ce code est [Deep Learning with Python and Keras](https://www.amazon.co.jp/Python%E3%81%A8Keras%E3%81%AB%E3%82%88] % E3% 82% 8B% E3% 83% 87% E3% 82% A3% E3% 83% BC% E3% 83% 97% E3% 83% A9% E3% 83% BC% E3% 83% 8B% E3 % 83% B3% E3% 82% B0-François-Chollet / dp / 4839964262 / ref = sr_1_1? __Mk_ja_JP =% E3% 82% AB% E3% 82% BF% E3% 82% AB% E3% 83% 8A & crid = 1HSLD7YJT37UJ & dchild = 1 & keywords = python + keras & qid = 1558530509 & s = livres & sprefix = python + keras% 2Caps% 2C268 & sr = 1-1) ↓ Ce code est utilisé. Code source

Recommended Posts

Convertissez une véritable image de crocodile féroce en un style neuronal souriant de 100 crocodiles avec Keras
Reconnaissance d'image avec keras
Classification d'images avec un réseau de neurones auto-fabriqué par Keras et PyTorch