掲示板お問い合わせランダムジャンプ

トップスペース

2008年04月29日
MMXとSSEに対応
 最近AviUtlのプラグインのことばかりですが、「間引ける1/2縮小」と「ガウスぼかし」をMMXとSSEに対応させて見ました。いつものところにアップしてあります。
 AviUtl プラグイン フィルタ by うえぽん
 もうこれ以上やることはないだろうし、道具が出来上がったのであとはプレイ動画を作ってニコニコにコッソリアップするだけです。AviUtlのプラグインを作るのはもう飽きました。

●組み込み関数を使おう
 MMXやSSEはアセンブラで組むものと思っている人も多いかもしれませんが、わざわざアセンブラを書かなくても“組み込み関数”を使えばC言語でもプログラムを組めます。しかもこれならコンパイラが最適化してくれるので、超凄腕のアセンブラ職人でもない限り組み込み関数で組んだ方が速いコードになります。超凄腕の人以外は組み込み関数を使いましょう。
 ただし、アセンブラは書かなくとも多少は読めたほうがいいです。コンパイラにアセンブラコードを出力させて、最適化度合いを見るからです。次第にC言語で書いてるのにアセンブラコードが見えるようになります。

●キャッシュしないと速くなることもある
 以前の「間引ける1/2縮小」のベンチマークではメモリ速度の壁にぶつかっていてこれ以上速度アップできないと思ってましたが、SSEのキャッシュ制御で出力時にL1やL2にキャッシュしないようにしたところ、なんとさらなる速度アップができました。
 しばらくアクセスしないデータはキャッシュしない方がL1、L2に余裕ができ、結果的に速くなるらしいです。
 以下ベンチマークの結果。Athlon64x2 4200+(2.4GHzにOC) DDR2 800MHzで、1280x720の動画(秒速5センチメートル)での結果です。
間引き方スレッド数SIMDなしMMXSSE
4ドットブレンド22.02 sec2.02 sec1.54 sec
12.57 sec2.30 sec1.94 sec
横ブレンド21.25 sec1.25 sec0.89 sec
11.70 sec1.58 sec1.37 sec
縦ブレンド22.01 sec2.01 sec1.53 sec
12.36 sec2.23 sec1.81 sec
間引く21.25 sec1.25 sec0.84 sec
12.36 sec2.23 sec1.81 sec


●メモリアライメントは揃えた方が速い
 「ガウスぼかし」もSSEに対応して速くなりました。ただし4個同時に乗算や除算することよりも、short型x3のピクセルデータをfloat型x4に拡張して128bitのメモリアライメントに並べたことによる速度アップが大きかったです。
 以下マルチスレッドでのベンチマーク結果。環境は上と同じ。設定の半径は24。シングルだとこれのちょうど2倍の時間が掛かりました。
モード時間
double(倍精度)で計算0.172 sec
longで計算0.250 sec
SSE(単精度)で計算0.125 sec

 キャッシュ制御といい、これといい、メモリ周りの見直しが一番速度アップになりそうです。

【余談】
 なまじ3D Now!に対応してしまうと、メンテナンスのためにAMDのCPUを所有し続けるはめになるんだよな。
[ 投稿者:うえぽん at 23:59 | AviUtlや画像処理 | コメント(2) | トラックバック(0) ]

2008年04月25日
ガウスぼかしフィルタ&キン肉マン理論で最適化
ガウスぼかし1
 AviUtlのプラグインにぼかしフィルタがあまり存在しないようなので、ガウスぼかしフィルタを作ってみました。いつものところにソース付きでアップしてあります。

 AviUtl プラグイン フィルタ by うえぽん

 テレビのニュース番組などで連行される容疑者の手錠がぼかされていることがありますが、それに似たようなこともできます。こんな感じです。
ガウスぼかし2


●参考にしたサイト
 下のサイトを参考にしました。
 ・MemoNyanDum : ガウスぼかし GaussianBlur
 ・t-pot『ガウスフィルタ』
 ・Gaussian blur - Wikipedia
 基本的なことは上のページを見れば大体分かります。
 上2つのページの補足としては、横と縦の2パスで処理するのはプログラムの理屈を分かりやすくするためのように思えますが、Wikipediaによると、実は高速化にもなっているそうです。O(m*n*M*N)がO((m+n)*M*N)になります。

●キン肉マンを応用した最適化
 このガウスぼかしフィルタは重たいです。しかし何も工夫していない分けではありません。キン肉マンで「6をひっくり返すと9になる」だとか「8を横にすると∞」だといった理論がありましたが、そんな感じで最適化してあります。
 具体的には“横方向へぼかす”→“縦方向へぼかす”と別々の関数で処理しているのを、“横方向へぼかす関数”の出力を縦横逆にすることによって、2パス目の処理も“横方向へぼかす関数”で処理させています。
2pass処理最適化説明

 メモリーのアクセス速度を気にする人は少ないようですが、横方向への処理はピクセルデータがメモリー上に連続するのでCPUの内部キャッシュにヒットしやすくなります。縦方向を横方向へすることによりキャッシュのヒット率が向上し、結果的に処理速度がアップします。実際、これによって処理時間が20%ぐらい短くなりました。
 あと、2つの関数を1つになることでプログラムの修正が容易になります。こうい画像処理はアセンブラレベルで最適化(SSEやSSE2へ対応)されることが多いですが、2つが1つになれば2倍楽になります。ついでにバグも減ります。

●ベンチマーク
 私の環境(Athlon64x2 4200+を2.4GHzにOC)でベンチマークしてみました。σを8にして1280x720の動画をぼかした際の結果です。
-マルチスレッドシングルスレッド
浮動小数点0.172 sec0.344 sec
固定小数点0.235~0.250 sec0.515 sec

 浮動小数点が固定小数点の1.5倍の速さというのに驚きです。Athlon64は浮動小数点処理が速いらしいのでその可能性があります。もしかしたら他のCPUでは固定少数点の方が速いかもしれません。
 あと、マルチスレッド処理によって処理時間が綺麗に2倍になってます。固定小数点だと2倍以上になってますが、これは謎です。

[追記:2008/04/29]
 MMXとSSEに対応して若干速くなりました。

【余談】
 最近テレビでコカ・コーラなどにぼかしを掛けているのをよく見るようになったが、なんでああするんだろうね。
[ 投稿者:うえぽん at 23:59 | AviUtlや画像処理 | コメント(6) | トラックバック(0) ]

2008年04月18日
SSFの動画キャプ用に「間引ける1/2縮小フィルタ」を作った
 AviUtlのフィルタ「間引ける1/2縮小」というのを作ったのでそれに関する薀蓄です。

 フィルタはいつものページにアップしてあります。
 AviUtl プラグイン フィルタ by うえぽん

 このフィルタはセガサターンのエミュレータ「SSF」の動画を編集するために作りました。セガサターンの画面モードは320x224~704x480と幅広くあります。704x224なんてパターンもあったりします。しかしSSFでは画面モードが320x224の時でも二倍の640x448で表示していたりします(遊ぶだけならその方が良いのですが)。しかし、動画にする場合は本来の320x224の方が容量の節約になります。
 そこでこのフィルタを作ってみました。まあ、既存のフィルタでも同じことができますが。

●SSFの画面は縦方向に補間されている
 下の画像はSSFの同じ場面をキャプしたものです。左はPrintScreenでキャプ、右はSSFのスナップショットでキャプしたものです。
SSFより

 よく見ると左側の方が少しぼやけています。どうやら縦方向にだけ補間されているようです。おそらくWindowsのAPIを使って縦に引き伸ばしているのでしょう。ディスプレイドライバーが親切に補間してくれてます。Bilinear FilteringをOFFにしても同じです。
 これをそのまま縮小してしまうとさらにぼやけた映像になります。だからと言ってラインを間引いて縮小しても右側と同じになりません。
 もしくっきりした映像が欲しいなら、スキャンラインをONにしてキャプし、当フィルタで加工すると良いと思います。

●インタレース表示
 「セガサターンマガジン」にこの事が書いてありましたが、バーチャファイター2のフレームは下のようにブレブレしてます。テレビのNTSC方式が奇数ラインと偶数ラインを交互に表示しているのを利用して、解像度を上げつつ処理を半分にするためだったと思います。
VF2スナップ1

 この動画をキャプするには、間引いて1/2に縮小すればいいようです。下の画像が単純に間引いたものです。
VF2スナップ2

 しかしテロップのWのあたりなどがギザギザしています。これはテロップが704x448なのに単純に間引いてしまったからです。そこで横方向だけはブレンドして縮小することにします。
VF2スナップ3

 これでだいぶマシになりました。よく見るとギザギザしている部分もありますが、動画にしてしまえばあまり気にならないかと思います。

●ベンチマーク
 「間引ける1/2縮小」には簡単なベンチマーク機能がついてます。マルチスレッドの効果があるのか調べるために付けてみました。
 私が使っている環境はAthlon X2 4200+(AM2)、2.2GHzを約2.4GHzにオーバークロック、メモリはDDR2で約800MHz動作です。これで1280x720の画像を縮小した際の結果は以下の通りです。
-マルチスレッドシングルスレッド上昇率
間引き1.23 sec1.44 sec14.6%
横ブレンド1.24 sec1.65 sec24.8%
縦ブレンド1.96 sec2.24 sec12.5%
4ドットブレンド1.96 sec2.40 sec18.3%
 興味深いのは、縦ブレンドと横ブレンドは同じ計算量なのに横ブレンドの方が処理時間が短いことです。おそらく横ドット同士の方が連続したメモリなのでCPUの内部キャッシュにヒットしやすいためだと思います。メモリ転送量も減っているはずです。
 マルチスレッドで12%~25%ぐらい速度アップしてます。Athlon X2のL2キャッシュは非共有なのでマルチスレッドにすると都合L2キャッシュが2倍になるため、それによる速度アップがほとんどではと考えています。つまり計算速度が倍になったことによる速度アップはそれほど無いと推測しています。L2キャッシュが大きいCPUだとマルチスレッドによる速度アップ率は少ないのではないでしょうか。
 あとマルチスレッドにしても処理時間が同じになってしまうのは、もしかしたらメモリ転送量の壁があるのかもしれません。

●マイナス時の四捨五入
 四捨五入は0.5して小数点以下切捨てという処理が一般的です。しかし-2.5のようにマイナス時が厄介です。これは-2.0にしても-3.0でも良いようですが、YUVの場合、-2.0の方に丸めてしまうと全体的に色が偏ってしまいます。あまり気にならないレベルのことですが、AviUtlの有名なフィルタの中にはそれをやってしまっているものがあるようです。
 当フィルタではマイナスの値をとらない輝度情報は四捨五入、色情報はマイナスもあるので単純に切り捨てるようにしています。
[ 投稿者:うえぽん at 04:09 | AviUtlや画像処理 | コメント(0) | トラックバック(0) ]

「セピア色とか白黒とか」解説
 この前AviUtlのプラグインを作ったのでそれの解説を書いておきます。画像をセピア調にする方法が書かれたサイトがあまり見つからなかったので、もしかしたら何かの参考になるかもしれません。

 フィルタはここに置いてあります。
 AviUtl プラグイン フィルタ by うえぽん

 これが設定ダイアログ。
セピア色とか白黒とかダイアログ

 RGBを指定すると動画の色調を指定色と同じにします。「単色効果」とも言うようです。
 RGBの値はwikipediaで調べれば親切に書かれています。wikipediaを検索する際はwikipediaにある検索で調べるよりもgoogleで「site:wikipedia.org」とやった方が良いでしょう。
Wikipediaの色情報

 設定ダイアログにはプリセットとしてセピア色だけでなくヴァーミリオンやクリムゾンなどを用意しました。これはメガドライブやセガサターンのゲームが元ネタになっています。下のような感じになります。
セピア色とか白黒とか

 ニコニコ動画にアップしたのがこれ。


 さて、この画像処理の仕組みは簡単です。RGBをYUVに変換し、動画の全ピクセルのUV値を指定色と同じにします。AviUtlにはRGBをYUVに変換する関数が存在するので指定色をそれで変換。さらにAviUtlの内部処理はYUVなので、当プラグインがやるのはUVを書き換えるだけだったりします。

 一応RGB→YUVの変換の仕組みを説明すると、基本は下のような計算です。

 Y = 0.29891 * R + 0.58661 * G + 0.11448 * B
 U = Y - B (青色の差分)
 V = Y - R (赤色の差分)

 あとは仕様用途に応じてUVの値の範囲を規格化するだけです。ネットを調べるとYUVの変換式があれこれあるのは規格がいくつかあるからです。
 YUVからRGBにする場合は逆の変換をするだけです。

 ちなみに、Yの式を見たことがある人は多いと思います。これは白黒に変換する式と同じです。実はUVの値を0にしたのが白黒変換だったりします。当フィルタで白黒変換もできたりするのはそのためです。
[ 投稿者:うえぽん at 00:53 | AviUtlや画像処理 | コメント(0) | トラックバック(0) ]

2008年04月11日
広告バナーをAjax化するProxomitronのフィルタ
 自作して1年以上使っているProxomitronのフィルタですが、便利だと思うので公開しようと思います。
 標準のフィルタに「Banner Blaster」というのがありますが、これは意外と誤爆が多く、また、肝心なときに動作しません。そこで、アフィリエイトのホストをリスト化し、そこへリンクしている画像に対して処理するというようにしてみました。
 また、画像そのものがネタになっていることもたまにあるので、完全に画像を削るのではなく、マウスカーソルを載せるとAjax風に画像がオープンします。(ドラゴンボールのポイポイカプセルみたいで面白いです)


●動作サンプル
 ↓マウスオーバーでバナーが開きます
 amazonamazonamazon


●使い方
 (1)まずこのミニバナー画像をproxomitronのhtmlフォルダに「bnr.png」とリネームして保存。
 bnr.pngと名付けて保存

 (2)webフィルタを登録。(以前紹介したオミトロンをWeb側で検出する方法のRefererで弾く対策を行っている場合、ミニバナー画像のURLを変更しないと表示されません。たとえば、バイパスリストに local.ptron/{ユニークなディレクト名}/ という感じのを追加して、ミニバナーをそこに移動したりすると良いと思います)
[Patterns]
Name = "Banner Image Ajax load (2008/04/11)"
Active = TRUE
Multi = TRUE
URL = "$TYPE(htm)|$TYPE(js)"
Bounds = "$NEST(<a\s*>,</a >)"
Limit = 2048
Match = "(*\shref=$AV(http(s|)://$LST(AfiList)*)[^>]++>*)\1(<img)\2([^>]++)\3\ssrc=(*>)\4\5"
        "|"
        "\1(<img[^>]++width=([#468]|[#728])[^>]++>&&*height=([#60]|[#90])"
        "&(<img)\2\3\ssrc=([^>]++>)\4)(\5)"
Replace = "\1\2"
          " style=width:8px;height:8px;"
          " src=http://Local.ptron/bnr.png"
          " onmouseover=var&#32;bnr&#61;this.getAttribute(&quot;bnr&quot;);return((bnr&amp;&amp;bnr.length)?(this.src&#61;bnr,this.setAttribute(&quot;bnr&quot;,&quot;&quot;),this.style.width&#61;&quot;&quot;,this.style.height&#61;&quot;&quot;,true):(true))"
          " \3"
          " bnr=\4\5"
 (3)最後に次のブロックリストをAfiListとして保存で完成。(このリストは他のフィルタにも使えると思います)
# click guaranteed advertisement
([^/]++.|)googlesyndication.com[:/]
([^/]++.|)custom-click.com[:/]
([^/]++.|)adconmatch.com[:/]

# affiliate
([^/]++.|)amazon.co.jp[:/]
([^/]++.|)(afl|rd).rakuten.co.jp[:/]
([^/]++.|)a8.net[:/]
([^/]++.|)valuecommerce.com[:/]
([^/]++.|)linksynergy.com[:/]
([^/]++.|)d-064.com[:/]
([^/]++.|)accesstrade.net[:/]
([^/]++.|)trafficgate.net[:/]
([^/]++.|)bidders.co.jp[:/]
([^/]++.|)comzz.co.jp[:/]
([^/]++.|)1okunin.com[:/]
([^/]++.|)fujisan.co.jp[:/]
([^/]++.|)bannerbridge.net[:/]
([^/]++.|)leaffi.jp[:/]
([^/]++.|)bottomline.jp[:/]
([^/]++.|)ad-link.jp[:/]
([^/]++.|)a-connect.jp[:/]
([^/]++.|)asbank.net[:/]
([^/]++.|)netalliance.jp[:/]
([^/]++.|)mck081.com[:/]
([^/]++.|)aff.to[:/]
([^/]++.|)a-sobo.com[:/]
([^/]++.|)keywords.jp[:/]
([^/]++.|)masell.net[:/]
([^/]++.|)pwc.jp[:/]
([^/]++.|)linkgets.com[:/]
([^/]++.|)e-click.jp[:/]
([^/]++.|)adcommerce.jp[:/]
([^/]++.|)affiluck.com[:/]
([^/]++.|)a-easy.com[:/]
([^/]++.|)s-commerce.jp[:/]
([^/]++.|)adcp.jp[:/]
([^/]++.|)am-plus.jp[:/]
([^/]++.|)affy.net[:/]
([^/]++.|)affiligate.jp[:/]
([^/]++.|)randk2.kir.jp[:/]
([^/]++.|)afj21.jp[:/]
([^/]++.|)j-a-net.jp[:/]
([^/]++.|)a20.jp[:/]
([^/]++.|)infocart.jp[:/]
([^/]++.|)opqr.info[:/]
([^/]++.|)mopo.jp[:/]
([^/]++.|)dooga.co.jp[:/]
([^/]++.|)affpartner.com[:/]
([^/]++.|)templatemonster.co.jp[:/]
([^/]++.|)cross-a.net[:/]

# affiliate or "click guaranteed advertisement"
([^/]++.|)microad.jp[:/]
([^/]++.|)edb.jp[:/]
sbiz.jp[:/]

# adult affiliate
([^/]++.|)dtiserv2.com[:/]
([^/]++.|)medicome.co.jp[:/]
([^/]++.|)jpassport.jp[:/]
([^/]++.|)bannerbridge.net[:/]
([^/]++.|)t2z.jp[:/]
([^/]++.|)motionlink.jp[:/]
([^/]++.|)dreamcash.com[:/]
([^/]++.|)af-board.com[:/]
([^/]++.|)dmm.co.jp[:/]
([^/]++.|)dmm.com[:/]
([^/]++.|)pacificbill.com[:/]
([^/]++.|)e-nls.com[:/]
([^/]++.|)i-cute.jp[:/]

# foreign affiliate
([^/]++.|)amazon.com[:/]
([^/]++.|)clixgalore.com[:/]
[ 投稿者:うえぽん at 23:59 | proxomitron | コメント(0) | トラックバック(0) ]