[PYTHON] Une méthode de conversion du style d'une image tout en préservant la couleur

introduction

Comme vous connaissez peut-être ceux qui étudient le Deep Learning, il existe un article intitulé [A Neural Algorithm of Artistic Style] qui convertit le style des images. L'explication en japonais est ci-dessous. Qu'est-ce que la conversion de style? Nous vous recommandons de jeter un coup d'œil ici en premier. Algorithme de recherche préféré pour la conversion du style

Si vous effectuez une conversion de style avec cette méthode, la couleur de l'image convertie sera similaire à l'image de style, mais récemment, la conversion de style est effectuée tout en conservant la couleur [Préserver la couleur dans Neural Artistic Style Transfer](http: / /arxiv.org/pdf/1606.05897v1.pdf) a été soumis. Il s'agit du même article de l'auteur sous le titre A Neural Algorithm of Artistic Style.

Qu'est-ce que la conversion de style d'image?

Préparez deux images, une image de contenu (par exemple, une image de chat) et une image de style (par exemple, une peinture dessinée par Goch). À partir de ces deux images, le contenu est une image de contenu et le style est similaire à l'image de style (dans ce cas, l'image d'un chat comme le dessin de Goch) est appelée conversion de style.

Aperçu

L'article propose deux types de méthodes.

Méthode 1 Correspondance d'histogramme de couleur

Convertit l'image de style pour que la moyenne et la covariance des valeurs RVB soient identiques à celles de l'image de contenu. Tout d'abord, définissez le symbole.

symbole sens dimension
\bf{x}_{C} Image de contenu 3 x (Image de contenuのピクセル数), Chaque ligne est R, G,Vecteur de valeur B
\bf{x}_{S} Image de style 3 x (Image de styleのピクセル数)
\bf{\mu}_{C} Valeur moyenne RVB de l'image de contenu 3-vector
\bf{\mu}_{S} Valeur moyenne RVB de l'image de style 3-vector
\bf{\Sigma}_{C} Co-distribution RVB de l'image de contenu 3 x 3
\bf{\Sigma}_{S} Co-distribution RVB des images de style 3 x 3

Conversion d'image de style

\bf{x}_{S^{\prime}} \leftarrow \bf{A}\bf{x}_{S}+\bf{b}

Penser à. Pour rapprocher l'histogramme des couleurs de la conversion de style après la conversion de l'histogramme des couleurs de l'image de contenu

\bf{\mu}_{S^{\prime}} = \bf{\mu}_{C}
\bf{\Sigma}_{S^{\prime}} = \bf{\Sigma}_{C}

Étant donné $ \ bf {A} $ et $ \ bf {b} $ qui satisfont

\bf{b} = \bf{\mu}_{C}-\bf{A}\bf{\mu}_{S}
\bf{A}\bf{\Sigma_{S}}\bf{A^{T}} = \bf{\Sigma_{C}}

Rencontrer. L'article en énumère deux comme $ \ bf {A} $ qui satisfont à cette formule.

Démontage Colleskey

\bf{A}_{\rm chol} = \bf{L}_{C}\bf{L}_{S}^{-1}

Cependant, $ \ bf {L} $ satisfait $ \ bf {\ Sigma} = \ bf {L} \ bf {L} ^ {T} $ par la décomposition choleskey de $ \ bf {\ Sigma} $.

Décomposition de valeur unique

Supposons que vous décomposiez $ \ bf {\ Sigma} $ en valeurs uniques pour obtenir $ \ bf {\ Sigma} = \ bf {U} \ bf {\ Lambda} \ bf {U} ^ {T} $. À ce stade, $ \ bf {\ Sigma} ^ {1/2} = \ bf {U} \ bf {\ Lambda} ^ {1/2} \ bf {U} ^ {T} $, $ \ bf {\ Sigma } ^ {-1 / 2} = \ bf {U} \ bf {\ Lambda} ^ {-1 / 2} \ bf {U} ^ {T} $. Et

\bf{A}_{\rm IA} = \bf{\Sigma_{C}^{1/2}}\bf{\Sigma_{S}^{-1/2}}

Est utilisé pour la conversion.

Utilisez les $ \ bf {A} $ et $ \ bf {b} $ obtenus pour convertir l'image de style, puis utilisez l'image de contenu et l'image de style convertie pour effectuer une conversion de style normale. L'article indique que la décomposition des valeurs propres a donné de meilleurs résultats que la décomposition choleskey.

J'ai essayé de convertir l'image de style en utilisant un algorithme qui utilise la décomposition des valeurs propres. Vous pouvez voir que le jeu de couleurs est similaire à l'image de contenu.

Image de contenu Image de style Image avec histogramme couleur fermer

Méthode 2 Transfert de luminance uniquement

Convertit l'espace colorimétrique de l'image de contenu et de l'image de style en YIQ et obtient l'image de contenu et l'image de style de luminosité uniquement. A ce moment, la conversion suivante est effectuée pour uniformiser la moyenne et la dispersion de la luminosité. $ L_ {C} $ est la luminosité de l'image de contenu, $ L_ {S} $ est la luminosité de l'image de style, $ \ mu_ {C}, \ mu_ {S} $ est la valeur moyenne de la luminosité de l'image de contenu et de l'image de style, respectivement. $ \ Sigma_ {C}, \ sigma_ {S} $ sont des écarts types.

L_{S^{\prime}} = \frac{\sigma_{C}}{\sigma_{S}}(L_{S}-\mu_{S})+\mu_{C}

Après avoir effectué une conversion de style à l'aide de ces images, vous pouvez obtenir l'image convertie en la combinant avec le canal IQ de l'image de contenu. Comment convertir entre RVB et YIQ peut être trouvé dans Wikipedia.

Implémenté par Python

Color histogram matching

L'implémentation Python de la correspondance d'histogramme de couleur à l'aide de la décomposition des valeurs propres ressemble à ceci: Vous pouvez effectuer une décomposition des valeurs propres avec numpy.linalg.eig.

import numpy as np
import six

#x est l'image de style
#y est une image de style
# x,y est un tableau numpy et la forme est(batch_size, 3, height, width)
def match_color_histogram(x, y):
    z = np.zeros_like(x)
    shape = x[0].shape
    for i in six.moves.range(len(x)):
        a = x[i].reshape((3, -1))
        a_mean = np.mean(a, axis=1, keepdims=True)
        a_var = np.cov(a)
        d, v = np.linalg.eig(a_var)
        a_sigma_inv = v.dot(np.diag(d ** (-0.5))).dot(v.T)

        b = y[i].reshape((3, -1))
        b_mean = np.mean(b, axis=1, keepdims=True)
        b_var = np.cov(b)
        d, v = np.linalg.eig(b_var)
        b_sigma = v.dot(np.diag(d ** 0.5)).dot(v.T)

        transform = b_sigma.dot(a_sigma_inv)
        z[i,:] = (transform.dot(a - a_mean) + b_mean).reshape(shape)
    return z

Conversion de BGR en YIQ

La conversion mutuelle entre BGR et YIQ est la suivante. BGR est utilisé à la place de RVB car le modèle VGG utilisé pour la conversion d'image utilise BGR comme entrée.

#x est un tableau numpy représentant une image et la forme est(batch_size, 3, height, width)
def bgr_to_yiq(x):
    transform = np.asarray([[0.114, 0.587, 0.299], [-0.322, -0.274, 0.596], [0.312, -0.523, 0.211]], dtype=np.float32)
    n, c, h, w = x.shape
    x = x.transpose((1, 0, 2, 3)).reshape((c, -1))
    x = transform.dot(x)
    return x.reshape((c, n, h, w)).transpose((1, 0, 2, 3))

def yiq_to_bgr(x):
    transform = np.asarray([[1, -1.106, 1.703], [1, -0.272, -0.647], [1, 0.956, 0.621]], dtype=np.float32)
    n, c, h, w = x.shape
    x = x.transpose((1, 0, 2, 3)).reshape((c, -1))
    x = transform.dot(x)
    return x.reshape((c, n, h, w)).transpose((1, 0, 2, 3))

Courir

J'ai effectivement essayé cette méthode. Le code source est ci-dessous. https://github.com/dsanno/chainer-neural-style

Méthode d'exécution

Vous pouvez le faire comme suit:

Effectuer la correspondance d'histogramme de couleur

$ python src/run.py -g 0 -c content.jpg -s style.jpg -w 384 -o out_dir_01 --iter 2000 --lr 10 --match_color_histogram --initial_image content

Exécuter uniquement la luminance

$ python src/run.py -g 0 -c content.jpg -s style.jpg -w 384 -o out_dir_02 --iter 2000 --lr 10 --luminance_only --initial_image content

Résultat d'exécution

Le résultat de l'exécution est affiché. La correspondance de l'histogramme des couleurs semble être similaire à l'image du contenu, mais le mur est de couleur chair et la bonne couleur n'est pas peinte au bon endroit. Le résultat du papier était une plus belle palette de couleurs, donc il se peut que quelque chose ne va pas. Pour la luminance uniquement, une image similaire à l'image de style est produite.

Image de contenu Image de style Color histogram matching Luminance-only transfer
Comme ci-dessus
Comme ci-dessus
Comme ci-dessus

En optimisant la conversion de style, il semble bon de rendre l'image initiale identique à l'image de contenu. Si l'image initiale est aléatoire, la lumière et l'obscurité s'écarteront de l'image du contenu comme indiqué ci-dessous. (L'image de style est la nuit étoilée de Goch, la méthode est uniquement en luminance)

Résumé

Implémentation de la conversion du style d'image tout en préservant la couleur.

Cette méthode est une combinaison de conversion de style existant et de conversion de couleur des images de contenu et des images de style, et peut être considérée comme une méthode simple. De cette façon, vous pouvez obtenir différents effets en modifiant un peu la méthode, donc j'ai pensé qu'il était important non seulement d'imiter la nouvelle méthode, mais aussi de réfléchir à la possibilité de la concevoir vous-même.

Les références

Recommended Posts

Une méthode de conversion du style d'une image tout en préservant la couleur
Cours ROS 119 Corriger la couleur de l'image de la caméra
Une implémentation Python simple de la méthode k-voisinage (k-NN)
Résumé de l'exploration d'image effectuée à la vitesse d'une seconde
J'ai fait une image ponctuelle de l'image d'Irasutoya. (partie 1)
J'ai fait une image ponctuelle de l'image d'Irasutoya. (partie 2)
Changer le style de matplotlib
L'image est Namekuji
Un aperçu de DELG, une nouvelle méthode d'extraction de caractéristiques d'image qui attire l'attention avec Kaggle
J'ai créé un robot Line qui devine le sexe et l'âge d'une personne à partir de l'image
Comprendre la fonction de convolution en utilisant le traitement d'image comme exemple
[Statistiques] Saisir l'image de la théorie de la limitation du pôle central avec un graphe
[Go] Créez une commande CLI pour changer l'extension de l'image
Une fonction qui mesure le temps de traitement d'une méthode en python
L'histoire de la création d'un outil pour charger une image avec Python ⇒ l'enregistrer sous un autre nom
Extraire les points caractéristiques d'une image
Obtenir les attributs d'un objet
Convertir une chaîne en image
L'histoire de l'exportation d'un programme
Mémorandum d'introduction du modèle de données EXODUS de la méthode des éléments finis (FEM)
Hit une méthode d'une instance de classe avec l'API Web Python Bottle
Je veux colorer une partie de la chaîne Excel avec Python
Ouvrez un fichier Excel en Python et coloriez la carte du Japon
Parlez de la probabilité d'évasion d'une marche aléatoire sur une grille entière
Comment lire une vidéo tout en regardant le nombre d'images (Mac)
Faites attention au type lorsque vous créez un masque d'image avec Numpy
Comment enregistrer les informations de point caractéristique de l'image dans un fichier et l'utiliser pour la mise en correspondance