HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2013
0906
seasaltVRAMを利用する処理なんですが、もっと速くできないでしょうか11解決


seasalt

リンク

2013/9/6(Fri) 23:45:20|NO.56949

衛星画像から白線(緯度経度線、国境線など)を取り除いて利用したいと思って、あれこれと試しています。
(衛星画像の参考:気象庁HP http://www.jma.go.jp/jp/gms/index.html
掲示板の過去の質問を検索すると、VRAMにアクセスしてpeek pokeを使うのが良さそうでしたので試してみました。
しかし何十枚もの画像を処理する必要があるため、もうすこし処理速度を上げられたらと思っています。
良い方法がありましたら教えてください。

実行サンプルのソース
指定されたピクセルが白線の位置かどうか参照データから判定し、白線のある位置なら、周囲のピクセルの色を使って補完して埋めています。
画像周囲に乱れが発生しますがそこは気にしません。

screen 0,300,300 title "処理前" cls 3 repeat 30 posx = rnd(200) posy = rnd(200) col = rnd(200)+150 size = rnd(200) color col,col,col circle posx,posy,posx+size,posy+size loop repeat 5 repeat 5 color 255,255,255 line cnt*60,0,cnt*65,300 line 0,cnt*60,300,cnt*60 circle 0,0,100+40*cnt,100+40*cnt,0 loop loop screen 1,300,300 title "参照データ" mref subvram,66 cls 4 repeat 5 repeat 5 color 255,255,255 line cnt*60,0,cnt*65,300 line 0,cnt*60,300,cnt*60 circle 0,0,100+40*cnt,100+40*cnt,0 loop loop screen 2,300,300 title "処理結果" mref vram,66 gmode 0 gcopy 0,0,0,300,300 time=gettime(4)*3600000+gettime(5)*60000+gettime(6)*1000+gettime(7) // 補完処理 vwidth = ( ( ginfo_winx*3 ) + 3 ) & 0xfffffffc vhigh = ginfo_winy margin = vwidth*vhigh-vwidth repeat 2 // 品質を上げるため、補完処理を2回繰り返す repeat vwidth*vhigh val = peek(subvram,cnt) if val > 200 { if ( cnt > vwidth ) && ( cnt < margin ) { val0 = peek(vram,cnt+3) val1 = peek(vram,cnt-3) tcol = ( val0 + val1 ) /2 poke vram,cnt,tcol } } loop repeat vwidth*vhigh val = peek(subvram,cnt) if val > 200 { if ( cnt > vwidth ) && ( cnt < margin ) { val0 = peek(vram,cnt+vwidth) val1 = peek(vram,cnt-vwidth) tcol = ( val0 + val1 ) /2 poke vram,cnt,tcol } } loop loop redraw 1 res(1)=(gettime(4)*3600000+gettime(5)*60000+gettime(6)*1000+gettime(7))-time title ""+res(1)+"mSecかかりました。" stop



この記事に返信する


かずまっくす

リンク

2013/9/7(Sat) 03:57:13|NO.56951

計算部分をDLLでやるのはどうだYO?



seasalt

リンク

2013/9/7(Sat) 13:02:01|NO.56955

やっぱそれしかないかYO!
VisualStudioダウンロードしたので挑戦してみようと思います。
回答ありがとうございました。



seasalt

リンク

2013/9/8(Sun) 05:35:47|NO.56993

補完処理の部分をちょっと変えたら速度が倍近く上がりました。
ピクセルをRGBすべて調べていたのをBだけで判定するようにしたのですが、やはり工夫は大事ですね。
この速度ならDLLを作る必要もなさそうです。
repeat 2 // 品質を上げるため、補完処理を2回繰り返す
repeat vwidth*vhigh/3 // repeat 回数が3分の1に vpos =cnt*3 val = peek(subvram,vpos) if val > 200 { if ( vpos > vwidth ) && ( vpos < margin ) { val0 = peek(vram,vpos+3) val1 = peek(vram,vpos-3) tcol = ( val0 + val1 ) /2 poke vram,vpos,tcol poke vram,vpos+1,tcol poke vram,vpos+2,tcol } } loop repeat vwidth*vhigh/3 vpos =cnt*3 val = peek(subvram,vpos) if val > 200 { if ( vpos > vwidth ) && ( vpos < margin ) { val0 = peek(vram,vpos+vwidth) val1 = peek(vram,vpos-vwidth) tcol = ( val0 + val1 ) /2 poke vram,vpos,tcol poke vram,vpos+1,tcol poke vram,vpos+2,tcol } } loop loop



fortunehill

リンク

2013/9/8(Sun) 07:30:54|NO.56994

/*輪郭の荒れが許容範囲なら1/2に縮小して処理したら処理速度も1/2に成ったけど(初期ルーチンで)・・・*/



seasalt

リンク

2013/9/8(Sun) 13:19:05|NO.56996

/*これは速いですね。合わせ技で処理速度が4倍近く速くなりました。
しかし、周囲の荒れは我慢できるんですが、画像全体の解像度が下がるのはなるべく避けたいんです。
1ピクセルが4〜5km四方に相当するとかそんななので。
でもこれはこれでリアルタイム処理行けそうなくらい速かったので新しい使いみちが見つかりそうです。
情報ありがとうございます。*/



pippi

リンク

2013/9/11(Wed) 00:19:26|NO.57075

解決済みなのでもう必要ないかもですが・・
細かいところで速度を稼ぐなら、変数の代入のところで一手間省けます
4〜6行目の

vpos =cnt*3 val = peek(subvram,vpos) if val > 200 {


if peek(subvram,cnt*3) > 200 {
で代入を2つ減らせます


同じように8〜10行目でも代入を2回減らせます。
また11行目〜13行目の poke で3回書き込み処理は
wpokeとpoke1回ずつで若干高速化できると思われます。



seasalt

リンク

2013/9/11(Wed) 22:09:10|NO.57091

情報をありがとうございます。
こういう事でいいのでしょうか。

val0 = peek(vram,cnt*3+3) val1 = peek(vram,cnt*3-3) tcol = ( val0 + val1 ) /2 poke vram,cnt*3,tcol wpoke vram,cnt*3+1,tcol<<8|tcol
vpos の部分は cnt*3 の計算を減らした方が速いかな?という意図だったのですが、
pippiさんのご指摘のように書き変えてみたところ若干高速になりました!
乗算するより変数参照する方がオーバーヘッドがかかるとかそういう事なんでしょうか…

最初のサンプルが平均430mSec以上かかっていたところ、150mSec台になりました。
また、実際の画像処理も、最初のルーチンでは2200mSec台でしたが現在700mSec台まで高速化出来ました。
現在最速なのはfortunehillさんの縮小法で280mSec台ですが、解像度をそのままで高速化できたのはうれしいです。
(CPU 2GHz/RAM 3GB、OS:VISTA)
DLLの方は現在勉強中なのでまだ結果が出せていません。

今後色々と応用できそうな情報をみなさんに教えて頂きました。
ありがとうございます。



fortunehill

リンク

2013/9/12(Thu) 06:40:44|NO.57096

/*もう一つ思いついた(2ドットオフセット打法1/2打法より高精度)
 念の為画像を重ねて(加減算)見ましたが殆ど違いが判りませんでした
 さらに気象庁の画像800x612で37ms(当方の環境)
 なお等高線の色は$DCDCDCで日本地図も消えてしまいましたw
*/

screen 0,800,612 title "処理前" ; picload "日本域赤外線画像a.png" time=gettime(4)*3600000+gettime(5)*60000+gettime(6)*1000+gettime(7) screen 1,800,612 :title "処理結果" gmode 0,800,612 :gcopy 0,0,0 pos 1, 1 :color $DC,$DC,$DC gmode 4,800,612,255 :gcopy 0,0,0 pos -1, 0 :gcopy 1,0,0 pos 0,-1 :gcopy 1,0,0 res(1)=(gettime(4)*3600000+gettime(5)*60000+gettime(6)*1000+gettime(7))-time title ""+res(1)+"mSecかかりました。" stop



pippi

リンク

2013/9/12(Thu) 09:45:54|NO.57097

ごめんなさい勘違いしてました
確かにcnt*3はvposに入れたほうが高速かもしれません・・
若干高速になったのはなぜなのかわかりませんが・・

ですが変数の代入はもっと減らせますよ

val0 = peek(vram,vpos+3) val1 = peek(vram,vpos-3) tcol = ( val0 + val1 ) /2


tcol = ( peek(vram,vpos+3) + peek(vram,vpos-3) ) /2



あとwpokeでは

wpoke vram,vpos+1,tcol<<8|tcol
より

wpoke vram,vpos+1,257*tcol
のが高速になるはずです。



ただもっと高速化するには抜本的なアルゴリズムの変更が必要かもです。
例えば、等高線や国境線が常に画像の中で同じ位置なら、毎フレーム参照データをpeekで参照するのは非常に無駄が多いです。
あらかじめどの位置のピクセルだけ補完すればいいか決めておけば毎フレーム1000ループくらいですむのではないでしょうか。

この場合、補完に使う参照ピクセルも、経線国境線などが乗って白くなってしまっているいわゆる使えないピクセルは、予め除外するように決めておけば完全に白っぽさがのこらずに毎フレーム綺麗に補間できます



暇人

リンク

2013/9/12(Thu) 20:31:32|NO.57104

バージョンによって変る可能性はあるけど
>乗算するより変数参照する方がオーバーヘッドがかかるとかそういう事なんでしょうか…
変数参照が5回以上あれば計算より効率が良い(4回だとぎりぎり都度計算の方が良い)
これは計算が1回の場合だが・・・

NO.56993の場合大半が

vpos =cnt*3 val = peek(subvram,vpos) if val > 200 {
ここで弾かれて参照は一回になるので効率が悪い事になる
> if peek(subvram,cnt*3) > 200 {
ってやった後にvpos =cnt*3にすれば9割り方5回参照される
でも、ここを抜けるのは数%だろうから代入しなくても大した違いは出ないが・・・



seasalt

リンク

2013/9/12(Thu) 23:25:18|NO.57111

さらなる情報をありがとうございます。

暇人さん
>変数参照が5回以上あれば計算より効率が良い
はじめて聞きました。こういう情報は探してもなかなか出てこないので貴重です。
今回は都度計算のほうが速いケースだったんですね。
ちなみに HSP のバージョンは 3.4beta を使っています。

pippiさん
>毎フレーム参照データをpeekで参照するのは非常に無駄が多いです。
おっしゃるとおりでした。
補完すべきピクセルの位置を配列に格納してからループを回したところ、70mSec 台で処理できるようになりました!
不思議なのですが、サンプルよりサイズが大きい実際の衛星画像でも 70mSec 台で線を消去できています。
(配列に格納する処理には別途 275mSec かかりました。要素数は13869でした。)
画像の質は変えずに、縮小法と同等のスピードが出せています。

fortunehillさん
/* 参照データすら…いらない…だと……? */
これは凄いですね!
画像には少しアラが残りますが、データを作る手間も含めて考えればそうとうパフォーマンスがいいのではないでしょうか!
サンプルスクリプトでは 45-98mSec とややばらつきのある結果になりましたが、実際の画像処理で威力を発揮しそうです。

ふと思いついて、一番大きな全球画像で処理を試してみました。
(全球画像:気象庁HP http://www.jma.go.jp/jp/gms/index.html?area=6
配列利用の peek poke 法だと323mSec でした。( 配列格納処理に別途 2600mSec )
2ドットオフセット打法だと 114mSec でした。


速度と手軽さを取るか、品質を取るか、かなり悩みます。
実を言うと、最初の段階では「3割くらい速くなればいいかな〜」とか思っていたのですが、すでに当初の10倍ちかい速度に達してしまいました。
もう昔には戻れない感じです。
みなさんのアドバイスのおかげです。ありがとうございます!



ONION software Copyright 1997-2023(c) All rights reserved.