対象読者
日向坂46 「ひなリハ」~青春の馬~(4K)
のような背景が固定の動画から、以下のような背景画像を抽出したい人向けです。
1. 背景の抽出
いくつか調べましたが、ImageMagick での抽出を行っています。
1.1. ImageMagick を使う方法
「Creating image masks from video file」を参考にしました。
ffmpeg -i input.mp4 -r 1 -f image2 org-%05d.png
まず動画から連番画像を抽出します。画像が足りない際は -r 1
を増やして適宜準備します。その後、
for file_name in `ls -1 org-*.png | shuf`
do
if [ "${before_file_name}" != "" ]; then
convert \
\( \
${before_file_name} \
\( \
-clone 0 \
${file_name} \
-compose difference \
-composite \
-threshold 1% \
-negate \
\) \
-compose multiply \
-flatten \
\) \
background.png \
-background black \
-compose src-over \
-flatten \
-transparent black \
background.png
count=`expr ${count:-0} + 1`
cp background.png `printf background-%05d.png ${count}`
echo `date +%Y-%m-%d\ %H:%M:%S` ${count} ${before_file_name} done
fi
before_file_name=${file_name}
done
-compose difference
で差分がなかったところ = 背景として、重ね合わせて背景画像を作っていきます。
共通の程度は動画の内容によって変わってくるので -threshold
で調整した方が良い感じでした。
また、動画から抽出した画像を連番で比較した場合、共通部分が多くなり誤って背景判定されることが多くなるため、全体を shuf
してから前後の比較をするようにしています。
最終的に、compose の src-over で、抽出した背景を重ね合わせ background.png
にします。元記事では一括でやっていますが、ファイル数が多くなった際にメモリが足りなくなったため、逐次結合しています。
背景が写っている頻度が少ない箇所はゴミが残ってしまうので、-compose src-over
の代わりに -compose lighten
(明るいもので上書かれるので背景が明るい際に有用) や -compose darken
(背景が暗い際に有用) を使うとゴミが少なくできそうです。
1.2. OpenCV のサンプルを使う方法(のメモ)
docker run -v /c/Users/${USER}/Downloads:/Downloads -it --rm -e DISPLAY=host.docker.internal:0.0 opencvcourses/opencv-docker:4.4.0
上記で opencv/opencv の Docker を起動します。
git clone https://github.com/opencv/opencv
python opencv/samples/python/tutorial_code/video/background_subtraction/bg_sub.py --input /Downloads/input.mp4
コンテナ内で上記を実行することで、リポジトリにある bg_sub.py が実行できますが、出力の保存等は試していません。
1.3. BGSLibrary を使う方法(のメモ)
docker run -v /c/Users/${USER}/Downloads:/Downloads -it --rm -e DISPLAY=host.docker.internal:0.0 andrewssobral/bgslibrary:opencv_3.4.1py36 bash
上記で andrewssobral/bgslibrary の Docker を起動します。
cd /root/bgslibrary/
./build/bgslibrary -uf -fn=/Downloads/input.mp4
コンテナ内で上記を実行することで、コマンドが実行できますが、出力の保存等は試していません。
2. おまけ: 動画の背景を分離
上記の画像を使って PeterL1n/BackgroundMattingV2 の Video matting (Colab) などを使うと、背景をそこそこ分離できました。