ffmpeg 3.2 でリリース予定のビデオフィルタ。ffmpeg のフィルタの中でかなり処理が重たい部類に入るエッジ保護のデノイザ nlmeans
フィルタの使い方。なぜこれほどまでに重たいかというとデノイズする部分を映像内容によって異なる処理をするために重たくなるから。詳しい処理内容は「non-local means filter」で検索する。
処理内容の紹介記事
Non-local Means Filterによるデノイジング | OpenCV.jp
Non-local Means Filterの実装 – Qiita
該当ソースコード:FFmpeg/vf_nlmeans.c at master · FFmpeg/FFmpeg
公式ドキュメント:FFmpeg Filters Documentation : nlmeans
基本コマンド
ffplay でスムーズに再生するにはハイスペックの CPU が必要
ffmpeg -i input -vf nlmeans=s=1:p=7:pc=0:r=15:rc=0 output
ffmpeg -i input -vf nlmeans=1:7:0:15:0 output
オプション
- s[double]
デノイズ強度の指定。大きい値ほど強くデノイズする
既定値:1
範囲:1 から 30 まで - p[int]
輝度(Y)のパッチサイズの指定。r よりも小さい値を指定する
大きな値ほど輝度のデノイズ効果は小さくなりサイズが増える。さらに輝度だけではなく彩度もデノイズ効果が小さくなる
0, 1 は無効、3以上から有効。奇数を指定する。偶数は1加算される
既定値:7
範囲:0 から 99 まで - pc[int]
彩度(UV)のパッチサイズの指定
0 は自動設定。1 は無効、3以上から有効。奇数を指定する。偶数は1加算される
既定値:0
範囲:0 から 99 まで - r[int]
輝度(Y)の探索サイズの指定。大きい値ほど負荷が重たくなる
0, 1 は無効、3以上から有効。奇数を指定する。偶数は1加算される
既定値:15
範囲:0 から 99 まで - rc[int]
彩度(UV)の探索サイズの指定。大きい値ほど負荷が重たくなる
0 は自動設定。1 は無効、3以上から有効。奇数を指定する。偶数は1加算される
既定値:0
範囲:0 から 99 まで
配信用の設定
ニコ生で使う場合の設定は重すぎると処理が追いつかないので負荷を軽くする
ffmpeg -i input -vf nlmeans=1:3:0:7:0 output
それでも重たい場合は偶数フレーム(0, 2, 4…)にフィルタを当てることもできる
ffmpeg -i input -vf nlmeans=s=1:p=3:pc=0:r=7:enable=lt(mod(n\,2)\,1) output
エッジ保護をする場合は他にもエッジマスクしてから普通のデノイザを使うこともできる
ffmpeg でエッジマスク
出力比較
個別に PNG で出力したサイズは上から 249KB、237KB、218KB

>p[int]
>輝度(Y)のパッチサイズの指定。r よりも小さい値を指定する
r よりも小さい値を指定する、は必須ですか?
ドキュメントのnote部分を読むと、rはパッチの中心エリアを決めるものなので必須ではないと思いますが、どうなんでしょう?
dirk farin氏やhandbrakeは大きい値が使われているようです。
必須ではないですが、値を大きくするほど ssim を見る限り元映像に近づく(デノイズがあまり効かずファイルサイズが大きくなる)ようです。p, r の値の大小関係が逆転する前後で大きく変化上がるものでもありませんでした。ということで記事を修正しました。
これはどうも静止画向きのフィルタのようですね。
少し試してみましたが waifu2x で除けられない類のノイズ(少しYやCがずれてるのが斑状に広がっているようなの)が潰せるのがいいです。