|
|
|
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?
|
|
2013/9/7(Sat) 13:02:01|NO.56955
やっぱそれしかないかYO!
VisualStudioダウンロードしたので挑戦してみようと思います。
回答ありがとうございました。
|
|
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
|
|
2013/9/8(Sun) 07:30:54|NO.56994
/*輪郭の荒れが許容範囲なら1/2に縮小して処理したら処理速度も1/2に成ったけど(初期ルーチンで)・・・*/
|
|
2013/9/8(Sun) 13:19:05|NO.56996
/*これは速いですね。合わせ技で処理速度が4倍近く速くなりました。
しかし、周囲の荒れは我慢できるんですが、画像全体の解像度が下がるのはなるべく避けたいんです。
1ピクセルが4〜5km四方に相当するとかそんななので。
でもこれはこれでリアルタイム処理行けそうなくらい速かったので新しい使いみちが見つかりそうです。
情報ありがとうございます。*/
|
|
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回ずつで若干高速化できると思われます。
|
|
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の方は現在勉強中なのでまだ結果が出せていません。
今後色々と応用できそうな情報をみなさんに教えて頂きました。
ありがとうございます。
|
|
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
|
|
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回参照される
でも、ここを抜けるのは数%だろうから代入しなくても大した違いは出ないが・・・
|
|
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倍ちかい速度に達してしまいました。
もう昔には戻れない感じです。
みなさんのアドバイスのおかげです。ありがとうございます!
|
|