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


HSPTV!掲示板


未解決 解決 停止 削除要請

2011
0524
むっしゅかむやつbuffer上の特定の1色の座標(1点)の高速検索方法は?10解決


むっしゅかむやつ

リンク

2011/5/24(Tue) 20:30:26|NO.39372

buffer上にあるフルカラーの画像から、
特定の1色の座標を高速に検索する処理を作りたいと思っています。
取得したい座標は1点で、画像の中で該当する色のdotのうち、、最も左上のピクセルです。

画像のサイズは1920*1020です。

動作するデモスクリプトと、簡単なアルゴリズムのコメント説明があると大変助かります。

よろしくお願いいたします。



この記事に返信する


Cookies

リンク

2011/5/24(Tue) 21:05:43|NO.39374

ええと、pgetよりもVRAMを直接peekした方がずっと速かった、
とどこかのブログに書いてあった気が…

実際そうです。試しました。
mrefでVRAMを変数に割り当て、頑張ればできるはず……



f3d

リンク

2011/5/24(Tue) 22:30:44|NO.39378

途中までやりました、未完成ですけど参考にしてください。
あとCookieさんのいうとおりpget使うより、vram(DIBセクション?)に書き込んだほうが早いです。
pget2とpgetを一万階回すと、
pget2 1s120m
pget 21s200m

#define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 #define pget2_setup mref vram,66 #define pget2(%1,%2) r = peek( vram, (2+ %1 *3)+( (SCREEN_HEIGHT-1- %2)*SCREEN_WIDTH*3 ) ):\ g = peek( vram, (1+ %1 *3)+( (SCREEN_HEIGHT-1- %2)*SCREEN_WIDTH*3 ) ):\ b = peek( vram, (0+ %1 *3)+( (SCREEN_HEIGHT-1- %2)*SCREEN_WIDTH*3 ) ) #define 指定した色の左上のピクセルを探す(%1,%2,%3) x = -1:y = -1:repeat SCREEN_WIDTH * SCREEN_HEIGHT :\ b = peek( vram, (0+ (cnt%SCREEN_WIDTH) *3)+( (SCREEN_HEIGHT-1- (cnt/SCREEN_WIDTH))*SCREEN_WIDTH*3 ) ):\ if(b == %3):g = peek( vram, (1+ (cnt%SCREEN_WIDTH) *3)+( (SCREEN_HEIGHT-1- (cnt/SCREEN_WIDTH))*SCREEN_WIDTH*3 ) ):\ if(g == %2):r = peek( vram, (2+ (cnt%SCREEN_WIDTH) *3)+( (SCREEN_HEIGHT-1- (cnt/SCREEN_WIDTH))*SCREEN_WIDTH*3 ) ):\ if(r == %1):if(x+y<(( (SCREEN_HEIGHT-1- (cnt/SCREEN_WIDTH))))+(cnt%SCREEN_WIDTH))):x = ( (SCREEN_HEIGHT-1- (cnt/SCREEN_WIDTH)))):\ y = (cnt/SCREEN_WIDTH))):\ loop pget2_setup//1:276 21:200 color 125,120,12 boxf 90,90,888,888 指定した色の左上のピクセルを探す 125,120,12 title ""+x+" "+y



たんす

リンク

2011/5/24(Tue) 22:33:14|NO.39379

>最も左上のピクセルです。
(2,0)と(0,2)が対象色だったとして、
どちらが”最も左上”になるのでしょうか・・・



むっしゅかむやつ

リンク

2011/5/24(Tue) 22:44:07|NO.39380

みなさんありがとうございます。vramをpeekするのがよいとのこと、参考になります。
スキルが十分でなく、vramの構造がいまいち理解できずに難航しています。。

f3dさんの方法だと1ピクセルのrgb要素を3つともpeekしているのでしょうか。
オートマトンで1色だけの評価から回していった方がいいのでしょうか。
peekとwpeekの組み合わせも気になります。(無意味?)

たんすさん、左上、という表現が正確ではありませんでした。失礼しました。
対象となるbufferには、検索対象の色が1dotだけしかないという仮定としたいと思います。



Cookies

リンク

2011/5/24(Tue) 22:53:06|NO.39382

VRAMの構造はここを。
http://hspdev-wiki.net/?%BE%AE%A5%EF%A5%B6%2FVRAM%A4%F2%C4%BE%C0%DC%C1%E0%BA%EE%A4%B7%A4%C6%A4%DF%A4%EB
左上からではなく、左下から始まります。
RGBでなく、BGRの順のようです。(自分も初知り。)

ちなみに、peekよりもlpeekしてビット演算したほうが速かったはずです。



木村

リンク

2011/5/24(Tue) 23:26:34|NO.39383

 あ〜、すみません。質問者とは別人ながらふと疑問に思った事が一つ。
 f3d様はVRAMデータを引き出す為にmref命令の66番目を利用していたわけですが、mref命令の96番目以降を利用しても同じ事ができるかもと思いました。

 Г泙困目当てウィンドウのBMSCR構造体を取得
◆続いて、,納萋世靴BMSCR構造体からお目当てウィンドウのVRAMデータへのポインタを取得
:更に、△納萋世靴燭修離櫂ぅ鵐燭dupptr命令で変数に落とし込む
ぁЛで変数化したデータを参照して検索すればOK

 と、考えて作ってみたのが以下

//ウィンドウIDからVRAMデータの入った配列数値型変数を作るソースのはず //ちなみに、VRAMデータは、1ピクセルを24bitで表現しているので注意 //定数の定義:詳しくは参考サイトを参照されたし #define TARGET_BUFFER 1 //今回の実験で調べる対象にするバッファのID #define VRAM_POINTER 5 //BMSCR構造体でVRAMへのポインタを示す配列番号 #define VRAM_SIZE 16 //単位はbyte、同構造体でVRAMのサイズを示す番号 //TARGET_BUFFERを作り、その(0,0)座標の色を(255,128,0)に定義する buffer TARGET_BUFFER, 2, 2, 0 color 128, 192, 64 pset 0, 0 color 10, 20, 40 pset 1, 0 //▲ΕンドウIDからBMSCR構造体を経て、VRAMデータにバッファのデータを入れる ウィンドウID = TARGET_BUFFER mref BMSCR構造体, 96+ウィンドウID dim VRAMデータ, BMSCR構造体(VRAM_SIZE)/4 dupptr VRAMデータ, BMSCR構造体(VRAM_POINTER), BMSCR構造体(VRAM_SIZE) //色(0),色(1),色(2)に、TARGET_BUFFERの(0,0)座標の(R,G,B)を代入する 色 = 0, 0, 0 repeat 3 memcpy 色(cnt), VRAMデータ, 1, 0, 8+(2-cnt) //何故か8byteの空白がある。この空白はバッファのサイズ次第で変動する loop //し覯未鯢充┐垢 gsel 0 mes "Buf"+TARGET_BUFFER+"の原点の色は("+色(0)+","+色(1)+","+色(2)+")" mes bmscr構造体(15) //セ温佑泙任縫蹈阿乏萄舵犬砲ける1byteの値を出してみた repeat 16 k = 0 memcpy k, VRAMデータ, 1, 0, cnt logmes "cnt="+cnt+" : "+k loop

 何故か、BMSCR構造体から取得したポインタと実態の座標がずれてしまいます。BMSCR構造体からの参照はいけない事だったのでしょうか?

 尚、BMSCR構造体の中身についてはこちらのページを参考にしました。http://dream.freespace.jp/puma/iroiro/struct/bmscr3.htm



HK2

リンク

2011/5/25(Wed) 00:55:00|NO.39384

memcpyで作ってみました。
なお、私の環境ではデータの作成に8663ms,検索に2293msかかりました。
CPUはCeleron 1.20GHz、
メモリーは504MByteです。(512MByte搭載しているのですが...)


余談ですが、
昔、違う種類のプログラムを作ったときに、
HSPで作った処理と、C++で作ったDLLで時間を比較したところ、
HSPが2秒ぐらいで処理されたものがC++のDLLでは0.03秒ぐらいで処理できました。
ちなみにそのパソコンは
CPU 550MHz メモリー 384MByteでした。


#define xsize 1920 #define ysize 1020 #uselib "winmm.dll" #func timeGetTime "timeGetTime" screen 1,xsize,ysize gsel 0,1 mes "データを作成しています。" gsel 1,0 redraw 0 timeGetTime delta=stat//開始時刻 repeat xsize x=cnt repeat ysize color rnd(255),rnd(255),rnd(255) pset x,cnt loop loop color 0,0,255 pset 100,100 timeGetTime delta=stat-delta redraw r=0 g=0 b=255 mref vram,66 gsel 0,0 title strf("データの作成に%dmsかかりました。",delta) *setting cls mes "検索する色を入力してください。(RGB)" input r,64,24 rid=stat input g,64,24 gid=stat input b,64,24 bid=stat button "検索",*search button "ランダム",*random stop *random gsel 1,0 x=rnd(xsize) y=rnd(ysize) pget x,y r=ginfo(16) g=ginfo(17) b=ginfo(18) gsel 0,0 objprm rid,r objprm gid,g objprm bid,b mes strf("この色は(%d,%d)から選択しました。",x,y) stop *search cls mes "検索中" sizeperline=3*xsize if(sizeperline&0x3){//4の倍数でないときは次の4の倍数にする。 mes "横のドット数が4の倍数でないので、次の4の倍数にします。" sizeperline=(sizeperline&fffffffc)+4 } target=b|(g<<8)|(r<<16)//色の番号 mes strf("次の色の検索を開始します。:#%06x",target) buf=0//一時変数 redraw 0 timeGetTime delta=stat//開始時刻を記録 repeat ysize offset=sizeperline*(ysize-cnt-1) y=cnt repeat xsize memcpy buf,vram,3,0,offset+cnt*3 //memcpyとlpeekではどちらの方が早いのかと思い、置き換えてみると、 //エラーになりました。 //1Byteオーバーしているのが原因のようです。 // buf=lpeek(vram,offset+cnt*3) if(buf==target){ mes strf("一致しました。(%d,%d)",cnt,y) } loop loop timeGetTime delta=stat-delta//処理時間 redraw mes "検索が終了しました。" title strf("処理時間は%dmsでした。",delta) pos 0,0 button "戻る",*setting



koju

リンク

2011/5/25(Wed) 12:00:20|NO.39385

モジュールにしてみました。
たぶん大抵は速いですが、探す色の青成分と同値の色成分が多い画面だとむっちゃ時間がかかります。


//colorで選択されている色のピクセルを探す #module #deffunc findpixel var x,var y #uselib "msvcrt.dll" #func memchr "memchr" int,int,int r=ginfo_r:g=ginfo_g:b=ginfo_b mref vram,66 sx=ginfo_sx sy=ginfo_sy lsize=(sx*3+3)&0xfffffffc vsize=lsize*sy pvram=varptr(vram) idx=0 repeat memchr pvram+idx,b,vsize-idx if stat==0:idx==-1:break idx=stat-pvram if idx\lsize\3:idx++:continue if idx\lsize/3>=sx:idx++:continue if wpeek(vram,idx+1)==(g|r<<8):break idx+=3 loop if idx==-1:x=-1:y=-1:return x=idx\lsize/3 y=sy-1-idx/lsize return #global screen 0,1920,1020 color 1,2,3 pset 10,20 findpixel x,y color mes ""+x+","+y



むっしゅかむやつ

リンク

2011/5/26(Thu) 00:32:00|NO.39387

みなさん、本当にありがとうございました。
vramを見ていくという方法が最もよいという結論に至り、
とりわけkojuさんのコードがほぼそのまま用途に合うものでした。

本件は、これにて解決とさせていただきます。



rat2

リンク

2011/5/26(Thu) 08:14:20|NO.39388

ttp://hsp.tv/play/pforum.php?mode=pastwch&num=13849

上みたいな方法を使って「指定色だけの画像」を作っておけば
条件が簡単化できるかも?



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