矩形截图彩色求平均值 [英] Screenshot colour averaging of rectangles

查看:253
本文介绍了矩形截图彩色求平均值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个快速的Python脚本返回围绕我的屏幕的周边矩形的平均颜色。 (这里的最终目标是让的RGB LED条周边我的显示器,用于在电影的发光效果 - 如这(YouTube)的,但更多的乐趣,因为我在做我自己)。

I wrote a quick python script to return the average colour of rectangles surrounding the perimeter of my screen. (The end goal here is to have RGB LED strips surrounding my monitor, for a glowing effect during movies - like this (youtube), but more fun because I'm making it myself).

我目前使用 autopy 获取屏幕作为位图(截图),获取每个像素值,和RGB&下; - > HEX转换。

I'm currently using autopy for getting the screen as a bitmap ("screenshot"), getting each pixel value, and the RGB <-> HEX conversions.

简体版:

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 :(此配置为5×5块,步= 1)

I then display the blocks using matplotlib: (this is configured as 5x5 blocks, step = 1)

的问题是执行的速度 - 因为这是在一个块循环对每一个像素(2560×1600分辨率/ 5 = 320 * 512块每块= 163,840个像素),并在周边的每个块(16 * 163,840 = 2621440循环)。总体来说,这款拍拍2.814s来完成。

The problem is the speed of implementation - because this is looping for each pixel in a block (2560*1600 resolution/5 = 320*512 block = 163,840 pixels per block), and each block around the perimeter (16*163,840 = 2,621,440 loops). Overall, this took took 2.814s to complete.

如果我增加了步长值,它的速度,但没有足够的:(这是使用周围的边界更加逼真的15×10块)

If I increase the step value, it speeds up, but not enough: (this is using a more realistic 15x10 blocks surrounding the border)

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.070s - 这意味着我仅限于12.8 FPS。

That's because the screenshot itself takes approx 0.070s - this means that I'm limited to 12.8 FPS.

>>> timeit.Timer("autopy.bitmap.capture_screen()", "import autopy").timeit(100)/100
0.06874468830306966

问题:


  • 是否有采取截图和平均屏幕区域更快的方法?

  • Is there a faster method of taking a screenshot and averaging regions of the screen?

我不是太担心的准确性,但希望能够返回这些值在约30 FPS,最好快(20-30毫秒),允许串行传输的开销。记住我的屏幕分辨率为2560 * 1600!

I'm not too worried about accuracy, but would like to be able to return these values at approx 30 FPS, ideally faster (20-30 ms) to allow for serial transmission overhead. Bear in mind my screen resolution is 2560*1600!

我听说过 Python图像库(PIL),但还没有时间寻找到的 ImageGrab 函数的速度还,但它看起来很有希望。

I've heard about Python Imaging Library (PIL), but haven't had time to look into the speed of the ImageGrab function yet, but it looks promising.

我可以直接从GPU读取像素值?

Can I read pixel values directly from the GPU?

另一种思考 - 什么是检测电影的顶部/底部边缘的最佳方式? (如果宽高比宽屏,还有顶部/黑条截图底部,一些矩形是黑色)。

Another thought - what's the best way to detect the top/bottom edge of a movie? (If aspect ratio is widescreen, there are black bars at top/bottom of screenshot, and some rectangles are black).

使用PIL的抢()

>>> timeit.Timer("ImageGrab.grab()", "from PIL import ImageGrab").timeit(100)/100
0.1099840205312789


PIL - 调整:(ChristopheD)


PIL - resize: (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,或3 FPS全抗锯齿。

Note: This is an improvement over the results obtained above, but we're still limited to 9 FPS, or 3 FPS with full anti-aliasing.

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步)。

Much faster than manually looping with autopy at top, but we're still limited to ~9 FPS (at a 'step' of 10).

请注意:这并不包括RGB到所需的十六进制转换

Note: This doesn't include the RGB to HEX conversion required

任何人都可以想出一个更快的方法 - 即以部分屏幕截图?我应该写的东西用C?

Can anyone come up with a faster method - i.e. taking a partial screenshot? Should I write something in C?

推荐答案

使用Python的图像库。从文档(图像模块中)

Use the Python Imaging Library. From the docs (in the Image module):

getcolors

im.getcolors()=>列表(计数,颜色)元组或无

im.getcolors() => a list of (count, color) tuples or None

im.getcolors(maxcolors)=>的(计数,颜色)元组或无

im.getcolors(maxcolors) => a list of (count, color) tuples or None

(新中1.1.5)返回(计数,颜色)的元组,其中该计数是在图像中出现的相应的颜色的次数未排序列表

(New in 1.1.5) Returns an unsorted list of (count, color) tuples, where the count is the number of times the corresponding color occurs in the image.

图片模块还包含一个作物()方法,你可以用它来获得每个矩形插到getcolors()。您可以轻松地从一个加权平均值。

The Image module also contains a crop() method you can use to get each rectangle to plug into getcolors(). You can take a weighted average from that easily.

这应该比蟒蛇手动运行循环快得多。我不知道这是否是足够快的实时使用,但你会得到一个显着的速度提升。您也可以采取截图每秒几次,因为赔率是,以60 fps的LED灯发出信号对10 FPS不会特别明显。不要看它作为限12.8 FPS,把它看成只能更新一次的LED每5帧,这不应该是一个明显的区别。

It should be much faster than running the loop manually in python. I'm not sure if it's fast enough to use in real time, but you will get a dramatic speed boost. You could also take the screenshot a few times per second, since odds are that sending signals to the LEDs at 60 fps vs 10 fps won't be particularly noticeable. Don't look at it as "limited to 12.8 FPS", look at it as "can only update the LEDs once every 5 frames", which shouldn't be a noticeable difference.

编辑:如果你的真正的兴趣在这里进一步的优化,我想你会发现<一个href=\"http://stackoverflow.com/questions/3586046/fastest-way-to-take-a-screenshot-with-python-on-windows\">Fastest的方式,采取与Python截图在Windows 非常有用。

If you're really interested in further optimization here, I think you'll find Fastest way to take a screenshot with python on windows quite helpful.

这篇关于矩形截图彩色求平均值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆