2015-11-28 21 views
0

我刚刚开发了一个用于使用Python捕获屏幕并分析流光溢彩的数据的小脚本。它已经工作,但我有一些性能问题:用于流光溢彩的Python屏幕截图(较少资源密集型)

  • 我的脚本需要大约25%-50%的CPU资源,同时观看YouTube视频(酷睿i5-2410M当前的FullHD @,脚本应为i7-6670k @ 4K优化(我的新电脑))
  • 我能够捕捉大约11 fps,这对于流光溢彩来说足够了,但是如果我能够更快地拍摄,我可以在拍摄之间放置延迟并减少资源
  • 只有主监视器被捕获,如果我可以选择,会很好。

我的脚本:

import time 
import asyncio 
import websockets 
from PIL import ImageGrab 
from PIL import ImageStat 
from PIL import ImageEnhance 

# Analyzing the image and deleting black borders from movies (21:9 or 4:3) 
def analyze_borders(debug=False): 
    min_size = 3 
    im = ImageGrab.grab() 
    width, height = im.size 
    box = [] 
    for x in range(0, height): 
     # check top 
     line = im.crop((0, x, width, x + 1)) 
     if debug: 
      print("TOP", ImageStat.Stat(line).median) 
     if ImageStat.Stat(line).median > [1, 1, 1]: 
      box.append(x) 
      break 
     if x >= height/min_size: 
      box.append(int(height/min_size)) 
      break 
    for x in range(height, 0, -1): 
     # check bottom 
     line = im.crop((0, x, width, x + 1)) 
     if debug: 
      print("BOTTOM", ImageStat.Stat(line).median) 
     if ImageStat.Stat(line).median > [1, 1, 1]: 
      box.append(height - x - 1) 
      break 
     if x <= height/min_size: 
      box.append(int(height/min_size)) 
      break 
    for x in range(0, width): 
     # check left 
     line = im.crop((x, 0, x + 1, height)) 
     if debug: 
      print("LEFT", ImageStat.Stat(line).median) 
     if ImageStat.Stat(line).median > [1, 1, 1]: 
      box.append(x) 
      break 
     if x >= width/min_size: 
      box.append(int(width/min_size)) 
      break 
    for x in range(width, 0, -1): 
     # check right 
     line = im.crop((x, 0, x + 1, height)) 
     if debug: 
      print("RIGHT", ImageStat.Stat(line).median) 
     if ImageStat.Stat(line).median > [1, 1, 1]: 
      box.append(width - x - 1) 
      break 
     if x <= width/min_size: 
      box.append(int(width/min_size)) 
      break 
    return box 


def capture(): 
    return ImageGrab.grab() 


@asyncio.coroutine 
def start(): 
    time1 = time.time() 
    websocket = yield from websockets.connect('ws://localhost:8887/') 
    for x in range(0, 1000): 
     im = capture() 
     im = ImageEnhance.Color(im).enhance(1) 
     im = ImageEnhance.Contrast(im).enhance(1) 
     box = [0, 0, 0, 0] 
     if x % 100 == 0: 
      box = analyze_borders() 
      print(box) 
     w, h = im.size 
     im = im.crop((box[2], box[0], w - box[3], h - box[1])) 
     w, h = im.size 
     im1 = im.crop((0, 0, int(w/2), h)) 
     im2 = im.crop((int(w/2), 0, w, h)) 
     stat1 = ImageStat.Stat(im1) 
     stat2 = ImageStat.Stat(im2) 
     # print(str(x) + " Median1: " + str(stat1.median)) 
     # print(str(x) + " Median2: " + str(stat2.median)) 
     yield from websocket.send(str("C1:(" + str(stat1.median[0]) + 
             ", " + str(stat1.median[1]) + 
             ", " + str(stat1.median[2]) + ")")) 
     yield from websocket.send(str("C2:(" + str(stat2.median[0]) + 
             ", " + str(stat2.median[1]) + 
             ", " + str(stat2.median[2]) + ")")) 
    yield from websocket.close() 
    duration = time.time() - time1 
    print(str(duration)) 
    print(str(1000/duration)) 


asyncio.get_event_loop().run_until_complete(start()) 

WebSocket的部分是因为我的LED条纹被连接到其接收消息的树莓派。可能会有一些性能优化,但我认为主要问题在PIL中。

我发现了这样的回答:https://stackoverflow.com/a/23155761/5481935

我觉得这是最好的方法,但我不明白我怎么能捕捉整个屏幕win32ui它裁剪成几部分,因为我刚刚与蟒蛇开始。目前我只是裁剪两个部分,但只要我的屏幕背后安装了数字LED条纹,我将捕捉更多的部分。

谢谢来自德国, 约翰内斯

编辑:我觉得最优化,可以为拍摄方法。此外,我认为我上面链接的答案是非常好的,但我不明白如何将上面的答案与我的代码连接起来:那么如何使用win32ui捕获整个屏幕并处理结果,如在我的代码中或将其转换到PIL图像?

+0

由于您不需要完整的解决方案,因此您可能可以使用[DWM缩略图](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969541.aspx) 。这是更轻量级的,因为a)它们已经存在,并且b)您不需要传输整个窗口的位图。 – IInspectable

+0

@IInspectable但我想捕捉整个屏幕,而不是一个窗口 – jhns

回答

0

PIL已经实现了analyze_borders类似的功能:getbbox。使用它可以获得更好的性能,因为遍历行中的图像列&会很慢。

您可能还想将PIL图像转换为numpy二维数组。可以用各种方式轻松分析数组。例如,要计算所有行的中值像素值,您只需执行numpy.median(img, axis=1)即可。

+0

getbbox()很棒!但我试过numpy,只有PIL的一半。 – jhns

+0

这是预期的。 - 'getbbox()'在扩展模块(C API)中实现,不必计算每行的中位数。如果你想做精美的图像分析,我建议'numpy'阵列。 –