opencv: покажите изображение и дождитесь, пока переменная изменится, вместо ожидания нажатия клавиши - PullRequest
0 голосов
/ 30 января 2019

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

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

Проблема в том, что cv2 требует, чтобы я вставил "waitKey" - который будет ждать несколько миллисекунд или пока не будет нажата клавиша.Если я не включу «waitKey» - изображение мгновенно исчезнет, ​​как только оно будет отображено.

Есть ли способ заставить cv2 отображать изображение, пока переменная не будет обновлена?

Правотеперь мой код выглядит так:

while True:
        finalimage = generate_image() # this part takes a second, give or take.
        cv2.imshow("window", finalimage)
        cv2.waitKey(2000)

Но для этого требуется, чтобы я ждал 2 секунды для каждого изображения ... которое можно ускорить.Также - если есть случай, когда генерация изображения занимает более 2 секунд, скрипт облажается.

TLDR: есть ли способ показать изображение с cv2 до тех пор, пока переменная не будет обновлена ​​/ изменена- не останавливая программу для ожидания ввода ключа?

1 Ответ

0 голосов
/ 30 января 2019

Обычный способ - отделить часть GUI от части, которая генерирует изображение.Для этого просто поместите поколение в другой поток.Вот небольшой пример кода того, как это сделать.

import numpy as np
import cv2
from threading import Thread, Lock
import time # not really needed, used to simulate the 2 seconds of generation

lock = Lock()

class ImageGenerator:
    def __init__(self, src=0):
      # initialize it with zeros to always have something to show. You can set it to None and check it outside before displaying
      self.frame = np.zeros((100,100,1))
      self.stopped = True

    def start(self):
     # checks if the generator is still running, to avoid two threads doing the same
     if not self.stopped:
       return
     self.stopped = False
     #Launches a thread to update itself
     Thread(target=self.update, args=()).start()
     return self

    def update(self):
      # go until stop is called, you can set other criterias
      while True:
        if self.stopped:
          return
        # generate the image, this is equal to finalimage = generate_image() in your code
        image = np.random.randint(0,255, (600, 800, 3), dtype=np.uint8)
        # this sleep is to simulate that it took longer to execute
        time.sleep(2)
        with lock:
          self.frame = image

    # if this changes the other thread will stop
    def stop(self):
      self.stopped = True

    # gets latest frame available  
    def get(self):
      return self.frame

# creates the object and start generating
imGen = ImageGenerator()
imGen.start()
# infinite loop to display the image, it can be stopped at any point with 'q'
while (True):
    cv2.imshow("Image", imGen.get())
    k = cv2.waitKey(50) & 0xFF
    if k == ord('q'):
      break;
# stops the generator and the other thread
imGen.stop()    
cv2.destroyAllWindows()

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

...