Unable to read frames from VideoCapture from secondary webcam with OpenCV

14,830

After some time I've found out that it is always only the first call of read that fails and skipping the first frame started to work fine although the true reason of this behavior remained unknown.

Later James Barnett (see comments above) has pointed out that the reason might be that it takes a while till the camera gets ready for capturing and my current solution looks the following way (C++11's sleep):

#include <chrono>
#include <thread>
...

VideoCapture cap(1);

// give camera some extra time to get ready:
std::this_thread::sleep_for(std::chrono::milliseconds(200));

if (!cap.isOpened()) {
     std::cout << "Unable to read stream from specified device." << std::endl;
     return;
}

while (true)
{
    // retrieve the frame:
    Mat frame;
    if (!cap.read(frame)) {
        std::cout << "Unable to retrieve frame from video stream." << std::endl;
        continue;
    }

    // display it:
    imshow("LiveStream", frame);

    // stop if Esc has been pressed:
    if (waitKey(1) == 27) {
        break;
    }
}

cap.release();

Hopefully some future visitors will find it helpful :)

Share:
14,830
LihO
Author by

LihO

Michal Lihocký I've been quite active here back in 2011-13 when working as C++/C# developer. Since then, I've spent the last 6 years traveling throughout Asia and building web solutions for companies around the globe, using Yii, Laravel, Symfony, CakePHP and recently also VueJS and ReactJS + Redux, which is quite cool stuff. Currently based in Singapore, overlooking the development of private equity investing portal Fundnel.

Updated on June 12, 2022

Comments

  • LihO
    LihO almost 2 years

    Code:

    Simple example that works perfectly with primary webcam (device 0):

    VideoCapture cap(0);
    
    if (!cap.isOpened()) {
         std::cout << "Unable to read stream from specified device." << std::endl;
         return;
    }
    
    while (true)
    {
        // retrieve the frame:
        Mat frame;
        if (!cap.read(frame)) {
            std::cout << "Unable to retrieve frame from video stream." << std::endl;
            break;
        }
        // display it:
        imshow("MyVideo", frame);
    
        // check if Esc has been pressed:
        if (waitKey(1) == 27) {
            break;
        }
        // else continue:
    }
    
    cap.release();
    

    Problem:

    I have a second webcam, which I'd like to use. However, when I replace VideoCapture cap(0); with VideoCapture cap(1);, the stream is being opened correctly (or at least cap.isOpened() returns true) but the cap.read(frame) call returns false and I'm unable to find out why.

    What I've tried:

    • I've been trying to play with VideoCapture's settings a bit like calling:

      cap.set(CV_CAP_PROP_FORMAT, CV_8UC3);
      

      and random stuff like that, but nothing seems to help.

    • I've also found this: VideoCapture::read fails on uncompressed video (Bug #2281), which seems to be solved on version 2.4.7.. but I've just updated OpenCV to 2.4.8 and it still doesn't work...

    • I've tried to use the AMCap to capture the raw video from this camera, save it as aaa.avi file and constructed VideoCapture by calling:

      VideoCapture cap("aaa.avi");
      

      and it works (while being read from file)... what I need is real-time processing with live view though.

    HW, OS, SW details:

    My HW: HP ProBook 4510s with built-in webcam that always works perfectly
    + external webcam CANYON CNR-FWCII3, refered by OS as "USB Video Device" (the troublesome one) OS, SW: Windows 8.1 Pro x86, Visual Studio 2012 Pro, OpenCV 2.4.8 ~ using vc11 build

    Questions:

    1. Am I missing something?
    2. Is there anything else that I could do?
    3. Is there at least any way how to retrieve some additional information about what the problem might actually be?

    ... OpenCV's API seems quite poor in this case and everywhere where people seemed to be facing the similar issue, there was someone claiming it to be "OS / HW depnendant" as an excuse.

    Any help will be appreciated.

    • James Barnett
      James Barnett about 10 years
      Are you sure nothing is currently using device 1 when you try to read from it? Perhaps a still running previous instance of your program? (Sounds stupid but it happened to me!)
    • LihO
      LihO about 10 years
      @JamesBarnett: Yes, I'm sure. The thing is... instead of guessing possible causes, it would be nice if there is a way how to get more info out of it.
    • James Barnett
      James Barnett about 10 years
      You could call cap.get(i) and print the various properties. That would give you some info see here
    • LihO
      LihO about 10 years
      @JamesBarnett: Out of curiousity I've tried whether read always fails and I found out that it is only the first call that fails -_-
    • James Barnett
      James Barnett about 10 years
      Interesting, perhaps it is timing based? As in the camera isn't ready to capture for few ms? What happens if you sleep or loop through a large array before the first capture?
    • LihO
      LihO about 10 years
      @JamesBarnett: Yes, you are right. Sleeping the current thread for 1 sec right after the VideoCapture is constructed yields the same, it works.
    • James Barnett
      James Barnett about 10 years
      good to know! one of the many quirks of opencv I guess
  • LihO
    LihO over 9 years
    I was checking the return value of cap.read call in original code yet it still wasn't enough in my case. I think this might be hardware / environment specific.
  • Ali Ahmadvand
    Ali Ahmadvand almost 2 years
    I have a same problem but this solution dose not work