USB-камера: OpenCV VideoCapture возвращает частичные кадры - PullRequest
11 голосов
/ 10 июля 2019

Я разрабатываю программу для обработки кадров с USB-камеры в Ubuntu.В настоящее время я использую OpenCV в Python.Когда я пытаюсь прочитать кадр, используя объект cv2.VideoCapture, я получаю только частичные кадры .

Камера, которую я использую, является USB-камерой Kayeton GS1M2812 , которая претендует на соответствие требованиям UVC.Большинство приложений (например, «сыр») перечисляют камеру среди доступных веб-камер, но не отображают никаких кадров.Google Hangouts, с другой стороны, может без проблем отображать живые кадры с камеры.

Я также могу успешно захватывать изображения и видео, используя streamer.Например:

streamer -c /dev/video1 -o capture.jpg

Первоначально, когда я пытался использовать cv.VideoCapture, у меня были выбранные тайм-ауты и никаких изображений.После некоторых исследований я обнаружил, что перезапуск модуля uvcvideo с nodrop=1 позволил мне, по крайней мере, получить частичные кадры из opencv (как тот, что был приведен выше).

Я попытался установить для параметра тайм-аута uvcvideo значение до смешного большого значения и испортил все остальные параметры и различные причуды, но безрезультатно.

Я обнаружил, что изменение разрешения (cv.CAP_PROP_FRAME_WIDTH и cv.CAP_PROP_FRAME_HEIGHT) до 320x240 или меньше перед каждым вызовом read() приводит к захвату полного кадра, но все, что больше, - нет.

Я также пытался изменить различные параметры с помощью v4l2-ctl, но это тоже не сработало.

Что я могу сделать, чтобы это исправить?

Вот мой код Python:

import cv2 as cv
import numpy as np
import sys

if len(sys.argv) != 2:
    print("invalid arguments")
    sys.exit()

camNo = int(sys.argv[1])
print("opening camera %d" % camNo)

cap = cv.VideoCapture(camNo)

print("done")

while True:
    cap.set(cv.CAP_PROP_FRAME_WIDTH,640);
    cap.set(cv.CAP_PROP_FRAME_HEIGHT,480);
    ret, frame = cap.read()
    print(ret)

    if(frame is None):
        print("Received empty frame. Exiting")
        sys.exit()

    cv.imshow('frame', frame)
    if cv.waitKey(30) & 0xFF == ord('q'):
        break

cap.release()
cv.destroyAllWindows()

Этот код работает правильно, когда я использую встроенную веб-камеру моего ноутбука (обычно /dev/video0), но при использовании USB-камеры отображаются неполные кадры.

Я использую python 2.7.12 и opencv 3.3.1 в Ubuntu 16.04

Ответы [ 2 ]

2 голосов
/ 12 июля 2019

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

Вы можете попробовать установить кодек cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'MJPG')).

0 голосов
/ 12 июля 2019

Попробуйте это

from threading import Thread
import cv2, time

class WebcamRecorder(object):
    def __init__(self, src=0):
        self.capture = cv2.VideoCapture(src)
        # Start the thread to read frames from the video stream
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True
        self.thread.start()

    def update(self):
        # Read the next frame from the stream in a different thread
        while True:
            if self.capture.isOpened():
                (self.status, self.frame) = self.capture.read()
            time.sleep(.01)

    def show_frame(self):
        # Display frames in main program
        cv2.imshow('frame', self.frame)
        key = cv2.waitKey(1)
        if key == ord('q'):
            self.capture.release()
            cv2.destroyAllWindows()
            exit(1)

if __name__ == '__main__':
    webcam_recorder = WebcamRecorder()
    while True:
        try:
            webcam_recorder.show_frame()
        except AttributeError:
            pass
...