OpenCV VideoCapture.retrieve () ограничивает число кадров в секунду до 30 с помощью DSHOW и MJPEG (добавляет задержку) - как обойти это? - PullRequest
0 голосов
/ 22 января 2019

Основы

Попытка захвата видео с камеры Logitech Brio (может поддерживать скорость до 60 кадров в секунду при 1080p - протестировано в VLC), но я не могу достичь скорости выше 30 кадров в секунду с помощью OpenCV VideoCapture.

Моя система и настройки

Информация о том, что у меня есть и с чем работать:

  • Камера: Logitech Brio
  • Язык: python
  • версия opencv: 4.0
  • Windows 10 с powershell (это необходимо, потому что моя основная программа взаимодействует с другими приложениями на базе Windows)

Настройки, связанные с кодеками:

  • Fourcc = MJPEG (так как другие не поддерживают разрешения, которые мне нужны для моей камеры по некоторым причинам)
  • для открытия камеры используется следующий код: cv2.VideoCapture(cv2.CAP_DSHOW + 1)

Некоторый фон и код

Я использовал подход с многопоточностью, как предлагается здесь: Задержка OpenCV VideoCapture из-за буфера захвата

В основном мой текущий код имеет 2 потока: 1 для функции grab () и 1 для функции retrieve () и сохранения полученного изображения в формате avi.

поток, выполняющий функцию grab (), выглядит примерно так:

def __frame_grab_worker(self, cap, cameraNumber):
    try:
        while(cap.isOpened()):
            # sync with retrieve
            acquired = self._retrievingLock[cameraNumber].acquire()
            try:
                cap.grab()
            finally:
                self._retrievingLock[cameraNumber].release()
            if(self.interrupt == True):
                break
    finally:
        self._cleanupLock.release()

поток, который извлекает изображение и сохраняет его, выглядит примерно так:

def __record(self, filename, vidWidth, vidHeight, fps, cap, cameraNumber):
    if(self.numberOfCams > 0):
        fourcc = cv2.VideoWriter_fourcc('M','J','P','G')
        out = cv2.VideoWriter(filename, fourcc , fps, (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))))
        while(cap.isOpened()):
            self._retrievingLock[cameraNumber].acquire()
            ret, frame = cap.retrieve()
            self._retrievingLock[cameraNumber].release()
            if ret ==True:
                if(self.recordingFlag==True):
                    out.write(frame)

                cv2.imshow(str(cameraNumber), frame)

                # stop if interrupt flag presented
                if cv2.waitKey(1) & self.interrupt == True:
                    break

        cap.release()
        out.release()
        cv2.destroyAllWindows()

Вещи, которые я пробовал

Я профилировал свой код. В общем, между каждой петлей в то время как смотреть в __record есть задержка около 0,03 сек, что составляет 30 кадров в секунду. Это в равной степени разделено между функциями cap.retrieve() и write и imshow.

Я заметил, что если я закомментирую части кода, которые выполняют какую-либо обработку для извлеченного изображения (например, out.write(frame) или cv2.imshow(...)), время, необходимое для функции cap.retrieve(), увеличивается до 0,03 (с ранее примерно 0,15). ).

Таким образом, я предполагаю, что проблема связана с DSHOW с MJPEG, не поддерживающим более 30 кадров в секунду, или с базовыми кодами opencv.

Я также просмотрел кодовую базу opencv (в частности, videoio / src / cap_dshow.cpp & videoio / src / cap.cpp) и не смог найти ничего полезного ... Возможно, я что-то упустил.

Если у кого-нибудь есть решение или что-нибудь, что может помочь, я был бы признателен Заранее спасибо:)

...