ffmpeg に colorkey フィルタが取り込まれたことにより、クロマキー合成や特定色に個別のフィルタを当てられるようになった。

ffmpeg 2.7.1 以降で colorkey フィルタが使える。
avfilter/vf_colorkey: Add colorkey video filter

colorkey は指定した色の部分をアルファチャンネルにして、それ以外を RGB の BGRA で出力する。指定する色は16進数の rrggbb 形式か、色名を指定する。入力映像が RGB の方が YUV よりも処理が早い。

YUVA で処理する chromakey フィルタはこちら:ffmpeg でクロマキー合成 その2

16進数と色の説明:FFmpeg Utilities Documentation :: Color

基本コマンド

ffmpeg -i input -vf colorkey=red:0.01:0 output
ffmpeg -i input -vf colorkey=0xFF0000:0.01:0 output

公式ドキュメント:FFmpeg Filters Documentation : colorkey

オプション内容

フィルタが当たった部分のアルファチャンネルの値が小さくなり透過する。一方でフィルタが当たらなかった部分はマスクされ透過しない。

  • color[color]
    指定した色を透過させる。16進数形式か、色名を指定
    既定値:black
  • similarity[float]
    一致の範囲指定。0.01 は完全一致、1 は全画面。大きい値ほど透過範囲が広くなる
    既定値:0.01
    範囲:0.01 から 1 まで
  • blend[float]
    似た色の透過の影響具合、0 は指定した色だけで大きくするほど似た色も少しずつ透過する。つまり透過のグラデーションがきれいになる
    既定値:0
    範囲:0 から 1 まで

blend, similarity について

  • 基本画像(赤の右端が少し透過して欠けている)
    colorkey=red

    ffmpeg -f lavfi -i rgbtestsrc -vf colorkey=red -vframes 1 rgbtestsrc.png

  • colorkey=red:0.01:0.1

    ffmpeg -f lavfi -i rgbtestsrc -vf colorkey=red:0.01:0.1 -vframes 1 rgbtestsrc00101.png

  • colorkey=red:0.01:0.5

    ffmpeg -f lavfi -i rgbtestsrc -vf colorkey=red:0.01:0.5 -vframes 1 rgbtestsrc00105.png

  • colorkey=red:0.01:1

    ffmpeg -f lavfi -i rgbtestsrc -vf colorkey=red:0.01:1 -vframes 1 rgbtestsrc00110.png

  • colorkey=red:0.1:0.1

    ffmpeg -f lavfi -i rgbtestsrc -vf colorkey=red:0.1:0.1 -vframes 1 rgbtestsrc0101.png

  • colorkey=red:0.5:0.1

    ffmpeg -f lavfi -i rgbtestsrc -vf colorkey=red:0.5:0.1 -vframes 1 rgbtestsrc0501.png

  • colorkey=red:1:0.1

    ffmpeg -f lavfi -i rgbtestsrc -vf colorkey=red:1:0.1 -vframes 1 rgbtestsrc1001.png

  • colorkey=red:1:1

    ffmpeg -f lavfi -i rgbtestsrc -vf colorkey=red:1:1 -vframes 1 rgbtestsrc1010.png

透過具合を調べる

アルファチャンネルを調べるにはそのチャンネルの暗さ具合を調べることで透過具合を調べられる。アルファチャンネルだけを調べるには2つの方法があり、extractplanes=a フィルタと alphaextract フィルタがある。どちらもアルファチャンネルをグレースケールで出力する。このとき白(255.255.255)が透過しない部分になる。暗さを調べるには YUV の Y の最小値を signalstats,metadata で調べられる。signalstats フィルタは RGB の値に対応していない。

ffmpeg -f lavfi -i smptebars=d=1 -vf colorkey=0x0000bf:0.01:0.1,alphaextract,signalstats,metadata=print:key=lavfi.signalstats.YMIN -vframes 1 test.png

各映像チャンネルを分離する extractplanes
YUV のデータを数値で表示する signalstats
メタデータをコンソールに表示する metadata, ametadata

基本的な使い方

ffmpeg -f lavfi -i smptebars -vframes 1 smptebars.png
上の色は左から

  • 190.190.190(0xbebebe)
  • 192.190.0(0xc0be00)
  • 0.190.189(0x00bebd)
  • 0.188.0(0x00bc00)(中央の緑)
  • 190.0.191(0xbe00bf)
  • 191.0.0(0xbf0000)
  • 0.0.191(0x0000bf)(青)

中央の色は左から

  • 0.0.191(0x0000bf)
  • 3.3.3(0x030303)
  • 190.0.191(0xbe00bf)
  • 3.3.3(0x030303)
  • 0.190.189(0x00bebd)
  • 3.3.3(0x030303)
  • 190.190.190(0xbebebe)

下の色は左から

  • 0.61.103(0x003d67)
  • 255.255.255(0xffffff)
  • 62.0.118(0x3e0076)
  • 0.0.0(0x000000)
  • 9.9.9(0x090909)
  • 0.0.0(0x000000)

となっている

10進数と16進数のどちらでも調べられる:SpotColor : Vector
各色の2桁目の値が何もない場合は 0 を代入する。

中央の緑(0x00bc00)が透過する

ffmpeg -i smptebars.png -vf colorkey=0x00bc00 smptebars_alpha.png

動画や画像にアルファチャンネルが付いている場合は先に付いているアルファチャンネルと、指定した色のアルファチャンネルを合成する方法をとる。

透過画像からさらに透過(0x0000bf)を追加する

ffmpeg -i smptebars_alpha.png -vf split[a][b];[a]colorkey=0x0000bf[a1];[b][a1]blend=all_mode=and smptebars_alpha2.png

一度に2カ所透過する

ffmpeg -f lavfi -i smptebars -vf split[a][b];[a]colorkey=0x00bc00[a1];[b]colorkey=0x0000bf[b1];[a1][b1]blend=all_mode=and -vframes 1 smptebars_alpha3.png

応用例

アルファチャンネルをグレースケールで取り出して、その部分だけ、いわゆるマスクををつけてフィルタを当てオーバーレイすることで指定した色に個別のフィルタを当てられる。特定の場所にフィルタを当てる例に、hqdn3d(ノイズ除去)フィルタ、unsharp, smartblur, sab(シャープ、ぼかし)フィルタ、gradfun(バンディング低減)フィルタなどが考えられる。

alphaextract フィルタは透過部分を黒にそうでないのは白のグレースケール出力に変換する。つまり、colorkey フィルタから alphaextract フィルタにつなげた場合の出力フォーマットにはアルファチャンネルは付かない。

alphamerge フィルタは2番目の入力のグレースケール(グレースケールでなければ変換される)の白黒具合に応じて1番目の入力を透過させる。透過具合については黒が透過し、白に近いほど透過しなくなり、出力は YUVA または ARGB、RGBA になる。アルファチャンネルを含む映像になるのでそれに対応したコーデックで出力しないとアルファチャンネルが消えてしまうのに注意。YUVA なら ffv1。RGBA なら utvideo で出力する。同じ機能のフィルタに mergeplanes フィルタがあるがこちらの方が負荷が少し軽い。

マスクする場合、白に近いほどフィルタが強く当たり、黒に近いほどフィルタが当たらない。つまり colorkey フィルタから alphaextract フィルタにつなげると、colorkey で指定した部分は黒くなる。この白黒をきれいに反転するには colorkey=white,alphaextract フィルタの代わりに curves=negative フィルタを使う。

注意点:overlay フィルタで RGB の画像出力するときは出力フォーマットで RGB 指定しないときれいに出力できない。(overlay=format=rgb)

以下のマスク(alphamerge)を使った処理方法はフォトショップなどの画像処理の手順を参考にするのがよい。

応用例:明るいところ、暗いところにフィルタを当てる

  • 中央の 00bc00 にノイズをのせる

    00bc00 にノイズをのせる

  • 中央の 00bc00 以外にノイズをのせる

    00bc00 以外にノイズをのせる

  • 指定した3カ所にノイズをのせる

    指定した3カ所にノイズをのせる

  • 中央のロゴ周りの緑色(0x003900)に smartblur フィルタを当てる
  • クロップして特定場所に効果がわかりやすいノイズをのせる
    256:148 が crop フィルタの座標指定。128:64 がクロップの範囲指定。
  • 動画の特定の色を透過させて別の動画をクロマキー合成する

動画出力

画像の場合は出力拡張子を .png にすればそのままアルファチャンネル付きで出力される。動画にする場合は選択肢が複数ある。ひとつは無圧縮、もう一つは可逆圧縮である。無圧縮の場合は解像度とフレーム数が大きければ大きいほど容量が莫大になる。可逆圧縮の場合はアルファチャンネルに対応したエンコーダを指定する。

  • バランス型の utvideo。速度と容量、デコード速度もバランスがよい。ニコニコモンズに投稿できない。
    ffmpeg -f lavfi -i smptebars -c:v utvideo smptebars.avi
  • 容量の大きい huffyuv。ニコニコモンズに投稿できる。
  • 画像なら APNG。エンコード速度はとても遅い。拡張子は .apng。出力した後に拡張子を .png に直せばニコニコモンズに投稿できる。-f apng をつければ .png でも出力できる

APNG をループ出力する

colorkey_opencl

opencl を使って colorkey_opencl フィルタを使う。

opencl が使えれば以下のコマンドを実行すると対応 CPU、または GPU が表示される。
ffmpeg -hide_banner -v verbose -init_hw_device opencl

出力コマンド例。

ポイントは opencl を使うデバイスを上の例では 0.0 から 1.1 から指定する。能力によって処理速度が大きく異なる。オプション指定は通常と同じ。

コマンド例。RGBA 入力なので前後にフォーマット変換を挟む。
ffmpeg -init_hw_device opencl=ocl:1.0 -filter_hw_device ocl -f lavfi -i rgbtestsrc -vf format=rgba,hwupload,colorkey_opencl=red:.01:.1,hwdownload,format=rgba -vframes 1 rgbtestsrc.png
ffmpeg -init_hw_device opencl=ocl:1.0 -filter_hw_device ocl -i input -vf format=rgba,hwupload,colorkey_opencl=red:.01:.1,hwdownload,format=rgba -vframes 1 rgbtestsrc.png

公式ドキュメント:FFmpeg Filters Documentation : colorkey_opencl

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)