Основы
Попытка захвата видео с камеры 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) и не смог найти ничего полезного ... Возможно, я что-то упустил.
Если у кого-нибудь есть решение или что-нибудь, что может помочь, я был бы признателен
Заранее спасибо:)