В этом уроке я покажу вам, как быстрее захватить экран вашего компьютера с помощью многопроцессорной обработки Python в библиотеке MSS.
Приветствуем всех в части 9 нашей серии API обнаружения объектов TensorFlow. Во-первых, Вы можете скачать код на моей странице GitHub. Этот урок будет немного отличаться от предыдущих уроков.
В 8-й части мне сказали, что я буду работать с многопроцессорностью Python, чтобы заставить код работать параллельно с другими процессами. Поэтому я часами учился использовать многопроцессорность (раньше я ее не использовал).
Поэтому я скопировал весь код из моего второго урока и удалил функции screen_recordPIL
и screen_grab
. Осталось только поработать с функцией screen_recordMSS
. Эту функцию мы можем разделить на две части, где мы захватываем экран и где мы показываем наш захваченный экран. Это означает, что нам нужно будет создать два процесса.
Сначала я делю весь код на две части; первую часть мы назовем GRABMSS_screen. Затем нам нужно поместить весь код в цикл while, чтобы запускать его снова и снова. Когда у нас есть наш экран, мы вызываем команду q.put_nowait(img)
, в которой мы помещаем наше изображение в общую очередь, и следующей строкой q.join()
мы говорим «подождите, так как изображение будет скопировано в очередь».
def GRABMSS_screen(q):
while True:
# Get raw pixels from the screen, save it to a Numpy array
img = numpy.array(sct.grab(monitor))
# To get real color we do this:
#img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
q.put_nowait(img)
q.join()
Вторую функцию мы назовем SHOWMSS_screen. После этого делаем то же самое, что и раньше, показывая захваченное изображение и измеряя FPS. Эта функция также будет выполняться в цикле while, и мы всегда проверяем, не пуста ли наша очередь. Когда у нас есть что-то в очереди, мы вызываем команду q.get_nowait()
, которая забирает все из очереди, а с помощью q.task_done()
мы блокируем процесс, чтобы не прерывать очередь, если мы не закончили забирать все данные.
def SHOWMSS_screen(q):
global fps, start_time
while True:
if not q.empty():
img = q.get_nowait()
q.task_done()
# To get real color we do this:
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# Display the picture
cv2.imshow(title, cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
# Display the picture in grayscale
fps+=1
TIME = time.time() - start_time
if (TIME) >= display_time :
print("FPS: ", fps / (TIME))
fps = 0
start_time = time.time()
# Press "q" to quit
if cv2.waitKey(25) & 0xFF == ord("q"):
cv2.destroyAllWindows()
break
Прямо сейчас у нас есть две разные функции, и мы будем использовать их в параллельных процессах.
Если мы хотим запустить наш код в многопроцессорном режиме, мы должны начать наш код с if name=="main":
и запустить скрипт Python из командной строки; в противном случае, если мы запустим его из оболочки Python, мы не получим никаких отпечатков, необходимых здесь для измерения FPS. Итак, наша полная третья часть кода выглядит так:
if __name__=="__main__":
# Queue
q = multiprocessing.JoinableQueue()
# creating new processes
p1 = multiprocessing.Process(target=GRABMSS_screen, args=(q, ))
p2 = multiprocessing.Process(target=SHOWMSS_screen, args=(q, ))
# starting our processes
p1.start()
p2.start()
Подробнее о многопроцессорности и очередях в Python вы можете узнать по этой ссылке. Объяснение шорткода: мы начинаем с создания очереди chared.
# Queue
q = multiprocessing.JoinableQueue()
Мы создаем процессы p1 и p2 со следующими строками, которые будут работать в фоновом режиме. Функция p1 вызовет функцию GRABMSS_screen(), а p2 вызовет функцию SHOWMSS_screen(). В качестве аргумента для этих функций мы должны привести аргументы, мы даем там q.
# creating new processes
p1 = multiprocessing.Process(target=GRABMSS_screen, args=(q, ))
p2 = multiprocessing.Process(target=SHOWMSS_screen, args=(q, ))
Последний шаг — запустить наши процессы. После этих команд наша функция захвата экрана будет работать в фоновом режиме.
# starting our processes
p1.start()
p2.start()
Для сравнения, я запускал старый код без многопроцессорности и с многопроцессорностью. Вот результаты без многопроцессорности:
Мы видим, что среднее значение составляет около 19–20 FPS. Вот результаты с многопроцессорной обработкой:
Захват экрана с многопроцессорными конвейерами
Обновлено Рокасом Балсисом 18 декабря 2018 г.
Вот аналогичный код, в котором я использую многопроцессорные каналы для связи «один к одному» между процессами:
import multiprocessing
from multiprocessing import Pipe
import time
import cv2
import mss
import numpy as np
import datetime
title = "FPS benchmark"
start_time = time.time()
display_time = 2 # displays the frame rate every 2 second
fps = 0
sct = mss.mss()
# Set monitor size to capture
monitor = {"top": 40, "left": 0, "width": 800, "height": 640}
def GRABMSS_screen(p_input):
while True:
#Grab screen image
img = np.array(sct.grab(monitor))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# Put image from pipe
p_input.send(img)
def SHOWMSS_screen(p_output):
global fps, start_time
while True:
# Get image from pipe
img = p_output.recv()
# Display the picture
cv2.imshow(title, img)
# Calculate FPS
fps+=1
TIME = time.time() - start_time
if (TIME) >= display_time :
print("FPS: ", fps / (TIME))
fps = 0
start_time = time.time()
# Press "q" to quit
if cv2.waitKey(25) & 0xFF == ord("q"):
cv2.destroyAllWindows()
break
if __name__=="__main__":
# Pipes
p_output, p_input = Pipe()
# creating new processes
p1 = multiprocessing.Process(target=GRABMSS_screen, args=(p_input,))
p2 = multiprocessing.Process(target=SHOWMSS_screen, args=(p_output,))
# starting our processes
p1.start()
p2.start()
Мы видим, что среднее значение составляет около 32 кадров в секунду. Таким образом, наш окончательный результат заключается в том, что наш экран захвата улучшился примерно на 50%. Я хочу улучшить его еще больше, но у меня пока нет идей, как это сделать. Во всяком случае, результаты намного лучше, чем раньше! Далее я попытаюсь интегрировать это с кодом обнаружения объектов CSGO.
Первоначально опубликовано на https://pylessons.com/Tensorflow-object-detection-grab-screen-multiprocessing
Больше контента на plainenglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Получите эксклюзивный доступ к возможностям написания и советам в нашем сообществе Discord.