[PYTHON] Un débutant a essayé de colorier un dessin au trait avec un chainer. J'ai pu le faire.

Le débarquement est tai2an, qui est principalement en charge du travail chez P-FN, qui serait banalisé et le brasage a une plus grande valeur ajoutée. Lors de l'Amazon Picking Challenge, qui a été diffusé dans tout le pays sur NHK, j'ai fait une main collante et une diapositive pleine de sentiment Robocon. Cependant, je voulais faire un apprentissage profond, alors j'ai commencé à étudier le chainer il y a un mois ou deux. Je voulais colorier le dessin au trait parce que c'était un gros problème, alors j'ai essayé différentes choses.

La coloration des dessins au trait est un processus d'apprentissage supervisé, vous avez donc besoin d'un ensemble de données (de préférence volumineux) de dessins au trait et d'images en couleur. Cette fois, OpenCV est utilisé pour extraire correctement les dessins au trait à partir d'images couleur.

Exemple d'extraction 6c55da4e7961024012e78b38db048f53ce8e3a31.jpg→ 6c55da4e7961024012e78b38db048f53ce8e3a31.jpg

Collectez des images couleur pour créer un dessin au trait et vous obtenez un jeu de données complet. (J'utilise environ 600000 cette fois)

En ce qui concerne la forme du réseau, j'ai utilisé un réseau appelé U-net, qui est utilisé en fusionnant la sortie de la couche lors de la convolution au début et en déconvolution à la fin. Cela semble approprié pour faire référence à un dessin au trait et le colorier. (U-net est également utilisé dans px2px) Pour le moment, j'ai essayé d'apprendre à minimiser le carré de l'erreur à partir de la bonne réponse. Je comprends que la définition du réseau elle-même est généralement correcte si la sortie de la couche et l'entrée de la couche suivante correspondent, mais c'est un peu difficile à comprendre car il n'y avait pas beaucoup de moyen de créer un ensemble de données que vous définissez vous-même. Je me demandais.

Voici le résultat de l'étude pendant la nuit et de l'alimentation des données de test ↓

スクリーンショット 2016-12-25 15.36.09.png

Eh bien, je peux ressentir la sensation du réseau neuronal, "Je peux comprendre la couleur de la peau d'une manière ou d'une autre, mais je ne sais rien d'autre, je ne peux pas deviner la couleur des cheveux ou des vêtements du personnage illustré." .. ..

C'est là qu'intervient l'Adversary Net. Connu sous le nom de Ad Auntie. Tante est un gars qui apprend la différence entre une image réelle et une image colorée d'un réseau neuronal et fait une brèche. Par conséquent, si vous ne diffusez que des images de couleur sépia de couleur peau, vous apprendrez d'un seul coup et vous finirez par ne pas manger de bon.

Cependant, si la femme publicitaire est trop forte, le côté coloré avec le nombril plié sera flou, alors soyez prudent.

2e3a61e3da383137ae334afe52c1efacd7249a86.jpg2e3a61e3da383137ae334afe52c1efacd7249a86.jpg2e3a61e3da383137ae334afe52c1efacd7249a86.jpg

Avec ce genre de sentiment, les couleurs sont sûrement attachées, mais cela devient un système artistique comme s'il s'agissait d'un dessin au trait. (Eh bien, c'est peut-être la voie de l'art comme ça

Si vous tournez l'apprentissage tout en faisant attention à l'équilibre avec le composant de différence de l'image d'origine. .. ..

スクリーンショット 2016-12-25 17.08.51.jpg

Ça se colore! Huh

C’est encore mieux! J'ai également appris un réseau qui réduit le dessin au trait 512x512px, peint 128x128px dans la première étape et les couleurs 512x512px dans la deuxième étape (la forme du réseau est presque la même dans la deuxième étape, mais l'entrée est 4 canaux et nouvellement ajoutée. Se recycler. Ce n'est pas une tante publicitaire)

Le résultat est ici ↓

スクリーンショット 2016-12-25 15.11.38.jpg

(J'ai emprunté ce dessin au trait de la publication de @ lio8644.)

Ça va.

スクリーンショット 2016-12-25 15.56.10.jpg

Ce n'est pas mauvais.

Tant que j'utilise le dessin au trait extrait pour le test, ça a l'air plutôt bien, mais qu'en est-il du dessin au trait?

J'ai emprunté un dessin au trait à une étiquette du système de peinture de pixiv et l'ai testé. (Fondamentalement, tous sont des CNN, donc même si le rapport hauteur / largeur change un peu, il peut être géré.

Denden

スクリーンショット 2016-12-25 15.03.39.jpg

génial.

スクリーンショット 2016-12-25 14.58.21.jpg

C'est devenu un monstre coloré, mais il y en a comme ça.

スクリーンショット 2016-12-25 17.29.48.jpg

Se sentir bien résumé

Au fait, après tout, il y a quelque chose comme vouloir que vous peigniez cette couleur, non? C'est pourquoi j'ai changé l'entrée du premier étage en 4 canaux pour pouvoir donner des indices supplémentaires.

Tsumari

スクリーンショット 2016-12-25 17.49.07.jpg

Vous pouvez définir des exigences telles que des cheveux bruns, un pull bleu clair et une jupe bleu marine.

Si vous donnez une impression approximative que vous voulez que cela ressemble à ceci, ce sera plutôt bien.

スクリーンショット 2016-12-25 14.57.25.jpg スクリーンショット 2016-12-25 15.03.03.jpg

(Si le dessin au trait est bon, j'ai l'impression que c'est beau si je le peins, mais w

Il est également possible de donner beaucoup d'indices assez détaillés. (C'est un peu difficile à comprendre, mais je donne des indices

スクリーンショット 2016-12-25 14.53.10.jpg

Joyeux Noël! !!

Avec cela, je suis également promu d'artisan à dessinateur!

Donc, je pense que la coloration automatique des dessins au trait et la coloration avec des indices ont été considérablement améliorées.

Je ne pense pas que je puisse battre la peinture appropriée des peintres, mais je pense qu'il est pratique d'essayer de peindre grossièrement. Ce serait pratique s'il était plus rapide de colorier les dessins animés que de coller les tons. (Ce réseau neuronal est puissant pour la couleur de la peau ... Savez-vous ce que vous voulez dire?)

En passant, il y a encore quelques faiblesses.

Par exemple, étant donné que vous apprenez Adversary Net et les astuces en même temps, l'effet d'entraînement lorsque vous donnez des astuces peut devenir instable.

スクリーンショット 2016-12-25 16.35.04.jpg

↑ Je voulais uniquement que le maillot de bain soit peint dans une couleur différente, mais les couleurs des autres parties ont également changé de manière significative. Si vous ne l'utilisez que comme outil de coloration facile, il peut être plus stable de s'entraîner uniquement avec des indices.

De plus, comme la couleur est peinte après l'avoir réduite une fois, même si le dessin au trait est trop épais / fin, il y a des cas où la ligne est écrasée ou sautée et cela ne fonctionne pas, ou même si vous demandez une peinture fine avec des indices Dans certains cas, cela ne sera pas reflété.

Ce serait cool si un NN pouvait gérer tous les détails, mais il semble nécessaire de faire des ajustements pour chaque application lors de son utilisation comme outil.

Emprunteur de dessin au trait http://www.pixiv.net/member_illust.php?mode=medium&illust_id=31274285 http://www.pixiv.net/member_illust.php?mode=manga&illust_id=43369404 http://www.pixiv.net/member_illust.php?mode=medium&illust_id=56689287 http://www.pixiv.net/member_illust.php?mode=medium&illust_id=40487409 http://www.pixiv.net/member_illust.php?mode=medium&illust_id=10552795 https://twitter.com/lio8644

À propos, la structure de ce réseau est la même pour les première et deuxième étapes, et cela ressemble à ceci

unet.py


    class UNET(chainer.Chain):
        def __init__(self):
            super(UNET, self).__init__(
                c0 = L.Convolution2D(4, 32, 3, 1, 1),
                c1 = L.Convolution2D(32, 64, 4, 2, 1),
                c2 = L.Convolution2D(64, 64, 3, 1, 1),
                c3 = L.Convolution2D(64, 128, 4, 2, 1),
                c4 = L.Convolution2D(128, 128, 3, 1, 1),
                c5 = L.Convolution2D(128, 256, 4, 2, 1),
                c6 = L.Convolution2D(256, 256, 3, 1, 1),
                c7 = L.Convolution2D(256, 512, 4, 2, 1),
                c8 = L.Convolution2D(512, 512, 3, 1, 1),

                dc8 = L.Deconvolution2D(1024, 512, 4, 2, 1),
                dc7 = L.Convolution2D(512, 256, 3, 1, 1),
                dc6 = L.Deconvolution2D(512, 256, 4, 2, 1),
                dc5 = L.Convolution2D(256, 128, 3, 1, 1),
                dc4 = L.Deconvolution2D(256, 128, 4, 2, 1),
                dc3 = L.Convolution2D(128, 64, 3, 1, 1),
                dc2 = L.Deconvolution2D(128, 64, 4, 2, 1),
                dc1 = L.Convolution2D(64, 32, 3, 1, 1),
                dc0 = L.Convolution2D(64, 3, 3, 1, 1),

                bnc0 = L.BatchNormalization(32),
                bnc1 = L.BatchNormalization(64),
                bnc2 = L.BatchNormalization(64),
                bnc3 = L.BatchNormalization(128),
                bnc4 = L.BatchNormalization(128),
                bnc5 = L.BatchNormalization(256),
                bnc6 = L.BatchNormalization(256),
                bnc7 = L.BatchNormalization(512),
                bnc8 = L.BatchNormalization(512),

                bnd8 = L.BatchNormalization(512),
                bnd7 = L.BatchNormalization(256),
                bnd6 = L.BatchNormalization(256),
                bnd5 = L.BatchNormalization(128),
                bnd4 = L.BatchNormalization(128),
                bnd3 = L.BatchNormalization(64),
                bnd2 = L.BatchNormalization(64),
                bnd1 = L.BatchNormalization(32)
        )

    def calc(self,x, test = False):
        e0 = F.relu(self.bnc0(self.c0(x), test=test))
        e1 = F.relu(self.bnc1(self.c1(e0), test=test))
        e2 = F.relu(self.bnc2(self.c2(e1), test=test))
        e3 = F.relu(self.bnc3(self.c3(e2), test=test))
        e4 = F.relu(self.bnc4(self.c4(e3), test=test))
        e5 = F.relu(self.bnc5(self.c5(e4), test=test))
        e6 = F.relu(self.bnc6(self.c6(e5), test=test))
        e7 = F.relu(self.bnc7(self.c7(e6), test=test))
        e8 = F.relu(self.bnc8(self.c8(e7), test=test))

        d8 = F.relu(self.bnd8(self.dc8(F.concat([e7, e8])), test=test))
        d7 = F.relu(self.bnd7(self.dc7(d8), test=test))
        d6 = F.relu(self.bnd6(self.dc6(F.concat([e6, d7])), test=test))
        d5 = F.relu(self.bnd5(self.dc5(d6), test=test))
        d4 = F.relu(self.bnd4(self.dc4(F.concat([e4, d5])), test=test))
        d3 = F.relu(self.bnd3(self.dc3(d4), test=test))
        d2 = F.relu(self.bnd2(self.dc2(F.concat([e2, d3])), test=test))
        d1 = F.relu(self.bnd1(self.dc1(d2), test=test))
        d0 = self.dc0(F.concat([e0, d1]))

        return d0

Ad Auntie

adv.py


class DIS(chainer.Chain):
    def __init__(self):
        super(DIS, self).__init__(
                c1 = L.Convolution2D(3, 32, 4, 2, 1),
                c2 = L.Convolution2D(32, 32, 3, 1, 1),
                c3 = L.Convolution2D(32, 64, 4, 2, 1),
                c4 = L.Convolution2D(64, 64, 3, 1, 1),
                c5 = L.Convolution2D(64, 128, 4, 2, 1),
                c6 = L.Convolution2D(128, 128, 3, 1, 1),
                c7 = L.Convolution2D(128, 256, 4, 2, 1),
                l8l = L.Linear(None, 2, wscale=0.02*math.sqrt(8*8*256)),

                bnc1 = L.BatchNormalization(32),
                bnc2 = L.BatchNormalization(32),
                bnc3 = L.BatchNormalization(64),
                bnc4 = L.BatchNormalization(64),
                bnc5 = L.BatchNormalization(128),
                bnc6 = L.BatchNormalization(128),
                bnc7 = L.BatchNormalization(256),
        )

    def calc(self,x, test = False):
        h = F.relu(self.bnc1(self.c1(x), test=test))
        h = F.relu(self.bnc2(self.c2(h), test=test))
        h = F.relu(self.bnc3(self.c3(h), test=test))
        h = F.relu(self.bnc4(self.c4(h), test=test))
        h = F.relu(self.bnc5(self.c5(h), test=test))
        h = F.relu(self.bnc6(self.c6(h), test=test))
        h = F.relu(self.bnc7(self.c7(h), test=test))
        return  self.l8l(h)

Recommended Posts

Un débutant a essayé de colorier un dessin au trait avec un chainer. J'ai pu le faire.
J'ai essayé d'extraire le dessin au trait de l'image avec Deep Learning
Depuis qu'il y avait Doppelgenger, j'ai essayé de le distinguer avec l'intelligence artificielle (rires) (Partie 2)
Depuis qu'il y avait Doppelgenger, j'ai essayé de le distinguer avec l'intelligence artificielle (rires) (Partie 1)
Un mémorandum lors de l'acquisition automatique avec du sélénium
J'ai essayé de créer un LINE BOT "Sakurai-san" avec API Gateway + Lambda
Quand j'ai essayé de créer un VPC avec AWS CDK mais que je n'ai pas pu le faire
Quand j'ai essayé de créer un environnement virtuel avec Python, cela n'a pas fonctionné
J'ai pu me moquer d'AWS-Batch avec python, moto, donc je vais le laisser
Dans IPython, quand j'ai essayé de voir la valeur, c'était un générateur, donc je l'ai inventé quand j'étais frustré.
J'ai essayé d'entraîner la fonction péché avec chainer
Python: peut être répété en lambda
Quand j'ai essayé de faire une communication socket avec Raspberry Pi, le protocole était différent
C'était un peu difficile de faire flacon avec la version docker de nginx-unit
AtCoder Beginner Contest 177 Problème C J'ai essayé de découvrir pourquoi c'était faux
Les débutants en Python ont créé un chat BOT alors j'ai essayé de résumer comment le faire
Traitement d'image avec Python (j'ai essayé de le binariser en art mosaïque 0 et 1)
J'ai essayé de faire de l'art créatif avec l'IA! J'ai programmé une nouveauté! (Article: Réseau Adversaire Créatif)
J'ai essayé d'implémenter une ligne moyenne mobile de volume avec Quantx
[IOS] Animation GIF avec Pythonista3. J'en étais accro.
J'ai pu implémenter l'authentification d'application Web avec flask-login
J'ai essayé de créer automatiquement un rapport avec la chaîne de Markov
J'ai essayé de notifier les informations de retard de train avec LINE Notify
J'ai essayé de résoudre le problème d'optimisation des combinaisons avec Qiskit
J'ai essayé de commencer avec Hy ・ Définir une classe
J'ai essayé d'implémenter ListNet d'apprentissage de rang avec Chainer
J'ai essayé de trier une colonne FizzBuzz aléatoire avec un tri à bulles.
Un débutant en python a essayé de faire un stage dans une entreprise informatique
J'ai essayé d'écrire dans un modèle de langage profondément appris
Quand j'ai essayé d'installer PIL et matplotlib dans un environnement virtualenv, j'en étais accro.
Quand j'ai essayé le concours AtCoder pour débutants, c'était un résultat terrible, alors je regarde en arrière
J'ai créé un serveur avec socket Python et ssl et j'ai essayé d'y accéder depuis le navigateur
[5e] J'ai essayé de créer un certain outil de type Authenticator avec python
[2nd] J'ai essayé de créer un certain outil de type Authenticator avec python
[Python] Un mémo que j'ai essayé de démarrer avec asyncio
J'ai essayé de créer une liste de nombres premiers avec python
Je souhaite rechercher le texte intégral avec elasticsearch + python
J'ai essayé de faire un processus d'exécution périodique avec Selenium et Python
J'ai essayé de résumer ce qui était sorti avec Qiita avec Word cloud
Une note à laquelle j'étais accro lors de la création d'une table avec SQL Alchemy
J'ai essayé de créer une application de notification de publication à 2 canaux avec Python
J'ai essayé de créer des taureaux et des vaches avec un programme shell
J'ai essayé de créer une application todo en utilisant une bouteille avec python
[4th] J'ai essayé de créer un certain outil de type Authenticator avec python
J'avais du mal à faire mes devoirs, j'ai donc utilisé Python pour la comptabilité de gestion.
Je veux faire ○○ avec les Pandas
[1er] J'ai essayé de créer un certain outil de type Authenticator avec python
J'ai essayé de faire une étrange citation pour Jojo avec LSTM
J'ai essayé de créer un mécanisme de contrôle exclusif avec Go
J'ai réussi à convertir jpg en png car la transparence n'a pas été altérée
Je veux le faire avec Python lambda Django, mais je vais m'arrêter
J'ai essayé de communiquer avec un serveur distant par communication Socket avec Python.
J'ai essayé de mettre en œuvre une blockchain qui fonctionne réellement avec environ 170 lignes
Lorsque j'ai essayé d'exécuter Python, j'ai été ignoré dans le Microsoft Store
J'ai essayé de créer un programme qui convertit les nombres hexadécimaux en nombres décimaux avec python