Quand j'ai remarqué, GW est passé en un clin d'œil. Cette année, GW a fait le tour de Tokyo (y compris certains Saitama) avec toute la famille. J'ai escaladé le Sky Tree, mais je ne pensais pas qu'il y avait autant de monde. Cela me paraissait intéressant d'y aller la nuit si je devais y aller ensuite. On dirait qu'il est en cours de dépistage.
J'ai modifié la structure du réseau et diverses choses dans l'ensemble de données pour améliorer le dessin au trait qui peut être extrait, donc je l'ai mis à jour avec son contenu.
Comme je l'ai écrit dans l'article précédent, j'ai essayé la coloration de dessin au trait avec Deep Learning, mais dans le processus, j'ai senti qu'il y avait des problèmes avec l'ensemble de données. Le dessin au trait lui-même a été créé en référence à http://qiita.com/khsk/items/6cf4bae0166e4b12b942, mais il semble y avoir des problèmes.
Eh bien, il y a quelques problèmes, mais je travaille toujours dessus car il peut être créé facilement (uniquement si OpenCV fonctionne) et à grande vitesse (OpenCV est abrégé).
Certaines des recherches existantes sont les suivantes. http://hi.cs.waseda.ac.jp:8081/
Ceci est un article. http://hi.cs.waseda.ac.jp/~esimo/publications/SimoSerraSIGGRAPH2016.pdf
Il s'agit d'une technique pour AutoEncoder qui convertit le dessin brut en dessin au trait. Cette fois, je l'ai fait en référence à cela.
class AutoEncoder(object):
"""Define autoencoder"""
def __init__(self):
self.conv1 = Encoder(3, 48, 5, 5, strides=[1, 2, 2, 1], name='encoder1')
self.conv1_f1 = Encoder(48, 128, 3, 3, name='encoder1_flat1')
self.conv1_f2 = Encoder(128, 128, 3, 3, name='encoder1_flat2')
self.conv2 = Encoder(128, 256, 5, 5, strides=[1, 2, 2, 1], name='encoder2')
self.conv2_f1 = Encoder(256, 256, 3, 3, name='encoder2_flat1')
self.conv2_f2 = Encoder(256, 256, 3, 3, name='encoder2_flat2')
self.conv3 = Encoder(256, 256, 5, 5, strides=[1, 2, 2, 1], name='encoder3')
self.conv3_f1 = Encoder(256, 512, 3, 3, name='encoder3_flat1')
self.conv3_f2 = Encoder(512, 1024, 3, 3, name='encoder3_flat2')
self.conv3_f3 = Encoder(1024, 512, 3, 3, name='encoder3_flat3')
self.conv3_f4 = Encoder(512, 256, 3, 3, name='encoder3_flat4')
self.bnc1 = op.BatchNormalization(name='bnc1')
self.bnc1_f1 = op.BatchNormalization(name='bnc1_flat1')
self.bnc1_f2 = op.BatchNormalization(name='bnc1_flat2')
self.bnc2 = op.BatchNormalization(name='bnc2')
self.bnc2_f1 = op.BatchNormalization(name='bnc2_flat1')
self.bnc2_f2 = op.BatchNormalization(name='bnc2_flat2')
self.bnc3 = op.BatchNormalization(name='bnc3')
self.bnc3_f1 = op.BatchNormalization(name='bnc3_flat1')
self.bnc3_f2 = op.BatchNormalization(name='bnc3_flat2')
self.bnc3_f3 = op.BatchNormalization(name='bnc3_flat3')
self.bnc3_f4 = op.BatchNormalization(name='bnc3_flat4')
self.deconv1 = Decoder(256, 256, 4, 4, strides=[1, 2, 2, 1], name='decoder1')
self.deconv1_f1 = Encoder(256, 128, 3, 3, name='decoder1_flat1')
self.deconv1_f2 = Encoder(128, 128, 3, 3, name='decoder1_flat2')
self.deconv2 = Decoder(128, 128, 4, 4, strides=[1, 2, 2, 1], name='decoder2')
self.deconv2_f1 = Encoder(128, 128, 3, 3, name='decoder2_flat1')
self.deconv2_f2 = Encoder(128, 48, 3, 3, name='decoder2_flat2')
self.deconv3 = Decoder(48, 48, 4, 4, strides=[1, 2, 2, 1], name='decoder3')
self.deconv3_f1 = Decoder(48, 24, 3, 3, name='decoder3_flat1')
self.deconv3_f2 = Decoder(24, 1, 3, 3, name='decoder3_flat2')
self.bnd1 = op.BatchNormalization(name='bnd1')
self.bnd1_f1 = op.BatchNormalization(name='bnd1_flat1')
self.bnd1_f2 = op.BatchNormalization(name='bnd1_flat2')
self.bnd2 = op.BatchNormalization(name='bnd2')
self.bnd2_f1 = op.BatchNormalization(name='bnd2_flat1')
self.bnd2_f2 = op.BatchNormalization(name='bnd2_flat2')
self.bnd3 = op.BatchNormalization(name='bnd3')
self.bnd3_f1 = op.BatchNormalization(name='bnd3_flat1')
def autoencoder(images, height, width):
"""make autoencoder network"""
AE = AutoEncoder()
def div(v, d):
return max(1, v // d)
relu = tf.nn.relu
net = relu(AE.bnc1(AE.conv1(images, [height, width])))
net = relu(AE.bnc1_f1(AE.conv1_f1(net, [div(height, 2), div(width, 2)])))
net = relu(AE.bnc1_f2(AE.conv1_f2(net, [div(height, 2), div(width, 2)])))
net = relu(AE.bnc2(AE.conv2(net, [div(height, 2), div(width, 2)])))
net = relu(AE.bnc2_f1(AE.conv2_f1(net, [div(height, 4), div(width, 4)])))
net = relu(AE.bnc2_f2(AE.conv2_f2(net, [div(height, 4), div(width, 4)])))
net = relu(AE.bnc3(AE.conv3(net, [div(height, 4), div(width, 4)])))
net = relu(AE.bnc3_f1(AE.conv3_f1(net, [div(height, 8), div(width, 8)])))
net = relu(AE.bnc3_f2(AE.conv3_f2(net, [div(height, 8), div(width, 8)])))
net = relu(AE.bnc3_f3(AE.conv3_f3(net, [div(height, 8), div(width, 8)])))
net = relu(AE.bnc3_f4(AE.conv3_f4(net, [div(height, 8), div(width, 8)])))
net = relu(AE.bnd1(AE.deconv1(net, [div(height, 4), div(width, 4)])))
net = relu(AE.bnd1_f1(AE.deconv1_f1(net, [div(height, 4), div(width, 4)])))
net = relu(AE.bnd1_f2(AE.deconv1_f2(net, [div(height, 4), div(width, 4)])))
net = relu(AE.bnd2(AE.deconv2(net, [div(height, 2), div(width, 2)])))
net = relu(AE.bnd2_f1(AE.deconv2_f1(net, [div(height, 2), div(width, 2)])))
net = relu(AE.bnd2_f2(AE.deconv2_f2(net, [div(height, 2), div(width, 2)])))
net = relu(AE.bnd3(AE.deconv3(net, [height, width])))
net = relu(AE.bnd3_f1(AE.deconv3_f1(net, [height, width])))
net = tf.nn.sigmoid(AE.deconv3_f2(net, [height, width]))
return net
AutoEncoder ressemble à ceci. Je me suis demandé si je pouvais l'obtenir d'une manière ou d'une autre. Dans l'article, il semble que l'accent soit mis sur la méthode appelée carte de perte, mais comme je ne sais pas comment faire référence à l'histogramme dans Tensorflow, cette partie est implémentée.
Le réseau utilisé était environ 250 000 fois avec les paramètres suivants.
J'ai abandonné la taille énorme parce que je ne pouvais pas survivre même avec 2 Go de mémoire en premier lieu. Il semble bon de le réduire une fois, de l'extraire, puis d'insérer un encodeur pour augmenter la résolution.
Mikon! Je l'ai peint. Amezuku @ Recherche d'emploi
Toutes les images originales sont empruntées car je les ai peintes avec Pixiv. Cette image n'a pas de dessin au trait original, et il n'y a pas de cible de comparaison en premier lieu, alors c'est tout. Cela a pris environ 10 secondes pour cette taille et pour le GPU, donc honnêtement, je ne veux pas penser à le faire avec un processeur.
Je pense que c'est assez solide. La taille moyenne des images de l'ensemble de données est d'environ 1000 \ * 1000, ce qui est assez grand, de sorte que même les images d'une certaine taille peuvent être gérées. Cependant, malheureusement, il y a une dentelure propre à la partie inférieure ... Cela ne peut pas être dit car il y a des moments où il sort et des moments où il ne sort pas.
La taille est de 256 \ * 256. Pour le moment, j'inclurai également la version que j'ai retirée avec OpenCV. Ignorez le tsukkomi que 256 \ * 256 est miniature.
Image originale. À première vue, il semble qu'une ligne apparaîtra, mais ...
Version OpenCV. Puisque toutes les belles couleurs ont été libérées, je ne peux pas nier le sentiment qu'il s'agit d'un dessin au trait ou d'une échelle de gris.
Cette version réseau. C'est en partie suspect (ou plutôt, la partie main est impossible à jouer), mais l'influence de l'ombre peut être assez bien ignorée, et l'expression de la partie cheveux est simple, c'est un miso avant, mais ça fait plutôt bien N'est-ce pas? Des détails trop fins tels que des volants sont écrasés par la pierre, mais il semble que cela puisse être résolu petit à petit si vous continuez à en apprendre un peu plus.
L'ensemble de données utilisé pour la formation est essentiellement obtenu à partir des catégories peintes par Pixiv. La chose la plus importante dans la création d'un ensemble de données était que ** le dessin au trait et le dessin en couleur avaient le même aspect **. Si cela change, ce sera comme ne pas pouvoir apprendre en premier lieu, alors je les ai rassemblés en vérifiant chacun d'eux.
Aussi, j'ai parfois trouvé que même si le rapport hauteur / largeur était le même, il y avait une légère différence entre le dessin au trait et l'image colorée **. J'ai dû l'omettre correctement parce que l'apprentissage ne se poursuivrait pas s'il y en avait aussi.
Cela dépend de la façon dont vous le peignez, mais je pense que c'est une ligne plus simple qu'OpenCV, et les détails ne sont pas tellement perdus. Cependant, en raison de la structure ou de la nature de ce que nous faisons, il y a des inconvénients, notamment le fait que nous ne pouvons rien y faire.
Fondamentalement, plutôt que de l'utiliser tel quel, je pense que ce sera plutôt un traitement basé sur cela.
Les réseaux de génération tels que AutoEncoder sont intéressants. Je veux également relever le défi de donner des paramètres pour changer la façon dont les dessins au trait sont créés.
C'est difficile à étudier et à mettre en œuvre, mais comme les amateurs peuvent faire du Deep Learning, nous vous recommandons d'investir un peu et de l'essayer (seul ou dans le cloud).
Recommended Posts