Pythonでいろいろやってみる

Pythonを使った画像処理や機械学習などの簡単なプログラムを載せています。

動画をモノクロ映画っぽくする

 動画をモノクロ映画っぽくします。カラーの動画ファイルを読み出し各フレームをグレースケール変換して動画として保存します。画像処理ライブラリOpenCVで動画ファイルを読み出し、フレーム毎の画像をcv2.cvtColorでグレースケール変換しその画像をつなぎ合わせて動画にします。さらにコントラストを強調することでよりモノクロ映画っぽくします。

環境
  • windows10 home
  • Anaconda 3/ jupyter notebook 5.6.0
  • Python 3.8.8
  • Pillow 8.2.0
  • OpenCV 4.0.1
準備

 動画ファイルはMixkitの "Annoyed man yelling at his wife"をダウンロードし320x180にリサイズしたうえでjupyter notebookファイル(***.ipynb)と同じディレクトリにファイル名’yelling.mp4'で保存しました。このブログにはmp4ファイルが貼れないのでアニメーションgifファイルに変換したものを下に貼ります。

f:id:T_A_T:20220123183613g:plain
"yelling.mp4(アニメーションgifに変換したもの)"

コード

cv2.cvtColorにより各フレームをグレースケール変換しmp4動画として保存します。

from PIL import Image
import cv2

# gifファイル作成用イメージリスト
images =[]  

# 動画ファイル作成用イメージリスト
frames =[]  

# 動画ファイルのキャプチャー
cap = cv2.VideoCapture('yelling.mp4')

# フレームの幅取得
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)

# フレームの高さ取得
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)

# 総フレーム数取得
allframes = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

# 動画ファイルのフレームレート取得
fps = cap.get(cv2.CAP_PROP_FPS)

# 保存用動画ファイルのフォーマット設定
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') 
out = cv2.VideoWriter('monochrome.mp4', fourcc, fps, (int(width), int(height))) 

# 動画を1コマずつ取り込んで処理
while(cap.isOpened()): 
    ret, frame = cap.read() # キャプチャー画像の取り込み
    
    if ret==True: # キャプチャー画像がある場合
                
        # グレースケール変換
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        
        # BGR変換(動画ファイルとチャンネル数を合わせるため)
        bgr = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)

        # VideoWriterにフレームを追加
        out.write(bgr)

        # gifファイル作成用イメージリストにフレームを追加
        images.append(Image.fromarray(cv2.cvtColor(bgr, cv2.COLOR_BGR2RGB)))

    else: # キャプチャー画像がない場合はループ終了 
        break
        
cap.release() # 再生画像をクローズ   
out.release() # 出力動画ファイルをクローズ

# gif動画保存
images[0].save('monochrome.gif', save_all=True, append_images=images[1:], 
               optimize=False, duration=1000/fps, loop=0)  
実行結果

モノクロ変換された動画が保存されます。
f:id:T_A_T:20220123184209g:plain


コード

よりモノクロ映画っぽくするために画像のコントラストを強調します。cv2.equalizeHistでヒストグラム平坦化しコントラストを強調してからグレースケール変換します。

from PIL import Image
import cv2

# gifファイル作成用イメージリスト
images =[]  

# 動画ファイル作成用イメージリスト
frames =[]  

# 動画ファイルのキャプチャー
cap = cv2.VideoCapture('yelling.mp4')

# フレームの幅取得
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)

# フレームの高さ取得
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)

# 総フレーム数取得
allframes = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

# 動画ファイルのフレームレート取得
fps = cap.get(cv2.CAP_PROP_FPS)

# 保存用動画ファイルのフォーマット設定
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') 
out = cv2.VideoWriter('monochrome_eq.mp4', fourcc, fps, (int(width), int(height))) 

# 動画を1コマずつ取り込んで処理
while(cap.isOpened()): 
    ret, frame = cap.read() # キャプチャー画像の取り込み
    
    if ret==True: # キャプチャー画像がある場合
                
        # 色空間をBGR->HSVに変換
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)         
        
        # equalizeHistによるヒストグラム平坦化
        hsv[:, :, 2] = cv2.equalizeHist(hsv[:, :, 2])

        # HSV->BGR変換
        bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR) 
        
        # グレースケール変換
        gray = cv2.cvtColor(bgr, cv2.COLOR_BGR2GRAY)
        
        # BGR変換(動画ファイルとチャンネル数を合わせるため)
        bgr = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)
        
        # VideoWriterにフレームを追加
        out.write(bgr)

        # gifファイル作成用イメージリストにフレームを追加
        images.append(Image.fromarray(cv2.cvtColor(bgr, cv2.COLOR_BGR2RGB)))

    else: # キャプチャー画像がない場合はループ終了 
        break
        
cap.release() # 再生画像をクローズ   
out.release() # 出力動画ファイルをクローズ

# gif動画保存
images[0].save('monochrome_eq.gif', save_all=True, append_images=images[1:], 
               optimize=False, duration=1000/fps, loop=0)   
実行結果

コントラストが強調されより古い映画っぽくなります。
f:id:T_A_T:20220123184253g:plain

以下のサイトを参考にさせていただきました

Pythonの文法メモ > 【OpenCV】動画ファイルの読み出しとプロパティ取得、キャプチャー画像の保存
Pythonの文法メモ > 【OpenCV】ヒストグラム平坦化による画像コントラストの向上

ブログランキングに参加しています

にほんブログ村 IT技術ブログへ
にほんブログ村