https://github.com/rezoo/illustration2vec illustration2vec est un modèle capable de détecter les caractéristiques et les balises des illustrations. La structure du modèle est presque un modèle VGG. Il y a quelques changements par rapport au VGG original, donc pour plus de détails, voir le document de commentaires au lien ci-dessus. C'est un modèle de café et de chainer. C'est un modèle intéressant, mais le chainer semble être un développement terminé, donc je voulais vraiment le réutiliser et j'ai écrit un code de conversion en keras. Je n'ai jamais utilisé de torche, alors allons-y.
L'exécution a été faite avec google colaboratory, donc lien ci-dessous. https://colab.research.google.com/drive/1UZN7pn4UzU5s501dwSIA2IHGmjnAmouY
Si vous ne pouvez pas ouvrir le lien, copiez ce qui suit dans colab et cela fonctionnera.
<détails> Tout ce que nous faisons est simplement de définir un modèle avec la même structure dans les keras et de l'initialiser avec le poids du modèle de chaînage.
Il y a trois changements comme suit.
・ Transposition du poids
Le noyau de convolution de ce modèle de chainer est (out_channel, in_channel, k_size, k_size), mais il a été transposé en (k_size, k_size, in_channel, out_channel) pour le modèle keras.
-Change l'image d'entrée de BGR à RVB
Dans le modèle d'origine, l'image d'entrée est BGR, mais je l'ai changée en entrée RVB. Par conséquent, le noyau convolutif de la première couche est inversé sur l'axe de in_channel.
-Change l'image d'entrée en channel_last
La convolution de chaînage a une entrée de (N, C, H, W), mais est la valeur par défaut de keras (N, H, W, C). L'entrée du modèle converti est la taille de (lot, 224, 224, 3). Si vous passez la liste de numpy.array de l'image au lien colab ci-dessus ou à la fonction de redimensionnement dans tout le code, il sera redimensionné + normalisé. Il existe deux modèles, illust2vec_tag_ver200.h5 et illust2vec_ver200.h5, mais la première sortie est la tag_list sur https://github.com/rezoo/illustration2vec. Il s'agit de la probabilité de chacune des 1539 balises dans .json. La sortie du deuxième modèle est un vecteur caractéristique de l'image. Veuillez signaler toute lacune.
Recommended Posts
!git clone https://github.com/rezoo/illustration2vec.git
!sh illustration2vec/get_models.sh
!pip install -r /content/illustration2vec/requirements.txt
!mv /content/illustration2vec/i2v /content/
import i2v
illust2vec_tag = i2v.make_i2v_with_chainer('/content/illustration2vec/illust2vec_tag_ver200.caffemodel', '/content/illustration2vec/tag_list.json')
%tensorflow_version 2.x
import tensorflow as tf
import numpy as np
#tag estimater model
model_tag = tf.keras.Sequential(name='illustration2vec_tag')
model_tag.add(tf.keras.layers.Input(shape=(224, 224, 3)))
pool_idx = [0, 1, 3, 5, 7]
for i, chainer_layer in enumerate(illust2vec_tag.net.children()):
kernel, bias = tuple(chainer_layer.params())
k_kernel = np.transpose(kernel.data, axes=[3, 2, 1, 0])
bias = bias.data
if i == 0:
k_kernel = k_kernel[:,:,::-1,:]
channel = bias.shape[0]
keras_layer = tf.keras.layers.Conv2D(channel, 3, padding='SAME', activation='relu', kernel_initializer=tf.keras.initializers.constant(k_kernel), bias_initializer=tf.keras.initializers.constant(bias), name='Conv_%d'%i)
model_tag.add(keras_layer)
if i in pool_idx:
model_tag.add(tf.keras.layers.MaxPooling2D())
del kernel, bias
model_tag.add(tf.keras.layers.AveragePooling2D(pool_size=(7, 7)))
model_tag.add(tf.keras.layers.Lambda(lambda x : tf.nn.sigmoid(tf.squeeze(x, axis=[1, 2])), name='sigmoid'))
model_tag.save('illust2vec_tag_ver200.h5')
del model_tag, illust2vec_tag
#feature vector model
illust2vec = i2v.make_i2v_with_chainer('/content/illustration2vec/illust2vec_ver200.caffemodel')
model = tf.keras.Sequential(name='illustration2vec')
model.add(tf.keras.layers.Input(shape=(224, 224, 3)))
pool_idx = [0, 1, 3, 5, 7]
for i, chainer_layer in enumerate(illust2vec.net.children()):
if i == 12:
break
kernel, bias = tuple(chainer_layer.params())
if len(kernel.data.shape) == 4:
k_kernel = np.transpose(kernel.data, axes=[3, 2, 1, 0])
bias = bias.data
if i == 0:
k_kernel = k_kernel[:,:,::-1,:]
channel = bias.shape[0]
keras_layer = tf.keras.layers.Conv2D(channel, 3, padding='SAME', activation='relu', kernel_initializer=tf.keras.initializers.constant(k_kernel), bias_initializer=tf.keras.initializers.constant(bias), name='Conv_%d'%i)
model.add(keras_layer)
if i in pool_idx:
model.add(tf.keras.layers.MaxPooling2D())
elif i == 10:
model.add(tf.keras.layers.Flatten())
elif len(kernel.data.shape) == 2:
model.add(tf.keras.layers.Dense(4096, kernel_initializer=tf.keras.initializers.constant(kernel.data), bias_initializer=tf.keras.initializers.constant(bias.data), name='encode1'))
del kernel, bias
model.save('illust2vec_ver200.h5')
del model, illust2vec
def resize(imgs):
mean = tf.constant(np.array([181.13838569, 167.47864617, 164.76139251]).reshape((1, 1, 3)), dtype=tf.float32)
resized = []
for img in imgs:
img = tf.cast(img, tf.float32)
im_max = tf.reduce_max(img, keepdims=True)
im_min = tf.reduce_min(img, keepdims=True)
im_std = (img - im_min) / (im_max - im_min + 1e-10)
resized_std = tf.image.resize(im_std, (224, 224))
resized_im = resized_std*(im_max - im_min) + im_min
resized_im = resized_im - mean
resized.append(tf.expand_dims(resized_im, 0))
return tf.concat(resized, 0)
Commentaire