2016年3月28日月曜日

TCannyMod その2

TCannyModをまた更新しました。


TCannyMod

TCannyMod-1.1.0.zip

mode0(つまり普通のcannyフィルタ)が30%~50%速くなりました。
あとガウシアンブラーとかも少し速くなってます。
ついでにmode1のaliasとしてEMask()を作りました。

ちなみに手元のベンチマークでは、64bitだと1080pのグレイスケール(Y8)なcrowd_runをmode0のデフォルト設定で27.5fpsで処理できます。
1.0.0からはAvisynth+のMT_NICE_FILTER対応にした(つもり)ので、32bitでも4スレッドもあればリアルタイムでプレビューできますな。
50fpsでうごくcrowd runの線画ってなんか奇妙に思えます。

2016年3月26日土曜日

TCannyMod

3年くらい前に書いたTCannyModを久々に更新しました。

TCannyMod

TCannyMod-1.0.0.zip

自分が昔書いたコードをいま読み直してみると、色々と訳が分からなくなることが多々あります。

あれー? なんで俺、こんな変なことやってんのかしら?

そういうのを見つけるたびに書き直したくなって、いざ手を付けてみるとすぐに飽きてやめることがほとんどなのですが、今回はリリースまでもったようです。

具体的な変更内容としては
1. 64bitのみAVX2/FMA3対応
 32bitで/arch:AVXを付けてビルドするとなぜか真っ黒になってしまうので64bitだけです。
 intrinsicってこういうときはダメだな。理由がさっぱりわからん。
2.SSE4.1も対応
 こちらは32/64両方ですが、少なくともHaswellではSSE2とスピードは全く変わりません。
 まあ、ほとんど使ってないしね。
3.VS2015に開発環境を変更
 C++11の機能くらいは普通に使いたいです。
 といってもこれもほとんど使ってないですが。

くらいでしょうか。

Cannyではなく普通のエッジ検出(mode=1)やガウシアンブラー(mode=4 or GBlur())として使う分には、少し高速化してます。
Cannyとしてはhysteresis処理がどうやっても速くならないので、従来と変わりません。

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 応用

2016年3月16日水曜日

RemoveGrain mode13~mode16

今回はmode13からmode16までです。

これまでのmode1~mode12はRemoveGrainの名にふさわしくいずれもdenoiserでしたが、13~16はdenoiserではなくなんとdeinterlacerです。

インタレ解除においては失われてしまったフィールド情報をいかにして補間するかが重要になるわけですが、補間方法にも線型補間とか三次補間とか色々あります。
上図において失われたフィールド上の点Xを補間する場合、線型(linear)補間なら(F0 + F1) / 2、三次(cubic)補間なら(F0 + F1*3 + F2*3 + F3) / 8を行いますが、他に有名どころではELA(Edge Line Average)法というものがあります。
ELA法は補間自体は線型補間と同様の計算をしますが、参照する2点の組み合わせを上図の場合だと(Fu0,Fl4)、(Fu1,Fl3)、(Fu2,Fl2)、(Fu3,Fl1)、(Fu4,Fl0)の5つのどれか一つから選びます。
これは三次補間のような垂直方向のみのデータの組み合わせでは、エッジ部においてジャギるからです。
もしエッジが斜め方向に走っている場合は参照する点も斜め方向からとらないといけないってわけですね。

RemoveGrainが書かれた当時(2005年頃?もっと前?)、avisynthにはすでにELAを使ったdeinterlacerとしTomsmocompが存在しており、なかなかに高い評価を受けていました。
しかしTomsmocompには「アーティファクトが発生しやすい」という弱点もありました。

で、Kassandro氏はELAにおける参照点として(Fu0,Fl4)か(Fu4,Fl0)が選ばれてしまった場合アーティファクトが特に発生しやすいことから、組み合わせを(Fu1,Fl3)、(Fu2,Fl2)、(Fu3,Fl1)の3つに減らし、さらにTemporalRepairフィルタを併用することで、よりアーティファクトの少ない(しかも高速な)deinterlacerとしてmode13~mode16を実装したのです!

と、ここまで書きましたが現在これを使う人はまずいません。
なぜならアーティファクト低減機能付きELA deinterlacerとして2007年にYadifというフィルタが登場したからです。

Yadifで満足できないならこれを使っても満足できるということはまずありませんので、これでmode13~mode16の解説は終了とします。

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

RemoveGrain mode5~mode12

今回はmode5からmode12までです。

・mode5~mode9
mode1~mode4ではCの近傍の8点N1~N8のうちのどれか2点を選んでclampしていましたが、mode5~mode9ではこの2点をCを通る直線上に限定するようになっています。
つまり、2点(a,b)の組み合わせが(N1,N8)、(N2,N7)、(N3,N6)、(N4,N5)のいずれかに限定されるということです。
mode3やmode4では組み合わせを限定していなかったため、細い直線やその終端が壊れやすかったのが、組み合わせを直線状に限定することで壊れにくくなっています。

具体的な処理内容については言葉で説明するのは非常に難しいため、もうソースコードを読んでもらうしかありません。
よって、ここでは傾向だけを説明します。

ノイズの取れ具合はmode5 < mode6 < mode7 < mode8 < mode9 とmodeが上がるほど強力になりますが、その分映像に与える悪影響(エッジの角が丸まったり、ボケたり)も大きくなります。

そして処理スピードは mode2 > mode9 > mode5 > mode7 > mode6 = mode8 です。

一般に細い線を壊さない処理というものは、YUV4:2:0な映像の色差にフィルタをかける場合に効果を発揮します。(なんせ色差は輝度の4分の1しかありませんから)
よって5~9はmodeU、modeVで指定することがほとんどでしょう。

・mode10
mode10はclampを行わず、N1~N8のうち最も近い値(C-Nxの絶対値が最も低いもの)にCを置き換えたものを出力します。
一見簡単に思えますが、実はこの処理はmode1~mode9のどれよりも比較の回数が増えるため、処理スピードはmode6 > mode10です。
しかもノイズの取れ具合はmode1と同程度と、もはや何のためにあるのかよくわかりません。

これが効果的な映像とは果たして…?

・mode11/mode12
mode11とmode12は3x3のconvolution filterです。
使用するカーネルは[1, 2, 1, 2, 4, 2, 1, 2, 1]で、これは内蔵フィルタのBlur(1.0)に相当しますがより速くて正確です。
オリジナルのほうのドキュメントの該当部分を読んでみると(処理内容があらかじめ理解できているとドキュメントも理解できるようになりました…なんという本末転倒…)
「mode12はmode11よりもさらに速いよ」ってなことが書かれていますが、tp7氏はどちらも同じ処理にしてしまっています。
そりゃ出力が同じなら、速い方しか要らんよね…なんで遅い方をわざわざ残してたんでしょ?

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

RemoveGrain mode1~mode4

まずはmode1からmode4の説明です。

・mode1
mode1ではN1からN8までの8点のうちの最小値minNと最大値maxNを求め、clamp(C, minN, maxN)を出力します。
このように、ポツポツと不連続なドット状ノイズが出ているような画像にかけると、ノイズ以外の部分にはほぼ影響を出さずにノイズだけ消すことができます。
ちなみにこの処理はtrbarry氏のundotフィルタと同じものです。

・mode2
mode2ではN1からN8までの8点のうちの2番目に小さい値min2Nと2番目に大きい値max2Nを求め、clamp(C, min2N, max2N)を出力します。
1よりもちょっと大きなノイズも取れますが、エッジの終端部分が少し壊れます。


・mode3
mode3ではN1からN8までの8点のうちの3番目に小さい値min3Nと3番目に大きい値max3Nを求め、clamp(C, min3N, max3N)を出力します。
mode2よりもさらに大きなノイズが取れますがエッジの終端により大きな影響を与えます。また、細い線が結構壊れます。

・mode4
mode4ではN1からN8までの8点のうちの4番目に小さい値min4Nと4番目に大きい値max4Nを求め、clamp(C, min4N, max4N)を出力します。
少し考えればわかると思いますが、これはN1~N8とCの9点におけるmedian(中央値)と同じです。
つまりmode4はごく一般的な3x3のメディアンフィルタです。
1~3に比べて結構ボケるし、エッジの角が丸くなったりしますので注意が必要です。使用の際はエッジマスク等の併用を常に考える必要があります。

ちなみに処理スピードはmode1 > mode4 >= mode2 = mode3 です。

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

RemoveGrainの基本事項

RemoveGrainのシンタックスは以下の通りです。

RemoveGrain(clip clip, int "mode", int "modeU", int "modeV", bool "planar")

今回はまず、フィルタの具体的な処理内容以外のことについて解説します。

RemoveGrainにおける基本事項


・参照サンプルの配置
RemoveGrainはmode=1からmode=24までの24種類のフィルタを一つにまとめたものですが、これらは全て処理対象となるサンプルとその近傍8点を参照するspatial(空間軸)フィルタです。
図にするとこんな感じ。
中央のCが処理対象となるサンプルで、N1~N8はその周囲のサンプルです。
次回から説明するすべてのmodeにおいて、処理対象となるプレーンの上下左右の画像端1ラインを除くすべてのサンプルに対して処理を行います。
なお画像端の1ラインはそのままコピーされます。

・mode、modeU、modeV
RemoveGrainではYプレーン、Uプレーン、Vプレーンそれぞれに異なったmodeでフィルタをかけることができます。
RemoveGrain(mode=10, modeU=2, modeV=5)なら、Yプレーンはmode10、Uプレーンはmode2、Vプレーンはmode5のフィルタがかかります。
modeは1~24までの24種類がありますが、それ以外に-1(なにもしない)と0(そのままコピー)もあります。
-1の場合、フィルタリング後のデータを書き出すために用意されたメモリには何も手を加えられませんので、どのような出力になるかは誰にもわかりません(avisynthは確保したメモリのゼロクリア等はしません)。
0ならば、フィルタ前のデータがそのままフィルタ後のメモリにコピーされます。
mode、modeU、modeVのデフォルト値はmode=1、modeU=mode、modeV=modeUです。
よって、もしYのみにフィルタをかけたい場合は、RemoveGrain(mode=1~24のどれか, modeU=0)とします。

・planar
本家RemoveGrainはYV12とYUY2/RGB(一応)をサポートしていましたが、RGToolsではYUY2やRGBのサポートはなくなり、代わりに全てのplanar format(YV24, YV16, YV12, YV411, Y8)をサポートするようになりました。
YUY2なクリップに対してフィルタをかけたいなら事前にConvertToYV16()をかけ、フィルタ後にConvertToYUY2()で元に戻しましょう。
RGBにかけたいならPlanarToolsでも使ってください。
planarパラメータはもともと本家RemoveGrainではSSE2Toolsを利用したYUY2/RGBサポートのために用意されていたものですが、RGToolsでは単にavisynth2.5用に書かれたユーザースクリプトへの互換性のためだけに用意されたもので、これをtrueにしてもいいことはまったくありません。
よってこのパラメータは一切弄らないようにしましょう。

・clamp()
modeの内容を説明するにあたり、clamp(x, a, b)という表現を使用することになると思います。
clamp(x, a, b)はxがa以下の場合はa、xがb以上の場合はb、a < x < b の場合はxの値そのままの意味になります。(なお常にa <= bの関係が成り立つものとします)
この処理はclippingとかsaturateなどと呼ばれることもありますが、ここではとりあえずclampで統一します。

では次からいよいよmodeの説明にはいります。

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

RemoveGrain解説 導入

RemoveGrainはkassandroことRainer Wittmann氏が書いた有名なavisynthプラグインです。
Didée氏のscriptなんかではほぼ確実に使われていたりと使用頻度は極めて高いプラグインなのですが、その使い方は自分にとって極めて難解なものでした。

難解な理由その1: ドキュメントが極めて読みにくい。
RemoveGrainのドキュメントはすべて英語で書かれています。
まあ英語だけならある程度気合いを入れれば読めないことはないのですが、なんと改行がほとんどありません。

数行読むだけでも息が詰まってくる上に、すぐにどこまで読んだのかわからなくなってしまうことの連続でいつも10分経たぬうちに挫折してしまいます。
まったく読みづらいったらありゃしねえ…。
RTFM(Read The Fine/F○○kin' Manual)なんて言葉がありますが、ここまでF○○kin'なマニュアルも珍しいんじゃないかと思います。

難解な理由その2: コードが極めて読みにくい。
「マニュアルがダメならソースコードを読んで理解すればいいじゃない」
そんな風に考えていた時期が俺にもありました。
CやPythonを少し覚えてちょぼちょぼとは書けるようになった頃だったと思います。
しかしその考えが甘かった。

RemoveGrainのバイナリパッケージにはRemoveGrain,Repair,DenoiseSharpen,RSharpenという4種類のDLLがCPUアーキテクチャやMSVCRTのスタティックリンク等の別に合計で13個(!)入っているわけですが、これらをビルドするためのソースコードはなんと約8900行からなるRemoveGrain.cppというたった一つのファイルしかありません。
いや、普通は複数のファイルで一つのバイナリなのに、一つのファイルで複数のバイナリっておかしいやろ…はじめて中身を覗いたときはそりゃもうびっくりしましたよ。

数行おきに現れる#ifdef~#elif~#endif、inline asm、そしてCPPマクロの嵐。
もはや狂気を感じるレベルです。
まあ、自分が書いたコードも(特に数年くらい前のやつとか)いま見直すと結構アレなんですが、このレベルになるともう、わざと書こうと思っても書けるものではありません。
実はわたくし、ドイツ人というものになんというかちょっとネガティブな偏見を持っているのですが、そのうちの半分くらいはこのRemoveGrainのドキュメントとコードに起因するものだったりします。

その後の展開
で、RemoveGrainのドキュメントとコードの解読はすっかり諦めていたわけですが、そのうちにFiresledge(cretindesalpes)氏がDitherPackage用に改造したりVapourSynthに移植されたりといったことが起こり、avisynthのほうでもtp7氏がRgToolsとしてrewrite版を出したおかげで大変わかりやすいソースコードが手に入るようになりました。
でもあいかわらずドキュメントは…。
で、自分用の備忘録も兼ねて解説でも書いてみようかなーとか思ったわけです。

tp7氏のRGToolsにはRemoveGrain、Repair、Clense、FowerdClense、BackwordClense、VerticalCleanerの計5つのフィルタが入っていますが、これらはすべてKassandro氏が書いたもののrewrite versionです。
解説はRGToolsのRemoveGrainをもとに行いますので、オリジナル(Kassandro版)とは違うところもあるかもしれません。

では次回よりRemoveGrainの解説を行います。

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

2016年3月5日土曜日

yadifmod2

前回yadifmodを書き直したものを公開しましたが、結局yadifそのものもavs2.6用に書き直すことにしました。

というわけでできたのがyadifmod2です。

yadifmod2

バイナリはここ

YadifMod2 = Yadif + YadifMod

とあるように、edeintなしならyadif、edeintありならyadifmodになります。

2016年3月1日火曜日

YadifMod for Avisynth2.6 / Avisynth+

tritical氏のyadifmodをAvisynth2.6/Avisynth+用に書き直してみました。

ソースコード:
yadifmod26

バイナリ(32bit/64bit同梱):
https://github.com/chikuzen/yadifmod26/releases

tritical版はSIMDはMMXしかありませんでしたが、今回SSE2とAVX2に対応させました。
それなりに速くはなったようです。

なおバイナリにyadifmod.dllとyadifmod_avx.dllの2種類がありますが、AVXマシン(SandyBridge以降だっけ?)はyadifmod_avx.dllを、
Nehalemとかの場合はyadifmod.dllを使ってください。

追記:これとは別にyadifとyadifmodを統合したyadifmod2もリリースしました。