Более быстрый способ чтения пикселя экрана в Python, чем PIL?

В настоящее время я использую считыватель пикселей через AutoItv3 для выполнения некоторых действий в программе, которая запускает прямой X; Игра. Сейчас программа работает нормально, но в качестве упражнения я переписывал ее в python. Сейчас я могу сделать:

import ImageGrab # Part of PIL image = ImageGrab.grab() #Define an area to capture. rgb = image.getpixel((1, 90)) #What pixel do we want? 

И это захватывает информацию о пикселях, которую я хочу просто отлично, но я делаю это довольно быстро (нужно делать 3 раза в секунду или быстрее), но в результате это существенно влияет на частоту кадров в этой игре на основе DirectX.

Есть ли более быстрый способ в Python читать определенный пиксель экрана? Даже ограничение этого на запуск каждые 0,3 секунды вызывает больше напряжения, чем это действительно должно (я действительно полагал, что python будет быстрее, чем AutoIt для этой конкретной цели, следовательно, причина, по которой я его пытаюсь)

4 Solutions collect form web for “Более быстрый способ чтения пикселя экрана в Python, чем PIL?”

Это источник видеоэкрана PIL, он не принимает никаких параметров и захватывает весь экран и преобразует его в растровое изображение.

 PyImaging_GrabScreenWin32(PyObject* self, PyObject* args) { int width, height; HBITMAP bitmap; BITMAPCOREHEADER core; HDC screen, screen_copy; PyObject* buffer; /* step 1: create a memory DC large enough to hold the entire screen */ screen = CreateDC(";DISPLAY", NULL, NULL, NULL); screen_copy = CreateCompatibleDC(screen); width = GetDeviceCaps(screen, HORZRES); height = GetDeviceCaps(screen, VERTRES); bitmap = CreateCompatibleBitmap(screen, width, height); if (!bitmap) goto error; if (!SelectObject(screen_copy, bitmap)) goto error; /* step 2: copy bits into memory DC bitmap */ if (!BitBlt(screen_copy, 0, 0, width, height, screen, 0, 0, SRCCOPY)) goto error; /* step 3: extract bits from bitmap */ buffer = PyString_FromStringAndSize(NULL, height * ((width*3 + 3) & -4)); if (!buffer) return NULL; core.bcSize = sizeof(core); core.bcWidth = width; core.bcHeight = height; core.bcPlanes = 1; core.bcBitCount = 24; if (!GetDIBits(screen_copy, bitmap, 0, height, PyString_AS_STRING(buffer), (BITMAPINFO*) &core, DIB_RGB_COLORS)) goto error; DeleteObject(bitmap); DeleteDC(screen_copy); DeleteDC(screen); return Py_BuildValue("(ii)N", width, height, buffer); error: PyErr_SetString(PyExc_IOError, "screen grab failed"); DeleteDC(screen_copy); DeleteDC(screen); return NULL; } 

Итак, когда я просто немного углубился, нашел подход C хорошим

http://msdn.microsoft.com/en-us/library/dd144909(VS.85).aspx

И у Python есть ctypes, так вот мой подход с использованием ctypes

 >>> from ctypes import * >>> user= windll.LoadLibrary("c:\\winnt\\system32\\user32.dll") #I am in windows 2000, may be yours will be windows >>> h = user.GetDC(0) >>> gdi= windll.LoadLibrary("c:\\winnt\\system32\\gdi32.dll") >>> gdi.GetPixel(h,1023,767) 16777215 #I believe its white color of RGB or BGR value, #FFFFFF (according to msdn it should be RGB) >>> gdi.GetPixel(h,1024,767) -1 #because my screen is only 1024x768 

Вы можете написать оболочку для функции GetPixel, как это

 from ctypes import windll dc= windll.user32.GetDC(0) def getpixel(x,y): return windll.gdi32.GetPixel(dc,x,y) 

Затем вы можете использовать как getpixel(0,0) , getpixel(100,0) и т. Д. …

PS: Mine – это Windows 2000, поэтому я помещаю winnt в путь, вам может потребоваться изменить его на windows иначе вы можете полностью удалить путь, просто используйте user32.dll и gdi32.dll .

Комментарий к решению S.Mark: библиотека user32 уже загружена windll в windll.user32, поэтому вместо строки dc = … вы можете сделать:

 def getpixel(x,y): return gdi.GetPixel(windll.user32.GetDC(0),x,y) 

… или предпочтительно:

 dc= windll.user32.GetDC(0) 

Вы могли бы сделать это через SDL (?). Основываясь на этом вопросе , SDL может получить доступ к экрану. И он имеет привязки python.

Может быть стоит сделать снимок? Если бы это сработало, это, безусловно, было бы быстрее, чем полный захват экрана в PIL.

Это старый вопрос, но он очень сильно оценивает Google при поиске методов захвата экрана Python, поэтому я думаю, что было бы полезно упомянуть, что модуль ImageGrab теперь поддерживает захват области экрана:

 PIL.ImageGrab.grab(bbox=None) Parameters: bbox – What region to copy. Default is the entire screen. Returns: An image 

http://pillow.readthedocs.io/en/3.1.x/reference/ImageGrab.html

Расширяя область действия, теперь есть замена ImageGrab, называемая pyscreenshot, которая также сохраняет часть экрана на изображении PIL / Pillow. Этот модуль также работает на Linux, в отличие от ImageGrab, который является только Windows и OS X.

 import pyscreenshot as ImageGrab im=ImageGrab.grab(bbox=(10,10,510,510)) # X1,Y1,X2,Y2 im.show() 

https://pypi.python.org/pypi/pyscreenshot

  • Обозначение Shebang: скрипты Python для Windows и Linux?
  • Как активировать среду conda в jenkins build
  • Каков правильный способ использования win32inet.WinHttpGetProxyForUrl
  • Не удается запустить python в терминале git?
  • охват замороженного исполняемого файла
  • Изменение кодировки Windows cmd вызывает сбой Python
  • Построение LLVM завершается с пустым сообщением об ошибке
  • Как я могу найти процесс по имени и убить с помощью ctypes?
  •  
    Interesting Posts for Van-Lav
    Python - лучший язык программирования в мире.