OpenCV 3.2 gives Select Timeout when grabbing, but

2019-03-05 01:33发布

问题:

I'm having a bit of a weird issue here. Simply put, I'm trying to grab a frame from a camera (Mercury 2.0 Webcam embedded camera), but it's not going as expected.

I'm running Debian Jessie on a BeagleBone Black. I've installed OpenCV 3.2 and tested it, my Vision algorithm is working fine with imread(), so it's time to start using the camera. The first issue I encountered was the camera not working in Ubuntu 16.04 minimal. So I switched to Debian Jessie and now I can grab 1600x1200 frames using fswebcam (fswebcam -r 1600x1200 --jpeg 95 -D 0 test.jpg) in a fraction of a second, as expected.

I was very happy when that worked, so I'm starting to get rather annoyed again now that VideoCapture >> Mat won't work as expected. Here's the kicker though, if I set the resolution to 800x600, it works fine. When I set the resolution to 1600x1200, it first gives me Select Timeout, but then immediately a succesful result. So, it is able to grab the frame, but just not on the first try. Seems to me it's a timing issue. So I tried using grab() and retrieve(), but that doesn't seem to help either.

Anyone else got some good ideas/suggestions/tips or experience with this issue?

Some specs:

$ uname -a
Linux arm 4.9.13-bone4 #1 [date] armv7l GNU/Linux

$ gcc --version
gcc (Debian 4.9.2-10) 4.9.2

$ v4l2-ctl --all 
Driver Info (not using libv4l2): 
    Driver name: uvcvideo 
    Card type: Mercury USB2.0 Camera 
    Bus info: usb-musb-hdrc.1.auto-1.1 
    Driver version: 4.9.13

$ fswebcam -r 1600x1200 --jpeg 95 -D 0 test.jpg
Opening /dev/video0
Trying source module v4l2...
/dev/video0 opened.
No input was specified, using the first.
Capturing frame...
Captured frame in 0.00 seconds.
Processing captured image...
Setting output format to JPEG, quality 95
Writing JPEG image to 'test.jpg'.

Basic code functionality

VideoCapture cam(0);
cam.set(CAP_PROP_FRAME_WIDTH,width);
cam.set(CAP_PROP_FRAME_HEIGHT,height);

     /*check cam.isOpened()*/

     /*echo some camera properties*/

if(cam.grab()) cam.retrieve(frame);

imwrite(filename, frame);

cam.release();

Also, I tried:

modprobe uvcvideo nodrop=1 timeout=6000

But that didn't help... I also tried using the old CvCapture class, but that didn't help either.

Been working on it all day and figured a few extra things out: The BeagleBone seems to have a hard time with plugging in and unplugging USB devices. I wanted to check the pictures I took, so I plugged in my USB Flashdrive, mounted it, unmounted it, took it out, admired the pictures. Then the camera wouldn't work anymore, even with fswebcam. Had to reboot to get it working again.

Also, taking a few 2MP pictures to fast in a row with fswebcam, seems to give issues as well. Sometimes I get to take a few pictures, other times only 1 before I need to reboot again. When I can't take 2MP pictures, I still can take 800x600 pictures though. Simply replugging the USB doesn't help.

回答1:

For everyone who's dealing with this same issue (Select Timeout). I fixed it for my case, I don't know if this is going to work for everyone, but I'd love if this helped others out there.

The problem is probably because the camera you're trying to use is only semi-UVC compatible. UVC is familiar with products being sold as UVC compatible, when in fact they're not. So they added something called quirks. Read more about this here: UVC FAQ

So, how to fix the Select Timeout? Well, easy apparently. First, we close the uvcvideo module

# rmmod uvcvideo

Next we enable it again, but with the bandwidth quirk enabled; and just in case add the nodrop and timeout flags as well.

# modprobe uvcvideo quirks=128 nodrop=1 timeout=6000

If you want the solution to work after rebooting, add both those lines to your .bash_profile

I tested the BeagleBone Black with my USB2.0 camera after this fix thoroughly: Average framerate: 4 (highly dependent on light, get 5 FPS with a darker environment) Average error percentage: 2.4% (1953 succesful pictures out of 2000 read()'s)

Tested by grabbing 100 frames in a loop and doing this 20 times. I rebooted after 10, to make sure my .bash_profile edit worked as well and to see if there was any performance difference after a fresh reboot. There is none ;)