1.はじめに
今回ご紹介するのは、以前よりも視覚的な不具合を防ぎ一貫性のあるスタイル転送を実現するPAMA(progressive attentional manifold alignment)という技術です。
*この論文は、2022.1に提出されました。
2.PAMAとは?
下記がネットワークの概略図です。3つの独立したアテンション・マニホールド・アラインメント(AMA)を使用して、3段階でコンテンツとスタイルを徐々に融合します。点線は、トレーニング時にのみ使用される損失計算の途中結果です。
下記がAMAで、左側のアテンション・モジュールでコンテンツFcとスタイルFsからアテンションマップAcsを作成し、右側の空間認識補間で重みWを取得しコンテンツとスタイルの補間に適用します。
さて、このスタイル転送でどんな変換ができるの例を見てみましょう。左からコンテンツ画像、スタイル画像、アウトプットです。
それでは、早速コードを動かしてみましょう。
3.コード
コードはGoogle Colabで動かす形にしてGithubに上げてありますので、それに沿って説明して行きます。自分で動かしてみたい方は、この「リンク」をクリックし表示されたノートブックの先頭にある「Colab on Web」ボタンをクリックすると動かせます。
まず、セットアップを行います。
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
#@title セットアップ %%capture # githubからコードをコピー ! git clone https://github.com/cedro3/PAMA.git %cd PAMA # 学習パラメータのダウンロード import gdown # original gdown.download('https://drive.google.com/uc?id=1rPB_qnelVVSad6CtadmhRFi0PMI_RKdy', 'original_PAMA.zip', quiet=False) ! unzip original_PAMA.zip # consistency gdown.download('https://drive.google.com/uc?id=1IrggOiutiZceJCrEb24cLnBjeA5I3N1D', 'PAMA_without_color.zip', quiet=False) ! unzip PAMA_without_color.zip # color gdown.download('https://drive.google.com/uc?id=1HXet2u_zk2QCVM_z5Llg2bcfvvndabtt', 'PAMA_1.5_color.zip', quiet=False) ! unzip PAMA_1.5_color.zip # content gdown.download('https://drive.google.com/uc?id=13m7Lb9xwfG_DVOesuG9PyxDHG4SwqlNt', 'PAMA_1.5_content.zip', quiet=False) ! unzip PAMA_1.5_content.zip import os import shutil # downloadフォルダ作成 os.makedirs('download', exist_ok=True) #学習済みパラメータの設定関数 def select_param(select): # checkpointsフォルダーリセット if os.path.isdir('checkpoints'): shutil.rmtree('checkpoints') if select == 'original': shutil.copytree('original_PAMA', 'checkpoints') if select == 'consistency': shutil.copytree('PAMA_without_color', 'checkpoints') shutil.copy('original_PAMA/encoder.pth', 'checkpoints/encoder.pth') if select == 'color': shutil.copytree('PAMA_1.5_color', 'checkpoints') shutil.copy('original_PAMA/encoder.pth', 'checkpoints/encoder.pth') if select == 'content': shutil.copytree('PAMA_1.5_content', 'checkpoints') shutil.copy('original_PAMA/encoder.pth', 'checkpoints/encoder.pth') print('checkpoint is '+select) # 画像連結関数 from PIL import Image def get_concat_h(im1, im2): dst = Image.new('RGB', (im1.width + im2.width, im1.height)) dst.paste(im1, (0, 0)) dst.paste(im2, (im1.width, 0)) return dst def edit_pic(file1, file2): f1 = Image.open(file1) f2 = Image.open(file2) f1_resize = f1.resize((f2.width, f2.height)) get_concat_h(f1_resize, f2).save('disp.jpg') |
まず、画像のスタイル転送をやってみましょう。checkpoint(学習済みパラメータ)を4種類の中から選択し、contentには元画像、styleにはスタイル画像を設定して下さい。ここでは、checkpoint = ‘consistency’, content = ’08.jpg’, style = ’16.jpg’ を設定しています。
自分で用意した画像を使用する場合は、元画像はcontentフォルダへ、スタイル画像はstyleフォルダへアップロードして下さい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#@title 画像のスタイル転送 # 設定 checkpoint = 'consistency' #@param ["original", "consistency", "color", "content"] {allow-input: true} content = '08.jpg'#@param {type:"string"} style = '16.jpg'#@param {type:"string"} # 学習済みパラメータの選択 select_param(checkpoint) # スタイル転送 ! python main.py eval --content content/$content --style style/$style # 変換前後の画像連結 edit_pic('content/'+content, 'ics.jpg') # 連結画像表示 from google.colab.patches import cv2_imshow import cv2 img_cv=cv2.imread('disp.jpg') cv2_imshow(img_cv) |
出来た画像をダウンロードします。
1 2 3 4 5 6 7 8 9 10 |
#@title 画像のダウンロード import os import shutil from google.colab import files content_name = os.path.splitext(content) style_name = os.path.splitext(style) file_name = 'download/'+content_name[0]+'_'+style_name[0]+'_'+checkpoint+'.jpg' shutil.copy('disp.jpg', file_name) files.download(file_name) |
もう1つ設定を変えてやってみましょう。今度は、checkpoint = ‘consistency’, content = ’14.jpg’, style = ’16.jpg’ の設定です。
次に、動画のスタイル変換をやってみましょう。checkpoint(学習済みパラメータ)を4種類の中から選択し、videoには元動画、styleにはスタイル画像を設定して下さい。ここでは、checkpoint = ‘consistency’, video = ’01.mpg’, style = ’16.jpg’ を設定しています。
自分で用意した動画や画像を使用する場合は、元動画はvideoフォルダへ、スタイル画像はstyleフォルダへアップロードして下さい。なお、動画は音声付きにして下さい。
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
#@title 動画のスタイル転送 #@markdown ・videoは音声付きとして下さい # 学習済みパラメータの選択 checkpoint = 'consistency' #@param ["original", "consistency", "color", "content"] {allow-input: true} select_param(checkpoint) # --- 動画を静止画にバラす --- video = '01.mp4' #@param {type:"string"} video_file = 'video/'+video import os import shutil import cv2 # flamesフォルダーリセット if os.path.isdir('images'): shutil.rmtree('images') os.makedirs('images', exist_ok=True) def video_2_images(video_file= video_file, # ビデオの指定 image_dir='images/', image_file='%s.jpg'): # Initial setting i = 0 interval = 1 length = 3000 # 最大フレーム数 cap = cv2.VideoCapture(video_file) fps = cap.get(cv2.CAP_PROP_FPS) # fps取得 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() return fps, i, interval fps, i, interval = video_2_images() #print('fps = ', fps) #print('flames = ', i) #print('interval = ', interval) # --- 動画のスタイル転送 --- # style_movieフォルダーリセット if os.path.isdir('style_movie'): shutil.rmtree('style_movie') os.makedirs('style_movie', exist_ok=True) # 指定したstyleをstyle_movieフォルダへコピー import shutil style = '16.jpg'#@param {type:"string"} shutil.copy('style/'+style, 'style_movie/'+style) # icsフォルダーリセット if os.path.isdir('ics'): shutil.rmtree('ics') os.makedirs('ics', exist_ok=True) # 静止画をスタイル転送 ! python main.py eval --run_folder True --content images/ --style style_movie/ # 静止画から動画の作成 print('making movie...') fps_n = fps/interval !ffmpeg -y -r $fps_n -i ics/%06d.jpg -vcodec libx264 -pix_fmt yuv420p -loglevel error out.mp4 # 音声の抽出&付加 print('preparation for sound...') ! ffmpeg -y -i $video_file -loglevel error sound.mp3 ! ffmpeg -y -i out.mp4 -i sound.mp3 -loglevel error output.mp4 |
1 2 3 4 5 6 7 8 9 10 |
#@title 動画の再生 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="70%" height="70%" controls> <source src="{data_url}" type="video/mp4"> </video>""") |
意外なスタイル画像が面白い転送結果を出すことがお分かり頂けたかと思います。ぜひ、色々試してみて下さい。
では、また。
(オリジナルgithub)https://github.com/computer-vision2022/PAMA
(twitter投稿)
コメントを残す