画面の周囲を囲む長方形の平均色を返す簡単なPythonスクリプトを作成しました。(ここでの最終目標は、モニターの周囲にRGB LEDストリップを配置して、映画の中で光る効果を出すことです。このように(youtube)ですが、自分で作成しているのでもっと楽しくなります)。
私は現在、画面をビットマップ( "screenshot")として取得し、各ピクセル値を取得し、RGB<->HEX変換を行うためにautopyを使用しています。
簡略化されたバージョン:
step = 1
width = 5
height = 5
b = autopy.bitmap.capture_screen()
for block in border_block(width, height): # for each rectangle around the perimeter of my screen
R,G,B = 0,0,0
count = 0
for x in xrange(block.x_min, block.x_max, step):
for y in xrange(block.y_min, block.y_max, step):
r,g,b = autopy.color.hex_to_rgb(image.get_color(x, y))
R += r; G += g; B += b
count += 1
block.colour = "#{:06x}".format(autopy.color.rgb_to_hex(R/count,G/count,B/count))
matplotlib
次に、 :(これは5x5ブロックとして構成され、ステップ= 1)を使用してブロックを表示します。
問題は、実装の速度です。これは、ブロック内の各ピクセル(2560*1600解像度/5= 320 *512ブロック=163,840ピクセル/ブロック)、および周囲の各ブロック(16 * 163,840 = 2,621,440ループ)でループしているためです。 )。全体として、これは完了するのに2.814秒かかりました。
ステップ値を増やすと、速度は上がりますが、十分ではありません:(これは境界を囲むより現実的な15x10ブロックを使用しています)
Step Time (s)
1 1.35099983215
2 0.431000232697
5 0.137000083923
10 0.0980000495911
15 0.095999956131
20 0.0839998722076
50 0.0759999752045
これは、スクリーンショット自体に約0.070秒かかるためです。これは、12.8FPSに制限されていることを意味します。
>>> timeit.Timer("autopy.bitmap.capture_screen()", "import autopy").timeit(100)/100
0.06874468830306966
質問:
スクリーンショットを撮り、画面の領域を平均化するより速い方法はありますか?
精度についてはあまり心配していませんが、シリアル伝送のオーバーヘッドを考慮して、これらの値を約30 FPS、理想的にはより高速(20〜30ミリ秒)で返すことができるようにしたいと考えています。私の画面解像度は2560*1600であることを覚えておいてください!
Python Imaging Library(PIL)について聞いたことがありますが、関数の速度を調べる時間が
ImageGrab
まだありませんが、有望に見えます。GPUから直接ピクセル値を読み取ることはできますか?
別の考え-映画の上端/下端を検出するための最良の方法は何ですか?(アスペクト比がワイドスクリーンの場合、スクリーンショットの上下に黒いバーがあり、一部の長方形は黒いです)。
PILのgrab()の使用:
>>> timeit.Timer("ImageGrab.grab()", "from PIL import ImageGrab").timeit(100)/100
0.1099840205312789
PIL-サイズ変更:(ChristopheD)
>>> timeit.Timer("PIL.ImageGrab.grab().resize((15, 10), PIL.Image.NEAREST)", "import PIL").timeit(100)/100
0.1028043677442085
>>> timeit.Timer("PIL.ImageGrab.grab().resize((15, 10), PIL.Image.ANTIALIAS)", "import PIL").timeit(100)/100
0.3267692217886088
注:これは上記で得られた結果よりも改善されていますが、9 FPS、または完全なアンチエイリアシングを使用した3FPSに制限されています。
PIL-最も近く、サイズを変更:(マークランサム)
>>> for step in [1,2,5,10,15,20,50]:
print step, timeit.Timer("PIL.ImageGrab.grab().resize(("+str(2560/step)+", "+str(1600/step)+"), PIL.Image.NEAREST).resize((15, 10), PIL.Image.ANTIALIAS)", "import PIL.ImageGrab").timeit(100)/100
結果:
Step Time(s)
1 0.333048412226
2 0.16206895716
5 0.117172371393
10 0.102383282629
15 0.101844097599
20 0.101229094581
50 0.100824552193
手動で上部をループするよりもはるかに高速autopy
ですが、それでも最大9 FPSに制限されています(「ステップ」10)。
注:これには、必要なRGBからHEXへの変換は含まれていません
誰かがより速い方法を思い付くことができますか?つまり、部分的なスクリーンショットを撮ることができますか?Cで何か書くべきですか?