|
|
2018/8/31(Fri) 22:16:31|NO.85255
個人的な興味からある種の画像処理ソフトを作っております。
いろいろ工夫してみましたが速度面の課題があります。
必要な部分だけ抽出したソースを作ってみました、適当な画像を選択すると点滅します。
うちの環境だと大きな画像(縦横1000ピクセル)で1秒程度変換時間がかかるのですが
これを劇的に早くする方法は無いでしょうか?
ルーチン内のpokeが3行あるのとか計算式は必要なものなので削れません。
screen 0,80,80
matrix=0,128,32,160,176,64,224,96,48,192,16,144,240,112,208,80
buffer 10
dialog "*",16,"画像"
filename1=refstr
gsel 10:picload filename1
picX=ginfo(26):picY=ginfo(27)
screen 9,picX,picY
buffer 1,picX,picY/2
xsize=ginfo_winx:ysize=ginfo_winy
mref vram1,66
buffer 2,picX,picY/2
mref vram2,66
gsel 1
gzoom picX,picY,10,0,0,picX,picY*2
vwidth=((xsize*3)+3)&0xFFFFFFFC
repeat
b=cnt
repeat ysize //変換描画コピールーチン
index_h=cnt*vwidth
yy=cnt
repeat xsize
index=cnt*3+index_h
a=yy\4*4+cnt\4
poke vram2,index+2,(peek(vram1,index+2)>matrix(a))*255*(b\2)
poke vram2,index+1,(peek(vram1,index+1)>matrix(a))*255*(b\2)
poke vram2,index,(peek(vram1,index)>matrix(a))*255*(b\2)
loop
loop //描画ここまで
gsel 9
gzoom picX,picY,2,0,0,xsize,ysize,0
redraw 1
await 0
loop
|
|
2018/8/31(Fri) 22:39:53|NO.85258
ちらつかせることが目的ではないですよね? ベンチマークですよね?
次のコードでベンチマーク(結果はタイトルバーにms単位で表示)を取って、その速度をどれだけ上げられるか を競えばいいんですよね?
#include "d3m.hsp"
screen 0,80,80
matrix=0,128,32,160,176,64,224,96,48,192,16,144,240,112,208,80
buffer 10
dialog "*",16,"画像"
filename1=refstr
gsel 10:picload filename1
picX=ginfo(26):picY=ginfo(27)
screen 9,picX,picY
buffer 1,picX,picY/2
xsize=ginfo_winx:ysize=ginfo_winy
mref vram1,66
buffer 2,picX,picY/2
mref vram2,66
gsel 1
gzoom picX,picY,10,0,0,picX,picY*2
vwidth=((xsize*3)+3)&0xFFFFFFFC
b=1
start=d3timer()
repeat ysize //変換描画コピールーチン
index_h=cnt*vwidth
yy=cnt
repeat xsize
index=cnt*3+index_h
a=yy\4*4+cnt\4
poke vram2,index+2,(peek(vram1,index+2)>matrix(a))*255*(b\2)
poke vram2,index+1,(peek(vram1,index+1)>matrix(a))*255*(b\2)
poke vram2,index,(peek(vram1,index)>matrix(a))*255*(b\2)
loop
loop //描画ここまで
gsel 9
gzoom picX,picY,2,0,0,xsize,ysize,0
redraw 1
await 0
title strf("%dms",d3timer()-start)
ちなみに、当方Full HDの画像で760msかかっています。ここから結果を同じに詰めることにしましょう。
|
|
2018/8/31(Fri) 22:47:42|NO.85259
ベンチマークですね。点滅目的ではないので(b\2)は無くても良いです。
vram1のRGB値をmatrix値と比較して大きければ255小さければ0としてvram2にコピーします。
実際にはmatrixR,G,Bが存在しています。
|
|
2018/8/31(Fri) 23:25:08|NO.85260
pokeをlpokeにして、3バイト分を4バイトデータとして一気に書き込むのでは駄目ですか?
4バイトデータを、インデックスを3バイトずつずらして書き込むため、
一番最後のデータを書き込む際にバッファオーバーランが出ます。
これを防止するためにバッファ2を1行余分に確保しています。
#include "d3m.hsp"
screen 0,80,80
matrix=0,128,32,160,176,64,224,96,48,192,16,144,240,112,208,80
buffer 10
dialog "*",16,"画像"
filename1=refstr
gsel 10:picload filename1
picX=ginfo(26):picY=ginfo(27)
screen 9,picX,picY
buffer 1,picX,picY/2
xsize=ginfo_winx:ysize=ginfo_winy
mref vram1,66
buffer 2,picX,picY/2+1 ;変換描画ルーチンで4バイト単位で書き込むため、冗長部分を確保
mref vram2,66
gsel 1
gzoom picX,picY,10,0,0,picX,picY*2
vwidth=((xsize*3)+3)&0xFFFFFFFC
b=1
start=d3timer()
repeat ysize //変換描画コピールーチン
index_h=cnt*vwidth
yy=cnt
repeat xsize
index=cnt*3+index_h
a=yy\4*4+cnt\4
;RGBの3バイトの情報をまとめて4バイトデータとして書き込む
lpoke vram2,index,(peek(vram1,index)>matrix(a))*255+(peek(vram1,index+1)>matrix(a))*$ff00+(peek(vram1,index+2)>matrix(a))*$ff0000
loop
loop //描画ここまで
gsel 9
gzoom picX,picY,2,0,1,xsize,ysize,0 ;冗長部分として確保した1行目を除外してコピー
redraw 1
await 0
title strf("%dms",d3timer()-start)
|
|
2018/8/31(Fri) 23:42:18|NO.85261
早速の改良ありがとうございます、11%ぐらい高速になりましたね。
メモリを多く使っても、とにかく速さが正義の認識でお願いします。
画像サイズは一応可変を許可しない予定です。
|
|
2018/8/31(Fri) 23:50:22|NO.85262
スーパー黒魔術を駆使して「多分」正しく動いてるコード。
#include "d3m.hsp"
screen 0,80,80
matrix=0,128,32,160,176,64,224,96,48,192,16,144,240,112,208,80
buffer 10
dialog "*",16,"画像"
filename1=refstr
gsel 10:picload filename1
picX=ginfo(26):picY=ginfo(27)
screen 9,picX,picY
screen 1,picX,picY/2
xsize=ginfo_winx:ysize=ginfo_winy
mref vram1,66
buffer 2,picX,picY/2
mref vram2,66
gsel 1
gzoom picX,picY/2,10,0,0,picX,picY
b=1
start=d3timer()
buffer 3,4,4
mref vram3,66
for y,0,4
for x,0,4
repeat 3
poke vram3,cnt+x*3+y*12,limit(matrix(x+y*4)+1,0,255)//なぜ1を足さねばならないか理解してない。あかん。
loop
next
next
redraw 1
buffer 4,picX,picY/2
pos 0,ysize-4
gcopy 3,0,0,4,4
box=4
repeat
pos box,ysize-4
gcopy 4,0,ysize-4,box,4
box*=2
if box>picX:break
loop
box=4
repeat
pos 0,ysize-box*2
gcopy 4,0,ysize-box,picX,box
box*=2
if box>ysize:break
loop
//ここまでで全体フィルターを生成
redraw 1
gmode 6,,,256
pos 0,0
gcopy 1,0,0,xsize,ysize//減算することで値が1以上残るピクセルをはじき出す
gmode 5,,,256
repeat 8
gcopy 4,0,0,xsize,ysize//同値加算8回で0か255の2値化が可能
loop
gsel 2
gmode 6,,,256
gcopy 4,0,0,xsize,ysize//実は反転絵を作ってたのでここで反転し規定のグラフィックを生成する
gsel 9
gzoom picX,picY,2,0,0,xsize,ysize,0
redraw 1
await 0
title strf("%dms",d3timer()-start)
黒魔術過ぎて作者もちょっと手におえてない"+1"とかあるけど、速度は 750ms→40msとかいう異次元の速度になった。
| |
|
2018/8/31(Fri) 23:51:21|NO.85263
repeat ysize 側で計算が完結するものは、ysize 側でやった方が計算量を抑えられると思うよ。
a = yy\4*4+cnt\4
など。
|
|
2018/9/1(Sat) 02:25:11|NO.85265
黒魔術の前には無意味かもしれませんが、
一応、先ほどの自分の投稿のスクリプトのループ内を極力高速化してみました。
#include "d3m.hsp"
screen 0,80,80
matrix=0,128,32,160,176,64,224,96,48,192,16,144,240,112,208,80
buffer 10
dialog "*",16,"画像"
filename1=refstr
gsel 10:picload filename1
picX=ginfo(26):picY=ginfo(27)
screen 9,picX,picY
buffer 1,picX,picY/2
xsize=ginfo_winx:ysize=ginfo_winy
mref vram1,66
buffer 2,picX,picY/2+1 ;変換描画ルーチンで4バイト単位で書き込むため、冗長部分を確保
mref vram2,66
gsel 1
gzoom picX,picY,10,0,0,picX,picY*2
vwidth=((xsize*3)+3)&0xFFFFFFFC
start=d3timer()
repeat ysize //変換描画コピールーチン
index=cnt*vwidth
yy=cnt\4*4
repeat xsize
a=matrix(yy+cnt\4)
;RGBの3バイトの情報をまとめて4バイトデータとして書き込む
lpoke vram2,index,(peek(vram1,index)>a)*$ff+(peek(vram1,index+1)>a)*$ff00+(peek(vram1,index+2)>a)*$ff0000
index+=3
loop
loop //描画ここまで
gsel 9
gzoom picX,picY,2,0,1,xsize,ysize,0 ;冗長部分として確保した1行目を除外してコピー
redraw 1
await 0
title strf("%dms",d3timer()-start)
多少は速くなりましたが、やはりアルゴリズムそのものを見直すのには敵いませんね。
|
|
2018/9/1(Sat) 16:23:15|NO.85267
ただの感想でごめんなさい。
でも言いたいんです。
みんな凄い。
|
|
2018/9/1(Sat) 22:01:51|NO.85268
ご意見改善案等ありがとうございました。
Velgariさんの黒魔術があまりに魔術過ぎて狂ったような速度が出ています。
多分今回の目的に特化した専用コードのようなので応用に悩みまして
組み込みに手間取ってしまいましたが、なんとか
RGB値とフィルター値のリアルタイム変更に追従できるようになりました。
http://fast-uploader.com/file/7091362450097/
ところで後出しで仕様を追加するようで申し訳ないのですが、実は
jpg等のブロックノイズを抑えるためbuffer1(vram1)の画像から
変換コピーする際に簡易減色をしていたのです。自分のソースでいうと
poke vram2,index+2,(peek(vram1,index+2)/BUNAKI*BUNKAI>matrix(a))*255
のように。
この部分を魔術コードで書き加える事は可能でしょうか?
buffer1をgmodeとgcopyの組み合わせで減色する方法がお手上げです。
可能であればご教示いただければ幸いです。
|
|
2018/9/1(Sat) 22:42:29|NO.85269
peek(vram1,index+2)/BUNAKI*BUNKAI
→このまま最適化するとpeek(vram1,index+2)になる(実は変数名が違うとかそういうことがなければ)
で、除算はないんだよなぁ。透過率という形なら書ける(gmode3)
ということで、
gmode 3,0,0,256/(BUNKAI*BUNKAI)を仕込んで元絵を「黒cls画面(cls 4)」上にgcopyすると、擬似的に(あくまで近似値)できるはず。
|
|
2018/9/2(Sun) 19:04:17|NO.85282
空気を読まずにコメントしますが
体験談として、画像処理させるDLLをCやC++で作って
HSPで使用するのが、一番処理が早いです。
|
|
2018/9/2(Sun) 19:24:52|NO.85283
>このまま最適化すると
HSPでは幸か不幸か最適化されないので自分はよく使っています。
a=15
b=a/16*16
mes b
stop
減色はまあこんな感じで使用目的に足りました。
#define BUN 5 //簡易減色 BUNは1〜7
buffer 10
dialog "*",16,"画像"
filename1=refstr
gsel 10:picload filename1
picX=ginfo(26):picY=ginfo(27)
screen 0,picX,picY
title"元"
gcopy 10,0,0,picX,picY
screen 1,picX,picY:color:boxf
title"減色"
tmp_i=powf(2,BUN)
gmode 5,0,0,128/tmp_i+1
repeat 2*tmp_i
gcopy 10,0,0,picX,picY
loop
redraw 1
stop
>画像処理させるDLLをCやC++で作って
まあそうでしょうね。C使いやプロの方はそうすべきと思います。
今回はHSPのみで期待以上の速度が出たので満足です。
|
|
2018/9/2(Sun) 19:30:45|NO.85284
ひとまず解決とさせていただきます。いろいろありがとうございました。
ところで、思いのほか楽しい変換ソフトになったので、
高速減色についてはほぼVelgail様(スペル間違っていて失礼しました)
作成ソースなのですが、コンテストに出してみても良いでしょうか?
|
|
2018/9/2(Sun) 22:04:39|NO.85286
私のソースは「Boost Software License - Version 1.0 - August 17th, 2003」として提供しますよ。
あ、面倒だな……って思ったかもしれないけど、利用要件は簡単。
ソースで利用した区間について、以下のライセンスが適用されていますと「ソースのコメントで」記載すれば良いのです。
他ドキュメントには一切書かなくてOK。コメントだからコンパイルすると消えるけど、「ソースコードにさえ著作権表示が残っていればよい」ということです。
ということで、以下のコード(というかコメント)をコピーしたコードの適当な場所に貼っておいてください。
そしたら、あとはどんなライセンスで(商用だろうと)提供しても構いませんよ。
/*
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
| |
|