【问题标题】:How can I process images faster with Python?如何使用 Python 更快地处理图像?
【发布时间】:2015-06-17 07:52:59
【问题描述】:

我正在尝试编写一个脚本来检测屏幕上的 RGB 值,然后单击 x,y 值。我知道如何执行点击,但我需要比下面的代码更快地处理图像。这可以用 Python 实现吗?

到目前为止,我一次读取一行,当 x = 1920 时,我进入第二行,但完成一行大约需要 10 秒。到那时屏幕上的人会搬到一个完全不同的地方,而我只做了一行!

我可以加快这段代码的速度还是有更好的方法来实现我想要的?如果在 Python 中不可能,我愿意接受 C++ 选项 :)

import Image

x = 0
y = 0

im = Image.open("C:\Users\sean\Desktop\screen.jpg")
pix = im.load()
print im.size #get width and height of the image for iterating over
while x < 1920:
    print pix[x,y] #get RGBA value of the pixel of an image
    print "x is:" +str(x)
    x = x + 1
    print "y is: " +str(y)
    if x == 1920:
        x = 0
        y = y + 1

【问题讨论】:

  • 你可以试试opencv python wrapper?
  • 链接:OpenCV
  • “点击 x,y”是什么意思?

标签: python image image-processing rgb


【解决方案1】:

有一个叫做 pyautogui 的东西,它通常会在 1-5 秒内找到屏幕上的整个图像,这不是太快但似乎比你当前的选项更好

【讨论】:

    【解决方案2】:

    您可能想在这里做两件事之一。

    1。从图像中获取单个像素

    在这种情况下,您不需要遍历整个文件。只需使用im.getpixel。 @Daniel 提出了一个有效的观点,即这在循环中很慢,但如果您只想要一个像素,这非常有效。

    from PIL import Image
    im = Image.open('screenshot.png')
    
    im.getpixel((x, y))    # Returns the colour at (x, y)
    

    2。处理图像中的多个像素

    正如@Lukáš 建议的那样,最好使用 NumPy 来完成。例如,如果你想做一些事情,比如获取像素周围 10 x 10 网格的平均颜色。

    您可以使用 scipy.misc.fromimage 将数据作为 NumPy 数组获取

    from PIL import Image
    from scipy.misc import fromimage
    
    im = Image.open('screenshot.png')
    data = fromimage(img)
    

    让我们将获取此数据所需的时间与 for 循环进行比较。

    In [32]: pix = im.load()
    
    In [33]: %timeit fromimage(im)
    10 loops, best of 3: 8.24 ms per loops
    
    In [34]: %timeit [pix[x, y] for x in xrange(im.size[0]) for y in xrange(im.size[1])]
    1 loops, best of 3: 637 ms per loop
    

    总结一下:

    • scipy.misc.fromimage 是最快的,对于 1920x1080 的图像约为 8 毫秒
    • 循环通过pix[x, y] 大约需要 640 毫秒,大约慢 80 倍

    【讨论】:

      【解决方案3】:

      感谢您的回复,以下是我使用的代码,我没有更改我的原始代码。事实证明它足够快,但打印是一项非常昂贵的操作:) 它可以在不到一秒的时间内找到 RGB 值的 x 和 y 坐标

      #check for certain RGB in image
      
      ##need to screen grab
      
      import Image, sys
      
      x = 0
      y = 0
      
      im = Image.open('C:\\Users\\sean\\Desktop\\test.jpg')
      pix = im.load()
      print im.size #get width and height of the image for iterating over
      while x < 1914:
          value = pix[x,y] #get RGBA value of the pixel of an image
          if value == (33, 179, 80):
              #call left_click(x,y)
              print x,y
          x = x + 1
          if x == 1914:
              x = 0
              y = y + 1
      print "Finished"
      sys.exit()
      

      【讨论】:

      • 打印在默认的IDLE环境中只是一个非常昂贵的操作,在pycharm等其他工具中速度要快得多,并且在没有IDE的情况下速度最快
      【解决方案4】:

      Image.getpixel 被视为very slow。相反,请考虑使用Image.getdata。这将为您提供一个序列,其中包含您可以迭代的所有像素的数据。

      类似这样的:

      import Image
      import math
      
      x = 0
      y = 0
      
      im = Image.open("IMG_2977.JPG")
      (width, height) = im.size
      print width
      print height
      
      pix = im.getdata()
      
      i = 0
      
      for pixel in pix:
          print pixel
          x = i % ( width )
          y = math.trunc( i / width)
          print "x is: {}".format(x)
          print "y is: {}".format(y)
          i += 1
      

      在我的 MacBook Pro 上无需打印(仅将像素存储在变量中),用户时间为 2 秒(处理器时间为 0.02 秒)。

      【讨论】:

        【解决方案5】:

        通常,您希望避免 Python 中的每像素循环。他们总是很慢。要获得较快的图像处理,您需要习惯使用矩阵而不是单个像素。您基本上有两个选择,您可以使用 NumPy 或 OpenCV,或两者的组合。 NumPy 是一个通用的数学矩阵/数组库,但你可以用它做很多与图像相关的事情。如果您需要更具体的内容,OpenCV 支持对图像的许多常见操作。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-04-11
          • 1970-01-01
          • 1970-01-01
          • 2019-08-08
          • 2020-07-22
          • 2015-07-07
          • 2023-04-04
          相关资源
          最近更新 更多