4K VideoCapture very slow on Windows compared to MS Camera App
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.
Please post your C++ code.
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.
Sorry. I'm using Debian Buster version 10.
Change this:
to
Also change this too:
to
Also you can
cv2.resize
too to get 3420, 2160