Ask Your Question
2

4K VideoCapture very slow on Windows compared to MS Camera App

asked 2019-07-23 13:20:24 -0600

roboter gravatar image

updated 2019-07-24 03:15:04 -0600

Hi!

I have gotten a Logitech BRIO Webcam, which delivers nice smooth 30 fps of 4k images in the native Windows Camera App. Using OpenCV 4.1.0 in Python, this seems impossible. The stream is very slow at the same exposure level. Here is my code:

import cv2
import time

print(cv2.getBuildInformation())

time_sum = 0
frames = 0

capture = cv2.VideoCapture()
capture.open(1 + cv2.CAP_DSHOW)

fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')
capture.set(cv2.CAP_PROP_FOURCC, fourcc)
capture.set(cv2.CAP_PROP_FPS, 30)
capture.set(cv2.CAP_PROP_FRAME_WIDTH, 3840)
capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 2160)

while(1):
    before_timer = time.perf_counter()
    ret, frame = capture.read()
    if frame is None:
        print("Frame is empty")
        break
    else:
        cv2.imshow('VIDEO', frame)
        after_timer = time.perf_counter() - before_timer
        time_sum += after_timer
        frames += 1
        if frames % 30 == 0:
            print("{} per second".format(frames/time_sum))
        cv2.waitKey(1)

Disabling the imshow does not have a significant impact on performance. Using CAP_MSMF as backend will deliver 30 FPS, but the video is just an upscaled version of a lower resolution stream, and sadly useless. I've been looking around the capture backend code for quite a while, but I can't seem to figure out where the problem lies.

When disabling the RGB conversion with capture.set(cv2.CAP_PROP_CONVERT_RGB, 0), the FPS also do not improve.

I also tried the same loop in C++, it was just as slow.

The relevant portion of getBuildInformation() looks like this:

Video I/O:
DC1394:                      NO
FFMPEG:                      YES (prebuilt binaries)
  avcodec:                   YES (58.35.100)
  avformat:                  YES (58.20.100)
  avutil:                    YES (56.22.100)
  swscale:                   YES (5.3.100)
  avresample:                YES (4.0.0)
GStreamer:                   NO
DirectShow:                  YES
Media Foundation:            YES
DXVA:                      NO

Does anyone have any pointers on how to improve video performance? I am at a loss as to what to do. Hardware acceleration might be an option, but I don't know how to get that into my opencv-python package :(

Setting the DEBUG environment variable does not produce any additional logging info.

Thanks a lot for any help!

Edit: C++-Code.

#include "stdafx.h"
#include "opencv2\opencv.hpp"
int main()
{
    cv::VideoCapture capture;

    capture.open(1 + cv::CAP_DSHOW);

    if (!capture.isOpened()) {
        std::cerr << "Error opening video stream" << std::endl;
        return -1;
    }

    capture.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'));
    capture.set(cv::CAP_PROP_FPS, 30);
    capture.set(cv::CAP_PROP_FRAME_WIDTH, 3840);
    capture.set(cv::CAP_PROP_FRAME_HEIGHT, 2160);

    while (true) {
        cv::Mat frame;
        capture >> frame;

        if (frame.empty()) {
            break;
            std::cerr << "Frame is empty." << std::endl;
        }
        cv::imshow("Brio", frame);

        char c = (char)cv::waitKey(1);

        if (c == 27) {
            break;
        }
    }

    capture.release();
    cv::destroyAllWindows();

    return 0;
}

Using chrono-STL-functions to measure the time unforntunately lead to an internal compiler error. But I can judge from the display that the result is the same.

edit retag flag offensive close merge delete

Comments

1

Please post your C++ code.

sjhalayka gravatar imagesjhalayka ( 2019-07-23 14:50:40 -0600 )edit

I have added the C++ code, I assume it does the same as the python code. Ran it in Release mode without debugging in Visual Studio 2017.

roboter gravatar imageroboter ( 2019-07-24 03:15:54 -0600 )edit

Sorry. I'm using Debian Buster version 10.

50562.08181784478 per second
56129.742077105766 per second
47952.30344835258 per second
45789.04836897512 per second
48202.80655905395 per second
49769.23663424743 per second
50959.64286914462 per second
49738.06689345821 per second
supra56 gravatar imagesupra56 ( 2019-07-24 06:25:06 -0600 )edit

Change this:

capture = cv2.VideoCapture()

to

capture = cv2.VideoCapture(0)

Also change this too:

if frame is None:

to

if ret is None:
supra56 gravatar imagesupra56 ( 2019-07-24 08:14:14 -0600 )edit

Also you can cv2.resize too to get 3420, 2160

supra56 gravatar imagesupra56 ( 2019-07-24 08:15:55 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2019-07-24 03:21:28 -0600

Ziri gravatar image

I am not sure why are you setting these parameters after opening the video :

capture.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'));
capture.set(cv::CAP_PROP_FPS, 30);
capture.set(cv::CAP_PROP_FRAME_WIDTH, 3840);
capture.set(cv::CAP_PROP_FRAME_HEIGHT, 2160);

But anyway, a better alternative is using Gstreamer c++

edit flag offensive delete link more

Comments

These parameters represent the hardware-supported video mode of my Logitech Brio webcam - MJPG stream with 30 fps at 4k resolution. Do you have alternative settings to achieve this?

Is Gstreamer available on Windows?

roboter gravatar imageroboter ( 2019-07-24 03:48:52 -0600 )edit

did you try opening the video without setting any parameters?

You can use Gstreamer in Windows Installing on Windows

Ziri gravatar imageZiri ( 2019-07-24 04:13:50 -0600 )edit

If I open the video without any of these settings, I get a 640x480 stream with solid FPS.

roboter gravatar imageroboter ( 2019-07-24 04:49:13 -0600 )edit

Are you sure you connected the cam to an USB3.0 port? Have a look at this - perhaps it will be helpful: https://www.e-consystems.com/Articles...

Witek gravatar imageWitek ( 2019-07-24 10:56:38 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2019-07-23 13:18:20 -0600

Seen: 7,213 times

Last updated: Jul 24 '19