Как реализовать неблокирующий бесконечный цикл в Python - PullRequest
0 голосов
/ 19 февраля 2019

У меня есть бесконечный цикл, который читает видеокадры с веб-камеры, и каждый кадр выполняет сложную функцию, требующую высокой вычислительной мощности.Таким образом, при отображении кадров программа будет несколько тормозить из-за кода блокировки.

Что я собираюсь сделать сейчас, так это

  • собирать только первые несколько кадров, когда появляется целевой объект
  • Поместите их в отдельный поток, чтобы избежать блокировки кода.

Я измерил количество кадров, снимаемых веб-камерой каждую секунду, то есть ~ 28 кадров.Таким образом, каждую секунду цикл while будет собирать только первые 5 кадров, обрабатывать их все в другом потоке и возвращать результат после завершения всех 5 функций.

Я пытался использовать 'Pool' и 'Queue', но не смог заставить его работать, цикл все еще заблокирован.Приведенный ниже код неопределенно представляет, как моя программа выглядит сейчас, будет редактировать ее, когда я вернусь домой, используя телефон, чтобы отправить сообщение сейчас.

def detect(frame):
    # detect target object from images
    pass

def nn(frame):
    # some heavy processing code
    pass

count = 0
stack = []

while True:
    frame = cv2.imread(0)

    detected = detect(frame)

    # stop collecting images when collected 5
    if detected and count <= 5:
        stack.append(frame)
        count += 1

    # start processing
    if len(stack) == 5:
        p = Pool(4)
        results = p.map(nn, frame)
        p.close()
        p.join()

        # reset
        stack = []
        count = 0

Правильно ли я понимаю концепцию?Или мне нужно сделать что-то еще, как сопрограмма?

1 Ответ

0 голосов
/ 19 февраля 2019

Я решил это, используя rq .
Простая очередь сообщений для python.Во-первых, реализация метода, который вам нужно запустить асинхронно.

Будет запущена ваша функция nn, в данном случае
, затем установите простую конфигурацию для очереди сообщений, я использую connectionPool изпакет redis .

По сути, вы отправляете всю задачу в параллельный процесс, выполняемый работником rq.

def nn(frame):
    # some heavy processing code
    pass

def asynch_call(frame):
   p = Pool(4)
   results = p.map(nn, frame)
   p.close()
   p.join()

pool = redis.ConnectionPool(
  host=HOST, 
  port=PORT, 
  password=PASS, 
  db=0)

r = redis.Redis(connection_pool=pool)  
q = Queue('nn_queue', connection=r)

count = 0
stack = []

while True:
    frame = cv2.imread(0)

    detected = detect(frame)

    # stop collecting images when collected 5
    if detected and count <= 5:
        stack.append(frame)
        count += 1

    # start processing
    if len(stack) == 5:

        job = q.enqueue(asynch_call, frame, timeout=any_long_timeout )

        if job.status=='queued':
            print("Job submission ok")

            # reset
            stack = []
            count = 0

Чтобы запустить работника, которыйбудет обрабатывать асинхронные вызовы, у вас есть несколько вариантов, создать свой собственный код для Worker или просто выполнить следующую команду в отдельном терминале:

rq worker nn_queue

См. команду симя очереди, использованное выше для отправки задания.
Надеюсь, это поможет.

...