普通の人には役に立たないと思われる豆知識の紹介
タイトルだけでは何を言ってるかわかりにくいと思います。ということで図を用意しました
IIPPPのトップフィールドファースト(TFF)のソースです。DoubleWeave()した後はSelectEveryやPulldownを使って1、3 or 4、6、8 or 9の4フレームを選択すれば24pにできますよね
このときフレーム1はボトムフィールドにはソースのaのボトムフィールド、トップフィールドにはソースのbのトップフィールドが使われています。ボトムフィールドがトップフィールドより前のフレームのものを使っていることになるので、ボトムフィールドファースト(BFF)になるのです
3,5,7,9も同様にBFFということになります。2つのフレームからフィールドを選択してフレームを作る場合は、そのフレームのフィールドオーダーは元の逆になるのです
1 2 3 |
AssumeTFF() DoubleWeave().SelectEvery(10, 1, 4, 6, 8) nnedi3(field=-1) |
こんなスクリプトがあったとします。クリップをAssumeTFF()を使ってTFFと定義しましたが、DoubleWeave().SelectEvery(10, 1, 4, 6, 8)の後は先頭の1がBFFなので、nnedi3にはBFFとして認識されてしまいます
3行目のnnedi3はfield=-1(自動選択/TFFなら1、BFFなら0になる)が指定されていますが、一度AssumeTFF()を使ったにも関わらず0として全フレーム動作してしまうのです
1 2 3 4 |
AssumeTFF() DoubleWeave().SelectEvery(10, 1, 4, 6, 8) AssumeTFF() nnedi3(field=-1) |
このようにAssumeTFF()をしなおせばnnedi3のfieldは1として全フレーム動作します。逆テレシネの後にフィールドオーダーを読んで処理させる場合、おまじないのようにAssumeTFF()やBFF()をするのはこのためです
Pulldown()で考えるなら、(0,2)や(0,3)や(2,4)を実行した後はフィールドオーダーは変わらず、(1,3)や(1,4)の後はフィールドオーダーが逆転してしまう、となります
さて、逆転することがあるということと、逆転する原因はわかりました。では次にフィールドオーダーはクリップごとに保存されているのか、フレームごとに保存されているのかを考えてみます。まずこうやってみました
1 2 3 |
AssumeTFF() DoubleWeave().SelectEvery(10, 1, 4, 6, 8) Subtitle(string(GetParity())) |
GetParity()はTFFならtrue、BFFならfalseを返します。こうしてみたところ、全フレームでfalseが表示されました。ということは全フレームBFFになっているからクリップごとに保存かな?と思えます
次にこうやってみました
1 2 3 4 |
AssumeTFF() DoubleWeave().SelectEvery(10, 1, 4, 6, 8) ScriptClip(last, " Subtitle(string(fo)) ") FrameEvaluate(last,"fo = Trim(current_frame,0).GetParity()") |
0フレーム目では普通にGetParity()をした結果を表示する、1フレーム目では先頭0フレーム目を削除してからGetParity()をした結果を表示する、2フレーム目では先頭の0,1の2フレームを削除してからGetParity()をした結果を表示する・・・ということをしています
するとなんと、0フレーム目はfalse、1~3フレーム目はtrue、4フレーム目はfalse・・・が表示されたのです
次に
1 2 3 4 5 |
AssumeTFF() DoubleWeave().SelectEvery(10, 1, 4, 6, 8) AssumeTFF() ScriptClip(last, " Subtitle(string(fo)) ") FrameEvaluate(last,"fo = Trim(current_frame,0).GetParity()") |
こうしてAssumeTFF()を間に挟んでみました。そうすると全フレームでtrueが表示されました
つまり
- フィールドオーダーを読んで処理できるもの(GetParityやnnedi3など)の一部はクリップの先頭のフレームのフィールドオーダーしか見ていないものがある
- フィールドオーダーはフレームごとに保存されている
- DoubleWeave()後の10フレームのうち、1,3,5,7,9番目の5フレームはフィールドオーダーが逆転する
- AssumeTFF()/BFF()は全フレームのフィールドオーダーを書き換える
こういうことになります。ちなみにSeparateFields()は毎フレームTFFかBFFか見て処理しているようです
また、
1 2 |
ConditionalFilter(last, hoge(), last, "fo", "=", "false") FrameEvaluate(last,"fo = Trim(current_frame,0).GetParity()") |
こんな風に書けば、2つのフレームからフィールドを取って作ったフレーム(DoubleWeave().SelectEvery(10,・・・)なら奇数を指定したフレーム)に対してのみhoge()が実行できる、ということにもなります
はい、役に立たない知識かもしれません。しかし、無理やり使おうと思えば使えなくもないかもしれません。2つのフレームからフィールドを選択して作ったフレームの特徴として
- 海外映画やドラマなどで、逆テレシネ前に字幕の縞がなかったソースの場合は、そのフレームにのみ字幕に縞が出る可能性がある
- そのフレームがシーンチェンジ直後か直前だったら画質の劣化が激しい
こういうことがあげられます
と、いうことで次のようなケースを考えてみました
1 2 3 4 5 6 7 8 9 |
v1 = Trim(0,5214).AssumeTFF().DoubleWeave().SelectEvery(10,0,3,6,8) v2 = Trim(5215,30774).AssumeTFF().DoubleWeave().SelectEvery(10,1,4,6,8) v3 = Trim(30779,43003).AssumeTFF().DoubleWeave().SelectEvery(10,0,2,4,7) v4 = Trim(43006,43905).AssumeTFF().DoubleWeave().SelectEvery(10,0,3,6,8) v1++v2++v3++v4 ConditionalFilter(last, AssumeTFF().CombReduce(last), last, "fo", "=", "false") FrameEvaluate(last,"fo = Trim(current_frame,0).GetParity()") |
CombReduce()は以前コメント欄で教えていただいた、字幕に縞が出た場合それだけ消す関数です。こう書けば、ソース次第では、縞が出る可能性のあるフレームにだけ関数を実行できて、結果は変わらないのに速度が稼げてしまう!
次に画質劣化に対処するケースを考えてみましょう
1 2 3 4 5 6 7 8 9 |
v1 = Trim(0,5214).AssumeTFF().DoubleWeave().SelectEvery(10,0,3,6,8) v2 = Trim(5215,30774).AssumeTFF().DoubleWeave().SelectEvery(10,1,4,6,8) v3 = Trim(30779,43003).AssumeTFF().DoubleWeave().SelectEvery(10,0,2,4,7) v4 = Trim(43006,43905).AssumeTFF().DoubleWeave().SelectEvery(10,0,3,6,8) v1++v2++v3++v4 ConditionalFilter(last, AssumeTFF().DecombUCF(last), last, "fo", "=", "false") FrameEvaluate(last,"fo = Trim(current_frame,0).GetParity()") |
DecombUCFはちょっとだけさんの、ノイズ量を計算して破綻したフレームの画質を修復するスクリプトです。このスクリプトでノイジーなフレームと判定されるのは大抵2フレームからフィールドを取って作ったフレームです(絶対にそうなるというわけではありませんが、全フレームそうなる場合もあります)
なのでこのようにしてしまえば結果は変わらない可能性も結構あるのに速度が稼げてしまう!
どちらも関数を適応するフレームを最大1/4まで減らせます!
と、無理やり考えれば活用できなくもないかもしれません
コメント
CombReduce関数について検索しても出てこなかったので某掲示板で聞いてしまったんですが、よろしければCombReduce関数を公開していただけませんか?
こんばんは。関数は紹介記事があったのですが、使ったSSがあまり良くなかったのでお蔵入りにしてしまってそのまま放置しちゃってました
いずれちゃんとした紹介記事を復活させたいですが、ひとまずこちらに書いておきます
オリジナルは私ではなく別の方で、私の方でかなり変えてしまってます
逆テレシネした後にに出る縞々な字幕を潰す関数です
必要なプラグインはmasktools2, combmask, nnedi3です(mode=1)
<使用例1>
# 逆テレシネ後に実行するだけ
# 縞判定をして、縞と判定されたら縞の部分を消そうとします
AssumeTFF().DoubleWeave().SelevtEvery(10, 1, 4, 6, 8)
CombReduce()
<使用例2>
# 縞なフレームのリストがすでにある場合
# 縞判定をスキップします
AssumeTFF().DoubleWeave().SelevtEvery(10, 1, 4, 6, 8)
ConditionalFilter( last, makeCombReduce( mode=1, mmode=2 ), last, “combed”, “=”, “true” )
ConditionalReader ( “xxxx.log”, “combed”, false)
——————————————————————————————-
http://linino.dip.jp/misc/combreduce.avsi