HDRからSDRなどのトーンマッピングするのに使われているtonemap
フィルタの使い方。高ビット深度から低ビット深度へ変換するために範囲外の値を線形化と浮動小数点にしてトーンマッピングし、出力先の変換式などに直す処理も同時に行う。ネイティブフィルタtonemap
フィルタの他にOpenCLを使ったtonemap_opencl
フィルタもある。
tonemap
基本コマンド
最初のzscale
フィルタで線形化し、format
フィルタで32ビット浮動小数点に変換し、tonemap
フィルタのclipでトーンマッピングして、zscale
フィルタで出力先にあわせてガンマカーブをbt709にして、ピクセルフォーマットをformat
フィルタで指定する。
ffmpeg -i input -vf zscale=transfer=linear,format=gbrpf32le,tonemap=clip:param=1.0,zscale=transfer=bt709,format=yuv420p -c:a copy output
ffplay -i input -vf zscale=transfer=linear,format=gbrpf32le,tonemap=clip:1.0,zscale=transfer=bt709,format=yuv420p
RGB画像で出力するときはformat
フィルタをgbrpにする。
ffmpeg -i input -vf zscale=transfer=linear,format=gbrpf32le,tonemap=clip:1.0,zscale=transfer=bt709,format=gbrp -vframes 1 output.png
HDRをSDRに変換して再生する。
ffplay -i input -vf zscale=transfer=linear,tonemap=hable,zscale=transfer=bt709,format=gbrp
ffmpeg – How to choose correct color space and transfer function with ffplay – Super User
HDR10からSDRに変換する。
ffmpeg -i input -vf zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p -c:a copy output
ffplay -i input -vf
zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p
具体的に何をしているか。Add tonemapping filter to convert HDR10 content to SDR. · Issue #415 · jellyfin/jellyfinより
- YUV –> RGB
- Linearization (Inverse PQ/HLG Curve)
- Tonemapping/EETF (Reinhard is a good starting point, Hable is default in VLC. I ended with a kind of pseudo-Uncharted2-inspired curve which I quite like)
- Gamma Correction (Rec.709 Curve)
- RGB –> YUV
SDRからHDRにトーンマッピングする。
Inverse Tone Mapping – Upscaling SDR Content to HDR
公式ドキュメント:FFmpeg Filters Documentation : tonemap
オプション
- tonemap[int]
トーンマッピングアルゴリズムの指定 - 0, none:トーンマッピングせずに輝度がはみ出た分だけ脱色する
- 1, linear:基準の色域全体をディスプレイの線形倍数に引き伸ばす
- 2, gamma:ガンマカーブを用いる
- 3, clip:範囲外の値をハードクリップする。範囲外の値を歪ませながら範囲内の値に対して完璧な色精度を得るために使用する
- 4, reinhard:画像全体の明るさをシンプルな曲線で維持し、非線形コントラストを使用することで細部を平坦にし色の精度を低下させる
- 5, hable:全体をわずかに暗くすることで暗い部分と明るい部分の両方の細部をreinhardよりもよくする。色や明るさの精度よりも細部が重要な場合に使用する
- 6, mobius:範囲外の値をスムーズにマッピングし範囲内のマテリアルのコントラストと色を可能な限り保持する。細部よりも色の正確さが重要な場合に使用する
- param[double]
tonemapに対応したパラメータの指定 - none:指定内容はない
- linear:引き延ばす値の指定
既定値:1.0 - gamma:ガンマ値の指定
既定値:1.8 - clip
クリッピングの前に乗算する余分な線形係数の指定
既定値:1.0 - reinhard:表示ピーク時の局所的なコントラスト係数の指定。既定値の0.5は入力した色域値がクリッピング時の約半分の明るさになる
既定値:0.5 - hable:指定内容はない
- mobius:線形変換からメビウス変換への移行点の指定。この点以下の値はすべて1:1でマッピングされる。値が大きいほど結果はより正確になるが、その代わりに明るい細部が失われる
- desat[double]
明るさのレベルを超える明るい部分には脱彩度(desaturation)を適用する。パラメータが高いほど色情報が保存される。このオプションは明るい部分の色が不自然に白になるのを防ぐのに役立つ。これにより映像がより自然に感じられるようになるが範囲外の色の情報が少なくなる。既定値の2.0はやや保守的で、ほとんどの場合空や直射日光の当たる表面にのみ適用される。0.0に指定するとこのオプションは無効になる。このオプションは入力フレームが対応しているメタデータを持っているときしか使えない
既定値:2.0
範囲:0からDBL_MAXまで - peak[double]
この値で信号/基準ピークを上書きする。メタデータに埋め込まれたピーク情報が信頼できないときや、低域から高域へのトーンマッピングを行う場合に役立つ
既定値:0.0
範囲:0からDBL_MAXまで
tonemap_opencl
tonemap
フィルタと少しオプション内容が異なるのと、フィルタの記述方法が難しい。
rigayaの日記兼メモ帳 AviutlのGPUフィルタでHDR2SDR
基本コマンド
HDRからSDRに変換。映像の種類によっては「Failed to inject frame into filter network: Cannot allocate memory」が出てエラーになるかもしれない。
ffmpeg -init_hw_device opencl=ocl -filter_hw_device ocl -i input -vf format=p010,hwupload,tonemap_opencl=tonemap=mobius:param=0.01:desat=0:r=tv:p=bt709:t=bt709:m=bt709:format=nv12,hwdownload,format=nv12 -c:a copy output
-hwaccel dxva2を使う。
ffmpeg -hwaccel dxva2 -hwaccel_output_format dxva2_vld -init_hw_device opencl=ocl -filter_hw_device ocl -i input -vf hwdownload,format=p010,hwupload,tonemap_opencl,hwdownload,format=nv12 -c:a copy output
cudaデコード、nvencを併用する。
ffmpeg -hwaccel cuda -hwaccel_output_format cuda -init_hw_device opencl=gpu -filter_hw_device gpu -i input -filter_complex "hwdownload,format=p010,hwupload,tonemap_opencl=tonemap=hable:r=tv:p=bt709:t=bt709:m=bt709:format=nv12,hwdownload,format=nv12,hwupload_cuda" -c:v hevc_nvenc -c:a copy output
Combining 2 Video Filters : ffmpeg
nvidia graphics card – FFMPEG 4k HDR to 1080p SDR Hardware Tonemap Conversion ( OpenCL) – Super User
公式ドキュメント:FFmpeg Filters Documentation : tonemap_opencl
オプション
- tonemap[int]
トーンマッピングアルゴリズムの指定 - 0, none:トーンマッピングせずに輝度がはみ出た分だけ脱色する
- 1, linear:基準の色域全体をディスプレイの線形倍数に引き伸ばす
- 2, gamma:ガンマカーブを用いる
- 3, clip:範囲外の値をハードクリップする。範囲外の値を歪ませながら範囲内の値に対して完璧な色精度を得るために使用する
- 4, reinhard:画像全体の明るさをシンプルな曲線で維持し、非線形コントラストを使用することで細部を平坦にし色の精度を低下させる
- 5, hable:全体をわずかに暗くすることで暗い部分と明るい部分の両方の細部をreinhardよりもよくする。色や明るさの精度よりも細部が重要な場合に使用する
- 6, mobius:範囲外の値をスムーズにマッピングし範囲内のマテリアルのコントラストと色を可能な限り保持する。細部よりも色の正確さが重要な場合に使用する
- param[double]
tonemapに対応したパラメータの指定 - none:指定内容はない
- linear:引き延ばす値の指定
既定値:1.0 - gamma:ガンマ値の指定
既定値:1.8 - clip
クリッピングの前に乗算する余分な線形係数の指定
既定値:1.0 - reinhard:表示ピーク時の局所的なコントラスト係数の指定。既定値の0.5は入力した色域値がクリッピング時の約半分の明るさになる
既定値:0.5 - hable:指定内容はない
- mobius:線形変換からメビウス変換への移行点の指定。この点以下の値はすべて1:1でマッピングされる。値が大きいほど結果はより正確になるが、その代わりに明るい細部が失われる
- desat[double]
明るさのレベルを超える明るい部分には脱彩度(desaturation)を適用する。パラメータが高いほど色情報が保存される。このオプションは明るい部分の色が不自然に白になるのを防ぐのに役立つ。これにより映像がより自然に感じられるようになるが範囲外の色の情報が少なくなる。tonemap
フィルタと少しアルゴリズムが異なる。0.0に指定するとこのオプションは無効になる
既定値:0.5
範囲:0からDBL_MAXまで - threshold[double]
シーンが変化したかどうかを検出するためにトーンマッピングアルゴリズムのパラメータをシーンごとに微調整するしきい値の指定。現在のフレーム平均輝度とこれまでの平均輝度との距離がしきい値を超えたときシーン平均輝度とピーク輝度を再計算する
既定値:0.2
範囲:0からDBL_MAXまで - peak[double]
上書きするピーク値
既定値:0.0
範囲:0からDBL_MAXまで - format[pix_fmt]
出力フォーマットの指定。FFmpeg – Wikipedia : Pixel formats - p010:Planar YUV 4:2:0、10ビット
- nv12:Planar YUV 4:2:0、8ビット
- range, r[int]
出力カラーレンジの指定。既定値は入力値と同じ - 1, tv, limited
- 2, pc, full
- primaries, p[int]
出力カラープライマリー(別の言い方ではカラースペース、ホワイトポイント)の指定。既定値は入力値と同じ - 1, bt709:HDRからSDR変換ならこちら
- 9, bt2020:HDRの相互変換ならこちら
- transfer, t[int]
出力トランスファーの指定。既定値は入力値と同じ - 1, bt709:HDRからSDR変換ならこちら
- 14, bt2020:HDRの相互変換ならこちら
- matrix, m[int]
出力色空間マトリクスの指定。既定値は入力値と同じ - 1, bt709:HDRからSDR変換ならこちら
- 9, bt2020:HDRの相互変換ならこちら