Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

USB Camera: OpenCV VideoCapture Returns Partial Frames

I am developing a program to process frames from a USB camera on Ubuntu. Currently I'm using OpenCV in python. When I try to read a frame using a cv2.VideoCapture object I only get partial frames.

The camera I'm using is a Kayeton GS1M2812 USB camera, which claims to be UVC compliant. Most applications (like cheese, for instance) list the camera among available webcams, but don't display any frames. Google Hangouts, on the other hand, can display live frames from the camera without a problem.

I can also successfully capture images and video using streamer. e.g.:

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

Initially when I tried to use cv.VideoCapture, I got select timeouts and no images. After some research I found that restarting the uvcvideo module with nodrop=1 allowed me to at least get partial frames from opencv (like the one linked above).

I tried setting the uvcvideo timeout param to a ridiculously large value and messed with all the other params and various quirks, but to no avail.

I did find that changing the resolution (cv.CAP_PROP_FRAME_WIDTH and cv.CAP_PROP_FRAME_HEIGHT) to 320x240 or smaller before each call to read() results in capturing a full frame, but anything larger doesn't.

I've also tried changing various parameters with v4l2-ctl, but that hasn't worked either.

What can I do to fix this?

Here is my python code:

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()

This code works correctly when I use my laptop's builtin webcam (usually /dev/video0), but displays partial frames when I use the USB camera.

I am using python 2.7.12 and opencv 3.3.1 on Ubuntu 16.04

like image 945
JohannB Avatar asked Jul 10 '19 16:07

JohannB


People also ask

What does cv2 VideoCapture return?

Next, we cay cap = cv2. VideoCapture(0) . This will return video from the first webcam on your computer.

How does OpenCV VideoCapture work?

Capture Video from Camera OpenCV allows a straightforward interface to capture live stream with the camera (webcam). It converts video into grayscale and display it. We need to create a VideoCapture object to capture a video. It accepts either the device index or the name of a video file.

How do I use VideoCapture in Python?

Steps to capture a video:VideoCapture( ) to get a video capture object for the camera. Set up an infinite while loop and use the read() method to read the frames using the above created object. Use cv2. imshow() method to show the frames in the video.


1 Answers

Probably by default opencv is requesting uncompressed images from your webcam. That's why when you reduce the resolution or FPS you get a full image otherwise the bandwidth is insufficient for the whole image.

You can try setting the codec cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'MJPG')).

like image 171
fireant Avatar answered Sep 28 '22 16:09

fireant