2016年3月20日日曜日

yadifmod2 その3

またまたFizick氏からレポートいただきまして、0.0.3に更新しました。

もともとのyadifのコードの処理が1行抜けてたようです…すまぬorz

yadifmod2
ダウンロード

edeintなしの時の出力がyadifと(ほぼ)同じになりました。
画像端のみ違うことがありますが、もともとyadif自体が画像端の処理はほぼ無視の状態なので、これは仕様ということにします。

ちなみにyadifmodとして使う分には0.0.0から何も変わっていません。

2016年3月19日土曜日

Clense 応用

前々回にClenseの解説をしました。

Clenseは時間軸ノイズ除去フィルタとしてはなかなか扱いが難しいですが、しかし3枚のフレームによるメディアンフィルタというのは、ちょっと工夫すると面白い使い方ができます。

例えば本来は同一の映像なのに、ノイズの出方が異なる3つのクリップV0,V1,V2があるとします。

で、この3つのクリップのメディアンを求めてやると
V0 = something
V1 = something
V2 = something
median = median3(V0, V1, V2)

StackVertical(StackHorizontal(v0, v1), StackHorizontal(v2, median))

function median3(clip c, clip p, clip n, bool "gray")
{
    gray = default(gray, false)
    c = c.DuplicateFrame(0)     #Clenseはpreviousとnextを前後に1フレームずつずらしてしまうので
    n = n.DuplicateFrame(0, 0)  #DuplicateFrameで位置合わせをする
    return Clense(c, p, n, gray).DeleteFrame(0)
}

ノイズというのは本来そうであるべき値より高い又は低い状態ですから、ノイズの出方がそれぞれ違っていればメディアンを取ってやれば消えるわけです。

ただしノイズが同じ場所に重なっていると、それは消えません。

アニメ/ドラマのOPとか、あるいは放送局違いで3種類のソースが手に入ったとかいう場合には使えるかもしれませんね。

目次:
RemoveGrain解説 導入
RemoveGrainの基本事項
RemoveGrain mode1~mode4
RemoveGrain mode5~mode12
RemoveGrain mode13~mode16
RemoveGrain mode17~mode22
RmoveGrain mode23/mode24 及び総評
Repair
Clense
Clense 応用

yadifmod2 その2

Fizick氏からバグレポート頂いたので修正しました。

yadifmod2
version 0.0.2

edeintなしでoptが0以外のときの出力が誤っていたのが直りました。
あと、なんか前より速くなった気がする。

2016年3月18日金曜日

Clense

RemoveGrain、Repairと解説したのでついでにClenseも解説しときます。

思えばClenseは自分にとってRemoveGrainやRepair以上に謎の多いフィルタでした。
ドキュメントやコードは理解できないうえに、名前にしてもclense(清潔にする)って、あいまいすぎます。
avisynth.infoには

RemoveDirtと同じシンプルなテクニックを使った時間軸クリーナー。ただし、人工物(artifacts)の検出を行わない。Repair(もしくは他の人工物(artifacts)除去フィルタ)とセットで使用する。

とありますが、これでなにかが分かる人なんているとも思えません。

果たしてClenseの正体とはなんなのか?
その答えは3つのフレームによる時間軸メディアンフィルタでした。

Clense(clip c, clip "previous", clip "next", bool "gray")

Clenseは3つのクリップを引数にとります。
previousとnextのデフォルト値はcで、処理にあたってはcのn番フレーム、previousのn-1番フレーム、nextのn+1番フレームを一組とし、各フレームの同一座標上のサンプルのメディアンを返します。
grayのデフォルト値はfalseで、これをtrueにするとフィルタ後に出力されるフレームの色差は全く処理されてない状態(RemoveGrainにおけるmodeU=-1、modeV=-1と同じ)になります。

・使用例
Clenseは時間軸ノイズ除去フィルタです。例えば
src = something
src.ApplyRange(100, 100, "subtitle", "noise", 100, 100) #100フレーム目のみnoiseの文字を入れる 
next = last.DuplicateFrame(0)
prev = last.deleteframe(0)
StackHorizontal(prev, last, next)
こんな感じで、あるフレームだけポツンとノイズがでているソースにClense()をかけてやると
src = something
src.ApplyRange(100, 100, "subtitle", "noise", 100, 100)
Clense()
next = last.DuplicateFrame(0)
prev = last.deleteframe(0)
StackHorizontal(prev, last, next)
けっこういい感じでノイズが消えたりします。
そもそもノイズというものは、周囲に比べて極端に値が高いか低いかのどちらかなので、前後のフレームとのメディアンを求めれば消えてしまうのですね。
ただし、ちょっと動きが大きくなると
このように残像が出てしまうので使い勝手はあまりよいとはいえません。

目次:
RemoveGrain解説 導入
RemoveGrainの基本事項
RemoveGrain mode1~mode4
RemoveGrain mode5~mode12
RemoveGrain mode13~mode16
RemoveGrain mode17~mode22
RmoveGrain mode23/mode24 及び総評
Repair
Clense
Clense 応用

2016年3月17日木曜日

Repair

前回までRemoveGrainの解説をやったので、Repairもやっておくことにします。

Repairはあるフレームにフィルタをかけた場合に発生したアーティファクトを低減するためのフィルタです。
名前もRepair(修復)で、ストレートなところがいいですね。

・シンタックス
シンタックスは
Repair(clip A, clip B, int "mode", int "modeU", int "modeV", bool "planar")
です。
RemoveGrainと違ってクリップ2つを入力にとります。

・Repairの基本と実例
Repairの基本的な考え方は
・任意のフィルタをかける前のクリップBeforeと、フィルタをかけたあとのクリップAfterを用意する。
・After上のあるサンプルXaと同一座標にあるBefore上のサンプルXb及びXbの近傍8点N1~N8を用意する。
・mode及びXb、N1~N8の値に応じてXaを書き換える。
となります。

modeは例によってたくさんありますが、mode1であれば
minimum = min(N1, N2, N3, N4, N5, N6, N7, N8, Xb); // Xb及びN1~N8のうちの最小値
maximum = max(N1, N2, N3, N4, N5, N6, N7, N8, Xb); // Xb及びN1~N8のうちの最大値
Xa = clamp(Xa, minimum, maximum); // Xaをminimum~maximumの範囲内にclamp
という処理を行います。

こうすることで、なんらかのフィルタをかけた際に出力値が極端に変化しすぎてしまったもの(=アーティファクト)を、許容範囲内に収めてしまおうというわけです。

では実際にやってみましょう。

まず、あるクリップにアンシャープマスクをかけてみます。
src = something
blur = src.RemoveGrain(19).RemoveGrain(19)
sharpen = src.mt_adddiff(src.mt_makediff(blur, chroma="process"), chroma="process")
StackHorizontal(src.Subtitle("source"), sharpen.Subtitle("sharpen"))

で、ちょっとこれだと強すぎかな?帽子周りとか肩あたりとかhaloでてるし~ という場合にこうする。
src = something
blur = src.RemoveGrain(19).RemoveGrain(19)
sharpen = src.mt_adddiff(src.mt_makediff(blur, chroma="process"), chroma="process")
repair = Repair(sharpen, src, 1)
StackHorizontal(src.Subtitle("source"), sharpen.Subtitle("sharpen"), repair.Subtitle("repair"))
はい、「ちょっとシャープ強すぎ?」が「そこそこシャープ」になりました。便利ですね。

・Repairのmode
RepairもRemoveGrain同様、modeは1~24(+mode-1とmode0)が用意されています。
しかし、mode1以外を使っているスクリプトを自分は知りませんし、自分でも1以外を使った記憶がありません。
まあ、ものによっては1以外が有効なこともあるんでしょうが…。
興味のある方は色々なソースやフィルタで試してみてください。

ではRepair解説はこれで終了とします。

目次:
RemoveGrain解説 導入
RemoveGrainの基本事項
RemoveGrain mode1~mode4
RemoveGrain mode5~mode12
RemoveGrain mode13~mode16
RemoveGrain mode17~mode22
RmoveGrain mode23/mode24 及び総評
Repair
Clense
Clense 応用

RemoveGrain mode23/mode24 及び総評

さて、RemoveGrainのmode解説も残すところあと2つとなりました。
ちなみにオリジナルにはmode25もありますが、RgToolsでは削除されています。

・mode23/mode24
mode23とmode24はエッジ周りを少し削ることを目的としたフィルタです。
ぼかしフィルタであるmode11/mode12/mode19/mode20やインタレ補間のmode13~mode16を除いた他のmodeは、基本的にエッジを保護するように働きますが、23と24はあえてエッジを削るのです。
これは、シャープフィルタや圧縮時のDCT等の影響で発生したhalo(オーバーシュート)を低減することが目的だからです。


たしかに帽子の輪郭とかのhaloが消えてはいますね…肩のあたりのラインが削れ過ぎてる気もするけど。
mode24でmode6+エッジ削りくらいかな?

スピード的にはmode9 = mode23 > mode5 = mode24 となります。

・総評
さて、以上でmode1~mode24の解説が終わりましたが、実際のところ、RemoveGrainはどのような感じで使われているのでしょうか?
Avisynth wikiのexternal filtersのページにはプラグインだけでなくユーザースクリプトも色々登録されていますので、使用にあたっての傾向がある程度わかります。

で、どんな感じかといえば…実際に使われているのはmode4、mode11/12、mode19/20ばっかりでした。

つまり、色々と工夫を凝らしてたくさんのmodeを用意したのに、現実にはただの高速blur/medianフィルタとしての需要しかないということです。

たしかにエッジ周りやラインの保護をしたければmasktools2等でエッジマスク作って色々やるほうが汎用性も高く仕上がりも調整しやすいですし、そもそも2005年と2016年では扱うソースも大幅に変わっていますし…。

とオチらしきものがついたところでRemoveGrain解説はおひらきといたします。

目次:
RemoveGrain解説 導入
RemoveGrainの基本事項
RemoveGrain mode1~mode4
RemoveGrain mode5~mode12
RemoveGrain mode13~mode16
RemoveGrain mode17~mode22
RemoveGrain mode23/mode24 及び総評
Repair
Clense
Clense 応用

RemoveGrain mode17~mode22

今回はmode17からmode22まで。


・mode17/mode18
mode17とmode18はmode5~mode9までと同じように、Cをclampする際の組み合わせをCを通る直線上の2点の組み合わせを元に選びます。
mode5~mode9同様、細い線を保護しつつ処理するのが主目的なようですね。

mode9までが実装、公開された後にDoom9あたりでディスカッションが起こり、それらを元に追加実装されたもののようですが、当時の自分はDoom9どころかエンコ自体知らなかったんで、そこら辺は憶測にすぎません。

傾向としては、mode17はmode1と同じかそれ以上に速くノイズの取れ具合もmode4なみですが、細い線以外への影響が大きい。
mode18はスピードも効き具合もmode5とmode6の中間ぐらいです。

・mode19/mode20
mode19とmode20はmode11/mode12のような3x3のconvolutionによるぼかしフィルタです。

mode19のカーネルは[1, 1, 1, 1, 0, 1, 1, 1, 1]で、mode20は[1, 1, 1, 1, 1, 1, 1, 1, 1]となっています。
どちらもmode11/mode12よりも強いblurがかかりますが、特にmode19は処理対象となる中央のサンプルCを含まないため、効きが一番強くなります。

・mode21/mode22
mode21とmode22は処理時の端数処理の違いはありますがどちらも同じフィルタです。
mode5等のようにCを通る直線状の2点の組み合わせ4組を使いますが、このmodeではそれらの組み合わせの平均値をまず求め、4つの平均値のうちの最小値と最大値でclampします。
コードっぽく書くなら
m1 = (N1 + N8) / 2;
m2 = (N2 + N7) / 2;
m3 = (N3 + N6) / 2;
m4 = (N4 + N5) / 2;
minimum = min(m1, m2, m3, m4);
maximum = max(m1, m2, m3, m4);
output = clamp(C, minimum, maximum);
といった感じです。
特にmode22はこれまでのどの処理よりも軽く、全24mode中最速となっています。

フィルタの傾向としてはmode1~mode10、mode17、mode18と違ってエッジ保護をしませんが、細い線は保護します。
というか細い線の保護以外は投げやっているような感じです。

目次:
RemoveGrain解説 導入
RemoveGrainの基本事項
RemoveGrain mode1~mode4
RemoveGrain mode5~mode12
RemoveGrain mode13~mode16
RemoveGrain mode17~mode22
RmoveGrain mode23/mode24 及び総評
Repair
Clense
Clense 応用