OpenCV 4.5.2 takes a long time (>100ms) to retrieve a single frame from a webcam, C++ on Windows 10

Viewed 226

I've been having a tough time getting my webcam working quickly with opencv. Frames take a very long time to read, (a recorded average of 124ms across 500 frames) I've tried on three different computers (running Windows 10) with a logitech C922 webcam. The most recent machine I tested on has a Ryzen 9 3950X, with 32gbs of ram; no lack of power.

Here is the code:

cv::VideoCapture cap = cv::VideoCapture(m_cameraNum);

// Check if camera opened successfully
if (!cap.isOpened())
{
    m_logger->critical("Error opening video stream or file\n\r");
    return -1;
}

bool result = true;
result &= cap.set(cv::CAP_PROP_FRAME_WIDTH, 1280);
result &= cap.set(cv::CAP_PROP_FRAME_HEIGHT, 720);

bool ready = false;
std::vector<string> timeLog;
timeLog.reserve(50000);
int i = 0;

while (i < 500)
{
    auto start = std::chrono::system_clock::now();
    
    cv::Mat img;
    ready = cap.read(img);

    // If the frame is empty, break immediately
    if (!ready)
    {
        timeLog.push_back("continue");
        continue;
    }

    i++;
    auto end = std::chrono::system_clock::now();
    timeLog.push_back(std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()));
}

for (auto& entry : timeLog)
    m_logger->info(entry);

cap.release();
return 0;

Notice that I write the elapsed time to a log file at the end of execution. The average time is 124ms for debug and release, and not one instance of "continue" after half a dozen runs.

It doesn't matter if I use USB 2 or USB 3 ports (the camera is USB2) or if I run a debug build or a release build, the log file will show anywhere from 110ms to 130ms of time for each frame. The camera works fine in other app, OBS can get a smooth 1080@30fps or 720@60fps.

Stepping through the debugger and doing a lot of Googling, I've learned the following about my system:

  • The backend chosen by default is DSHOW. GStreamer and FFMPEG are also available.
  • DSHOW uses FFMPEG somehow (it needs the FFMPEG dll) but I cannot use FFMPEG directly through opencv. Attempting to use cv::VideoCapture(m_cameraNum, cv::CAP_FFMPEG) always fails. It seems like Opencv's interface to FFMPEG is only capable of opening video files.
  • Microsoft really screwed up camera devices in Windows a few years back, not sure if this is related to my problem.

Here's a short list of the fixes I have tried, most taken from older SO posts:

  • result &= cap.set(cv::CAP_PROP_FRAME_COUNT, 30); // Returns false, does nothing
  • result &= cap.set(cv::CAP_PROP_CONVERT_RGB, 0); // Returns true, does nothing
  • result &= cap.set(cv::CAP_PROP_MODE, cv::VideoWriter::fourcc('M', 'J', 'P', 'G')); // Returns false, does nothing
  • Set registry key from http://alax.info/blog/1693 that should disable the new Windows camera server.
  • Updated from 4.5.0 to 4.5.2, no change.
  • Asked device manager to find a newer driver, no newer driver found.

I'm out of ideas. Any help?

0 Answers
Related