はじめに
私事ですが、友人がYoutubeに動画投稿をしており、度々グリーンバックの動画と背景画像を送り付けてきて、「編集お願い!」と言ってきます。
まあまあな頻度なので勉強もかねてプログラムにしてみようと思いました。
内容が気になる方はリポジトリを下に載せておくので覗いてみてください。
Python + poetryの環境で開発を行ったので、git cloneしてきてpoetry install
を実行すればプログラムを動かせるはずです。
主な処理
def create_frame(input_frame):
# コントラスト調整
contrast_image = cv2.convertScaleAbs(input_frame, alpha=contrast_adjustment_value, beta=0)
# クロマキー処理と二値化
hsv_chroma_key_color = cv2.cvtColor(chroma_key_color, cv2.COLOR_BGR2HSV)
lower_green = np.array([hsv_chroma_key_color[0][0][0] - chroma_key_threshold, 50, 50])
upper_green = np.array([hsv_chroma_key_color[0][0][0] + chroma_key_threshold, 255, 255])
hsv_image = cv2.cvtColor(contrast_image, cv2.COLOR_BGR2HSV)
chroma_key_image = cv2.inRange(hsv_image, lower_green, upper_green)
mask_image = cv2.bitwise_not(chroma_key_image)
# ノイズ除去
transparent_image = cv2.cvtColor(input_frame, cv2.COLOR_BGR2BGRA) # RGBA形式に変換
transparent_image[:, :, 3] = mask_image # アルファチャンネルにマスク画像を設定
# 背景画像に重ねる
foreground = transparent_image[:, :, :3]
alpha = transparent_image[:, :, 3:] / 255.0
background = back.copy()
output_frame = cv2.convertScaleAbs(background * (1 - alpha) + foreground * alpha)
return output_frame
このプログラムの主となる、画像処理部分が上にあるコードです。
動画を1フレームずつ取ってきて、画像処理しています。
まず最初にコントラストを調整します。
画像処理は専門外なので、理由はよくわかっていませんが画像処理の精度をよくするためらしいです。
次に指定した色の箇所を白に、それ以外の箇所を黒にする二値化処理を行っています。
lower_greenやupper_greenは透過する色の閾値を決めています。
mask_image
が二値化処理が済んだ画像になります。
次にtransparnet_image
=透過画像を作成します。BGR形式からアルファチャンネルを含むBGRA形式に変換して、アルファチャンネルにmask_imageを設定します。
これで、指定した色の箇所が透過されます。
最後に背景画像と合成して終了です。
ほとんどOpenCVが関数を用意してくれているので、そんなに時間をかけずにコードを書くことができました。
サンプル
やや縁が残っていますが、友人はこれくらいなら許容してくれます。
リポジトリ
実行速度が遅いので、できるならば速くしたいと思っています。
良い方法があれば、プルリクやコメントしていただけると嬉しいです。