Python + Opencvでアニメをラフ画のような線画に変換する
/
Python + Opencvでアニメをラフ画のような線画への変換を実施します.
今回はGoogle ColabとGoogle Driveを連携させて,notebook形式で実行してます.
Google Colaboratory(以下Google Colab)は、Google社が無料で提供している機械学習の教育や研究用の開発環境です。開発環境はJupyter Notebookに似たインターフェースを持ち、Pythonの主要なライブラリがプリインストールされています。
引用元:Google Colabの使い方 (opens new window)
全国630店舗以上!もみほぐし・足つぼ・ハンドリフレ・クイックヘッドのリラクゼーション店【りらくる】
# Google Colabのファイル構成
プロジェクトディレクトリはpdf_translate_bertとしています.度々,省略しています.
lineart
├── /pdf_translate_bert
└── lineart.ipynb <- 実行用ノートブック
# Google Driveと連携
Google ColabとGoogle Driveを連携させて,作業ディレクトリを作成します.
# Google Driveと連携
from google.colab import drive
drive.mount('/content/drive')
# 作業ディレクトリの作成
%cd /content/drive/MyDrive/
!mkdir -p lineart
%cd lineart
!ls
# モジュールのインストール
下記のコマンドでモジュールをインストールします.
# ffmpeg
!apt-get install ffmpeg
# pip
!pip install pydub
# 線画への変換を実行
変換は下記の工程で実行します.
音声ファイル(mp3)の作成
フレーム数の設定
線画動画の出力(音声なし)
線画動画と音声ファイルの結合
import os
import cv2
import numpy as np
import subprocess
from pydub import AudioSegment
# 音声ファイル(mp3)の作成
下記のコードで音声ファイル(mp3)を作成します.
# 入力動画
mp4_file = 'jujutsukaisen_op.mp4'
# mp3の変換
mp3_file = mp4_file.replace('.mp4', '.mp3')
cp = subprocess.run(['ffmpeg', '-y', '-i', mp4_file, '-acodec', 'libmp3lame', '-ab', '256k', mp3_file])
# 音声ファイルの読み込み
sound = AudioSegment.from_file(mp3_file, "mp3")
time = sound.duration_seconds # 再生時間(秒)
print(time)
# フレーム数の設定
下記のコードで動画のフレーム数の設定します.
# 動画の読み込み
vid = cv2.VideoCapture(mp4_file)
# 動画情報の抽出(fps)
for vid_fps in range(20,32):
video_frame_count = vid.get(cv2.CAP_PROP_FRAME_COUNT) # フレーム数を取得する
video_len_sec = video_frame_count / vid_fps # 長さ(秒)を計算する
# 誤差1秒以内
if 1 > abs(time-video_len_sec):
break
print(vid_fps, abs(time-video_len_sec))
# 線画動画の出力(音声なし)
下記のコードで線画動画の出力します.(音声なし)
# 出力動画の設定
sub_file = mp4_file.replace('.mp4','_sub.mp4')
codec = cv2.VideoWriter_fourcc(*'XVID')
vid_width,vid_height= int(vid.get(cv2.CAP_PROP_FRAME_WIDTH)), int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT))
out = cv2.VideoWriter(sub_file, codec, vid_fps, (vid_width,vid_height))
# 近傍(線画)の設定
# 線画の設定は下記の数値を変更して,調整してください.
n = 5
neiborhood24 = np.ones((n, n), np.uint8)
while True:
_, frame = vid.read()
if frame is None:
print('Completed')
break
# 線画化
# グレースケールで画像を読み込む
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 白い部分を膨張させる.
dilated = cv2.dilate(gray, neiborhood24, iterations=1)
# 差をとる.
diff = cv2.absdiff(dilated, gray)
# 白黒反転
contour = 255 - diff
# 出力
out.write(cv2.cvtColor(contour, cv2.COLOR_BGR2RGB))
if cv2.waitKey(1) == ord('q'):
break
vid.release()
out.release()
# 線画動画と音声ファイルの結合
下記のコードで線画動画と音声ファイルを結合します.
# 映像/音声の結合
cp = subprocess.run(['ffmpeg', '-y', '-i', sub_file, '-i', mp3_file, '-c:v', 'copy', '-c:a', 'aac', '-map', '0:v:0', '-map', '1:a:0', mp4_file.replace('.mp4','_cv2.mp4')])
# ファイル削除
os.remove(sub_file)
os.remove(mp3_file)
変換結果
# まとめ
本稿では,上記のコードでアニメの線画化を実装しました.