学会に参加してるのですが、昼休みが長すぎたので実験しました。CPUでも待ち時間で計算できたことに少し驚き。 最適化の箇所を 2/17 に追記する予定。
Neural Style Transfer
の二番煎じですが、tensorflowで実装。 使用した画像はpixabeyの商用可能画像です。
を含めたくさんの実装が公開されてます。
VGGネット
訓練済みモデルのダウンロード
neural style transferでは訓練済みの画像分類モデルVGG-19を用いるので、それを定義する。 モデルの重みは Matconvnetのこちらから取得できる。
モデルの定義
画像に直接加える前処理(中間画像を引く、など)は preprocess
内に全て記述する。
訓練をする際にある損失関数を計算する箇所は後ほど登場。
class vgg: # init def __init__(self): self.name = "default" self.vgg_path = "vgg19.mat" self.mean_pixel = None # [R, G, B] self.SKIP_PREPROCESS = False print("[vgg]init") # network def build(self): # layer name self.layers = ( 'conv1_1', 'relu1_1', 'conv1_2', 'relu1_2', 'pool1', 'conv2_1', 'relu2_1', 'conv2_2', 'relu2_2', 'pool2', 'conv3_1', 'relu3_1', 'conv3_2', 'relu3_2', 'conv3_3', 'relu3_3', 'conv3_4', 'relu3_4', 'pool3', 'conv4_1', 'relu4_1', 'conv4_2', 'relu4_2', 'conv4_3', 'relu4_3', 'conv4_4', 'relu4_4', 'pool4', 'conv5_1', 'relu5_1', 'conv5_2', 'relu5_2', 'conv5_3', 'relu5_3', 'conv5_4', 'relu5_4' ) # load weight data = scipy.io.loadmat(self.vgg_path) mean = data['normalization'][0][0][0] self.mean_pixel = np.mean(mean, axis=(0, 1)) self.weights = data['layers'][0] print("[vgg]build") def conv_layer(self, input, weights, bias): conv = tf.nn.conv2d(input,\ tf.constant(weights),\ strides=(1, 1, 1, 1),\ padding='SAME') return tf.nn.bias_add(conv, bias) def pool_layer(self, input): return tf.nn.max_pool(input,\ ksize=(1, 2, 2, 1),\ strides=(1, 2, 2, 1),\ padding='SAME') # eval ## 画像をモデルに入力 def process_img(self, input_image): net = {} current = input_image for i, name in enumerate(self.layers): kind = name[:4] if kind == 'conv': kernels, bias = self.weights[i][0][0][0][0] kernels = np.transpose(kernels, (1, 0, 2, 3)) bias = bias.reshape(-1) current = self.conv_layer(current, kernels, bias) elif kind == 'relu': current = tf.nn.relu(current) elif kind == 'pool': current = self.pool_layer(current) net[name] = current assert len(net) == len(self.layers) return net # preprocess ## 中間画像を足す or 引く def _add_mean(self, image, sign=-1): return image + sign*self.mean_pixel def preprocess(self, image): if not self.SKIP_PREPROCESS: image = self._add_mean(image, sign=-1) return image def unprocess(self, image): image = self._add_mean(image, sign=1) return image
モデルを宣言
model = vgg() model.build()
中間層での画像特徴量の抽出
ローカルで実験しているので tf.device('/cpu:0')
としていますが、GPUデバイスを認識できる環境ならばこの箇所を tf.device('/gpu:k')
などと適当に変更する必要があります。
input_img = cv2.imread("sample.jpg") content_image = raw_content.astype(np.float) content_shape = (1,) + content_image.shape # (h, w, nch) => (1, h, w, nch) with tf.Graph().as_default(), tf.Session() as sess, tf.device('/cpu:0'): image = tf.placeholder('float', shape=content_shape) nets = model.process_img(image) img_prep = np.array([model.preprocess(content_image)]) img_feat = nets['relu2_2'].eval(feed_dict={image: img_prep})
プロット用の関数
plot_data
, plot_title
にリスト形式でプロットしたいデータを渡し、pltmethod
でプロットする手法を指定。一度に5~10このグラフを出力することが何回もあるので、毎回これを使用する。
# plot image data def plot_image(plot_data, plot_title, size=(10,10,3,3), pltmethod=plt.imshow): plt.figure(figsize=(size[0], size[1])) for i in range(len(plot_data)): plt.subplot(size[2],size[3],i+1) pltmethod(plot_data[i]) if len(plot_title) == len(plot_data): plt.title(plot_title[i]) plt.tight_layout() plt.show()
中間層の画像の可視化
抽出した画像をプロットしてみる。 グレースケールにした方が良かった…?
plot_data = [input_img]+[img_feat[0, :, :, i] for i in range(5)] plot_title = ["original_img"]+["%d-layer" % (i) for i in range(5)] plot_image(plot_data, plot_title, size=(10,10,3,3))
最適化問題
元論文を参考にしながら「コンテンツロス」+「スタイルロス」の和が最小になるようにモデルを訓練する。
損失関数の計算
はじめに、このモデルの基となった同著者のモデルの損失の計算(の概略)が以下。
+後ほど詳細追記予定。
出力結果
後ほど追記予定。
画風変換に関する論文一覧
ほぼ時系列順、専門ではないので見落としたくさんあると思います。
- Texture Synthesis Using Convolutional Neural Networks
- A Neural Algorithm of Artistic Style
- Visualizing and Understanding Deep Texture Representations
- Compact Bilinear Pooling
- From A to Z: Supervised Transfer of Style and Content Using Deep Neural Network Generators
- Texture Networks: Feed-forward Synthesis of Textures and Stylized Images
- Generative Image Modeling using Style and Structure Adversarial Networks
- Perceptual Losses for Real-Time Style Transfer and Super-Resolution
- Precomputed Real-Time Texture Synthesis with Markovian Generative Adversarial Networks
- Improving the Neural Algorithm of Artistic Style
- A Powerful Generative Model Using Random Weights for the Deep Image Representation
- Preserving Color in Neural Artistic Style Transfer