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 →
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 ↓
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.
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. .. ..
Ç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 ↓
(J'ai emprunté ce dessin au trait de la publication de @ lio8644.)
Ça va.
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
génial.
C'est devenu un monstre coloré, mais il y en a comme ça.
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
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.
(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
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.
↑ 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