1.はじめに
今回は、今となっては懐かしい2015年にgoogleが発表した、画像を悪夢の様に変換する「Deep Dream」という技術をご紹介します。
2.DeepDreamとは?
画像識別用のCNNに、ImageNet の様な膨大な自然画像を学習させると、CNNの各フィルターは様々な動物の要素を高次元の特徴量として学習します。
DeepDreamは、各フィルターが学習した特徴量をわざと可視化して、入力画像と合成することで、悪夢の様な画像が生成する技術です。
今回は、静止画をDeepDream変換するだけでなく、動画をDeepDream変換することをやってみようと思います。
3.コード
コードはGoogle Colabで動かす形にしてGithubに上げてありますので、それに沿って説明して行きます。自分で動かしてみたい方は、この「リンク」をクリックし表示されたノートブックの先頭にある「Colab on Web」ボタンをクリックすると動かせます。
最初に、セットアップとして、ライブラリーの読み込みやクラスと関数の定義を行います。(コードは省略します)
サンプルデータをダウンロードします。
1 |
!git clone https://github.com/cedro3/Sample.git |
モデルの作成を行います。
1 2 3 4 5 6 7 8 9 10 11 12 |
# ベースモデル InceptionV3 のダウンロード base_model = tf.keras.applications.InceptionV3(include_top=False, weights='imagenet') # Maximize the activations of these layers names = ['mixed3', 'mixed5'] layers = [base_model.get_layer(name).output for name in names] # Create the feature extraction model dream_model = tf.keras.Model(inputs=base_model.input, outputs=layers) # make model deepdream = DeepDream(dream_model) |
まず、静止画をDeepDream変換してみましょう。使用する静止画は、./Sample/animal_pic/dog.png で指定しています。自分の画像をDeepDream変換する場合は、この指定を変更して下さい。
1 2 3 4 5 |
# 静止画をDeepDreamに変換(octave) original_img = input('./Sample/animal_pic/dog.png') img = octave(original_img) show(original_img) show(img) |
上がオリジナルの静止画、下がDeepDream変換をした静止画です。かわいいワンちゃんの体や背景の至る所に目や鼻などの要素が造形され、結構怖くなります(笑)。
それでは、動画にDeepDream変換を掛けてみましょう。
まず、動画を静止画に切り出します。使用する動画は、./Sample/video/elephant.mp4 で指定しています。自分の動画を使う場合は、この指定を変更して下さい。
動画のフレームレートは30fpsで、6フレーム毎に切り出した静止画を images フォルダーへ保管する設定です。
images フォルダーが既にある場合(2回目以降)は、既にある images フォルダーを中身も含めて削除してから、新たにimagesフォルダーを作成して実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# ビデオを静止画に変換 import os import shutil import cv2 # 既にimagesフォルダーがあれば削除 if os.path.isdir('images'): shutil.rmtree('images') os.makedirs('images', exist_ok=True) def video_2_images(video_file= './Sample/video/elephant.mp4', # ビデオの指定 image_dir='./images/', image_file='%s.png'): # Initial setting i = 0 interval = 6 length = 300 # 最大フレーム数 cap = cv2.VideoCapture(video_file) while(cap.isOpened()): flag, frame = cap.read() if flag == False: break if i == length*interval: break if i % interval == 0: cv2.imwrite(image_dir+image_file % str(int(i/interval)).zfill(6), frame) i += 1 cap.release() def main(): video_2_images() if __name__ == '__main__': main() |
完了すると、動画が静止画(***.png)にバラされて、imagesフォルダーに保管されます。
次に、images フォルダーからバラされた静止画を1枚づつ読み込み、DeepDream変換を掛け、同じファイル名で上書きします。
1 2 3 4 5 6 7 8 9 10 11 12 |
# 静止画をDeepDream画像へ変換(octave) import glob from tqdm import tqdm files=[] for name in sorted(glob.glob('./images/*.png')): files.append(name) for file in tqdm(files): original_img=input(file) dream_img = octave(original_img) PIL.Image.fromarray(np.array(dream_img)).save(file) |
完了すると、images フォルダーの中の静止画が全てDeepDream変換を掛けた静止画に変わっています。
DeepDream変換を掛けた静止画からmp4動画を作成します。-r の後の「6」が作成するmp4のフレームレートです。作成したmp4は output.mp4 というファイル名で保存されます。このコードを2回目以降に動かす場合は、上書きするかどうか[y/N]を聞いて来ますので、[y]を入力します。
1 2 |
# DeepDream画像をmp4に変換 !ffmpeg -r 6 -i images/%06d.png -vcodec libx264 -pix_fmt yuv420p output.mp4 |
1 2 3 4 5 6 7 8 9 10 |
# mp4動画の再生 from IPython.display import HTML from base64 import b64encode mp4 = open('./output.mp4', 'rb').read() data_url = 'data:video/mp4;base64,' + b64encode(mp4).decode() HTML(f""" <video width="80%" height="80%" controls> <source src="{data_url}" type="video/mp4"> </video>""") |
今までのDeepDream変換は、Octaveという大きな変換ですが、Simpleという小さな変換(変換速度が早い)があり、Google Colabノートブックの後半に載せてありますので、これも試してみて下さい。
では、また。
(Twitterへの投稿)Simple変換したものです。