fieldmatch
フィルタで逆テレシネしてプログレッシブフレームを作り、プログレッシブ化に漏れたフレームを改めてインターレース解除フィルタでプログレッシブ化しdecimate
フィルタで間引けば24p化することができる。テレシネではなくインターレースのときは逆テレシネしないので、あとのインターレース解除フィルタでプログレッシブ化できる。ポストプロセスppsrcでノイズ除去、または明るさ、コントラストの調整することでオリジナルフィールドを劣化させず逆テレシネすることもできる。逆テレシネして24pまたは25pの映像には効果的だが、30p(縞なし)、60p(毎フレーム縞)が大半を占めるときは通常のインターレース解除フィルタのほうがよい。
- ffmpeg でインターレース解除
- 単純な逆テレシネフィルタdetelecine
- 高速で万能な逆テレシネフィルタ pullup
- フレームがインターレースかどうかを調べる idet
- vmaf スコアをインターレース解除とデノイズのフィルタを使って調べてみた
基本コマンド
アニメのインターレース解除漏れにはestdif
フィルタがよさそうに感じた。次点はyadif
フィルタ。
ffmpeg -i input -vf fieldmatch,estdif=0:0:1,decimate -c:a copy output
ffplay -i input -vf fieldmatch,estdif=0:0:1,decimate
cthreshを上げたほうが逆テレシネのフレームが増える。
ffmpeg -i input -vf fieldmatch=cthresh=40,estdif=0:0:1,decimate -c:a copy output
ffplay -i input -vf fieldmatch=cthresh=40,estdif=0:0:1,decimate
映像上部にあるロゴを判定区画から外す。適宜ロゴサイズに合わせて調整する。
ffmpeg -i input -vf fieldmatch=y0=0:y1=50:cthresh=40,estdif=0:0:1,decimate -c:a copy output
ffplay -i input -vf fieldmatch=y0=0:y1=50:cthresh=40,estdif=0:0:1,decimate
フィールド判定がうまくいってないときはsetfield
フィルタで指定する。
ffmpeg -i input -vf setfield=tff,fieldmatch=tff:cthresh=40,estdif=0:0:1,decimate -c:a copy output
ffplay -i input -vf setfield=tff,fieldmatch=tff:cthresh=40,estdif=0:0:1,decimate
デバグ方法はcombdbgを指定しほかのパラメータを変えながら挙動の変化を確認する。
ffmpeg -report -i input -vf setfield=tff,fieldmatch=tff:combmatch=full:combdbg=1:cthresh=9:combpel=80 -an -f null - > nul 2>&1
先にFFREPORTでファイル名とデバグレベルを指定するとログのファイル名を指定できる。
set FFREPORT=file=foo.log:level=48
カンマ区切りに整形したログ。
grep SC: foo.log | grep -oP "COMBS:\s+\K.*" | sed "s/ \+/,/g" > fieldmatch_combdbg_log.csv
ppsrcを有効にしてil
フィルタでフィールド分離して縦に並べてbilateral
フィルタでデノイズしてil
フィルタで元の映像に戻す例。
ffmpeg -report -i input -vf setparams=tff,split[1],il=l=d:c=d,bilateral,il=l=i:c=i[0];[0][1]fieldmatch=tff:ppsrc=1:combmatch=sc:cthresh=8:combdbg=1 -an -f null - > nul 2>&1
ピクチャーをインターリーブ、デインターリーブするil
エッジ保持のスムースフィルタ bilateral
bilateral
フィルタの代わりにlutyuv
フィルタで少し明るくする。
ffmpeg -report -i input -vf setparams=tff,split[1],lutyuv=y=gammaval(1/1.1)[0];[0][1]fieldmatch=tff:ppsrc=1:combmatch=sc:cthresh=8:combdbg=1 -an -f null - > nul 2>&1
Windows の ffmpeg で生放送する方法 : LUT(ルックアップテーブル、ラット)
入力にテレシネの30iとプログレッシブの24pが混在したVFRのときはdejudder
フィルタとfps
フィルタで大きいフレームレートで固定したCFRにする。テレシネの30iでOPEDなどが60iになる片フィールド補間が必要な映像はdecimate
フィルタで間引かない。
ffmpeg -i input -vf dejudder,fps=30000/1001,fieldmatch,decimate -c:a copy output
ffplay -i input -vf dejudder,fps=30000/1001,fieldmatch,decimate
テレシネにテロップなどの60iが混在しているときはfieldmatch
フィルタでは解除漏れするのでインターレース解除フィルタを併用し、解除するフィールド指定をインターレースだけにする。
ffmpeg -i input -vf dejudder,fps=30000/1001,fieldmatch=combmatch=full,estdif=0:-1:1 -c:a copy output
さらに昔のノイタミナの冒頭にあった30pと本編テレシネとテロップの60iも揃うとインターレース解除フィルタで30pの部分がボケるので、30pの部分をインターレース解除フィルタから退避するなどしてボケないようにさせる。
ffmpeg -i input -filter_complex "split[1v],trim=start_frame=0:end_frame=120,fieldmatch=combmatch=full,setpts=PTS-STARTPTS[0v];[1v]trim=start_frame=120,fieldmatch=combmatch=full,estdif=0:-1:1,setpts=PTS-STARTPTS[1v];[0v][1v]concat=n=2:v=1:a=0" -c:a aac output
ただし上の方法だと冒頭の30pのフレームレートが少しおかしくなるので、正確さを求めるなら区間ごとにrawファイルの.264や.265などで出力してconcatする。
ffmpeg -i input -filter_complex "split[1v],trim=start_frame=0:end_frame=120,fieldmatch=combmatch=full,setpts=PTS-STARTPTS[0v];[1v]trim=start_frame=120,fieldmatch=combmatch=full,estdif=0:-1:1,setpts=PTS-STARTPTS[1v]" -map [0v] output1.264 -map [1v] output2.264
高ビット深度のテレシネコンテンツにはppsrc=1を使えばビット深度を保持できる。使わないと8ビット深度に落ちる。
ffmpeg -i input -vf setparams=tff,split,fieldmatch=tff:ppsrc=1,estdif=0:0:1,decimate -c:a copy output
ffplay -i input -vf setparams=tff,split,fieldmatch=tff:ppsrc=1,estdif=0:0:1,decimate
公式ドキュメント:FFmpeg Filters Documentation : fieldmatch
オプション
- order[int]
想定されるフィールドオーダーの指定 - -1, auto:自動検出。ffmpegの処理と同じ。既定値
- 0, bff
- 1, tff
- mode[int]
フィールドマッチ方法の指定。下にいくほど処理が遅くなる。orderで指定したフィールドを元に対のフィールドをp:過去、c:現在、p:未来のフィールドを移動したのがこのグラフ。u/bはよくわからない - 0, pc
- 1, pc_n:既定値
- 2, pc_u
- 3, pc_n_ub
- 4, pcn
- 5, pcn_ub
- ppsrc[boolean]
2入力して1入力目をポストプロセスでフィルタを当ててフィールドマッチに役立てる。フィルタはデノイズや明るさ調整が考えられる。出力フレームには1入力目のフィルタの影響はない
既定値:0 - field[int]
照合するフィールドの指定。通常はorderと同じ設定にする - -1, auto:orderと同じ。既定値
- 0, bottom
- 1, top
- mchroma[boolean]
フィールドマッチに彩度を考慮する。通常は有効にするが、大きな虹やその他アーティファクトなど、映像によくない彩度の問題があるときに無効にする。無効にすると処理速度が上がる
既定値:1 - y0[int]
既定値:0 - y1[int]
それぞれの値を含むy0とy1の間をフィールドマッチの決定から除外する縦幅の指定。y0はスキャン開始座標、y1はスキャン終了座標を設定する。字幕、ロゴ、黒枠などマッチの邪魔になるものが映像にあるときに指定する。y0、y1を同じ値にすると効果が無効になる
既定値:0 - scthresh[double]
シーンチェンジで使う輝度変化の最大の割合値。適切な値は8から14でcombmatch=scのときだけに効果がある
既定値:12
範囲:0から100まで - combmatch[int]
インターレース櫛がないときに最終的にどの方法で櫛の程度を決めるか - 0, none:しない
- 1, sc:シーンチェンジ。既定値
- 2, full:全部。シーンチェンジ以外でフィールドタイプが変わる60iクレジットやテロップの区間を調べるときに使う
- combdbg[int]
計算した櫛のスコアをコンソールに流す。match=0はフィールドマッチしていなく、match=1はフィールドマッチしている。一般的なテレシネでは映像が継続的に動いて櫛が見えるとmatchが11001を繰り返す。途中から見れば1が3連続、0が2連続になる。映像が動いてなければフィールドがマッチしないフレームは1になりやすい。combpelで指定した値が、例えば以下の最初の3つの数値以上でcombed=YESになる。62が80より小さいのでcombed=NOになる。combed=YESのときにコンソールのログに「is still interlaced」が表示される
例:COMBS: 256 62 256 -1 -1 (combpel=80) match=1 combed=NO - 0, none:ログは非表示。既定値
- 1, pcn:mode=pc_nに強制してログを表示する
- 2, pcnub:mode=pcn_ubに強制してログを表示する
- cthresh[int]
櫛検出の閾値。大きな値では大きく見える櫛を検出し、小さな値では見えにくい櫛を検出する。-1はすべてのピクセルに櫛があると検出し、255は逆に櫛が検出されない。この値はピクセルの差分値である。小さな値はフィールドマッチ漏れしやすくなる
既定値:9
範囲:-1から255まで - chroma[boolean]
櫛フレーム検出に彩度を考慮する。大きな虹やその他アーティファクトなど、映像によくない彩度の問題がありchromaを有効にして櫛フレーム検出に問題があるときは無効にする。しかし実際は彩度だけに櫛が残る場合を除いて無効にしたほうが信頼性が高い
既定値:0 - blockx[int]
combpelで櫛フレーム検出に使われる領域の横幅の指定。2のべき乗である任意の値を指定する
既定値:16
範囲:4から512まで - blocky[int]
combpelで櫛フレーム検出に使われる領域の縦幅の指定。2のべき乗である任意の値を指定する。縦スクロールのクレジット検出にこの値を上げると検出しやすくなる
既定値:16
範囲:4から512まで - combpel[int]
櫛状態のピクセルがblockxとblocky内にどれだけ含まれていたら櫛状態と判定する閾値。blockxとblockyの乗算以下でなければならない
既定値:80
範囲:0からINT_MAXまで
テレシネ以外の映像を検出するには
- テレシネ以外の映像の検出にはcombmatch=fullを追加する。
- テレシネに30pが混在するとmatch=1、combed=YESが連続する。
- テレシネに下テロップやクレジットなどの60iが混在してもmatch=1、combed=YESが連続する。
- cthreshを上げすぎるとテレシネ以外の映像が検出しにくくなる。