Как прочитать все пиксели экрана в массиве питона с частотой 60 кадров в секунду +

1

Первый раз задаем вопрос о SO.

Я пытаюсь найти быстрый способ чтения экрана в реальном времени (60fps+). Скриншот для numpy - быстрый метод, но не соответствует этой скорости. В этом вопросе есть блестящий ответ для пикселей: Самый эффективный/быстрый способ анализа данных с помощью Python?

Я попытался изменить GetPixel на эту длинную форму для BMP, но это уменьшает ее до 5 кадров в секунду:

t1 = time.time()
count = 0

width = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN)
height = win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN)
left = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN)
top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN)
while count < 1000:
    hwin = win32gui.GetDesktopWindow()
    hwindc = win32gui.GetWindowDC(hwin)
    srcdc = win32ui.CreateDCFromHandle(hwindc)

    memdc = srcdc.CreateCompatibleDC()

    bmp = win32ui.CreateBitmap()
    bmp.CreateCompatibleBitmap(srcdc, width, height)
    memdc.SelectObject(bmp)

    memdc.BitBlt((0, 0), (width, height), srcdc, (left, top), win32con.SRCCOPY)
    bmpinfo = bmp.GetInfo()
    bmpInt = bmp.GetBitmapBits(False)

    count +=1
t2 = time.time()
tf = t2-t1
it_per_sec = int(count/tf)
print (str(it_per_sec) + " iterations per second")

Я смотрел видео с youtube парня, работающего на С#, где он сказал, что GetPixel открывает и закрывает память, и поэтому использование GetPixel для каждого отдельного пикселя имеет много накладных расходов. Он предложил заблокировать все поле данных и только затем сделать getpixel. Я не знаю, как это сделать, поэтому любая помощь будет оценена по достоинству. (EDIT: эта ссылка может ссылаться на Небезопасную обработку изображений на Python, например LockBits в С#)

Существует также другой метод, который получает адрес памяти растрового изображения, но я не знаю, что с ним делать. Логика заключается в том, что я должен иметь возможность считывать память из этой точки в любой массив numpy, но я не смог этого сделать.

Также будет оценена любая другая возможность быстро прочитать экран.

Должен быть какой-то способ, GPU знает, какие пиксели рисовать в каждом месте, это означает, что в нем должен быть какой-то банк памяти или поток данных, к которому мы можем подключиться.

PS почему требуется высокая скорость? Я работаю над инструментами автоматизации работы, у которых много накладных расходов, и я надеюсь оптимизировать поток данных экрана, чтобы помочь этой части проекта.

  • 0
    Вам, вероятно, понадобится сотрудничество с графическим оборудованием, чтобы сделать это в C, а затем написать привязки к Python, чтобы позволить ему получить доступ к захваченному потоку. NVIDIA Capture SDK может стать местом для поиска.
  • 0
    Как работают потоковые программы? У них есть какой-то доступ к нему, верно? Я попытаюсь проверить NVIDIA SDK, но хотелось бы, чтобы он был более универсальным, чтобы я мог попробовать его на своем интегрированном ноутбуке Intel.
Показать ещё 1 комментарий
Теги:
performance
winapi
frame-rate
screen

1 ответ

0

В приведенном ниже коде используется MSS, который, если он изменен, чтобы показать отсутствие выхода, может достигать 44fps для 1080p. https://python-mss.readthedocs.io/examples.html#opencv-numpy

import time

import cv2
import mss
import numpy


with mss.mss() as sct:
    # Part of the screen to capture
    monitor = {'top': 40, 'left': 0, 'width': 800, 'height': 640}

    while 'Screen capturing':
        last_time = time.time()

        # Get raw pixels from the screen, save it to a Numpy array
        img = numpy.array(sct.grab(monitor))

        # Display the picture
        #cv2.imshow('OpenCV/Numpy normal', img)

        # Display the picture in grayscale
        # cv2.imshow('OpenCV/Numpy grayscale',
        #            cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY))

        print('fps: {0}'.format(1 / (time.time()-last_time)))

        # Press "q" to quit
        if cv2.waitKey(25) & 0xFF == ord('q'):
            cv2.destroyAllWindows()
            break

Все еще не идеально, хотя, как это не 60fps+, и использование необработанного переупакованного буфера с графического процессора было бы лучшим решением, если это было возможно.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню