I'm trying to record from a Logitech Brio at 60fps, preferably at 1080p.
It should work because I can get it working on OBS and many others have achieved the settings.
Here is the code I am using to try to capture at this rate:
// Do some grabbing
cv::VideoCapture video_capture;
video_capture.set(cv::CAP_PROP_FRAME_WIDTH, 1920);
video_capture.set(cv::CAP_PROP_FRAME_HEIGHT, 1080);
video_capture.set(cv::CAP_PROP_FPS, 60);
{
INFO_STREAM("Attempting to capture from device: " << device);
video_capture = cv::VideoCapture(device);
// Read a first frame often empty in camera
cv::Mat captured_image;
video_capture >> captured_image;
}
if (!video_capture.isOpened())
{
FATAL_STREAM("Failed to open video source");
return 1;
}
else INFO_STREAM("Device or file opened");
cv::Mat captured_image;
video_capture >> captured_image;
What should I be doing differently for the Brio?
I had the same problem: same camera, couldn't change resolution or fps . After hours of working on this and digging the internet I found a solution:
Need to use DSHOW and need to instead read from capture device 1 (instead of 0). Code below for reference
fourcc = cv2.VideoWriter_fourcc('M','J','P','G')
cap = cv2.VideoCapture()
cap.open(cameraNumber + 1 + cv2.CAP_DSHOW)
cap.set(cv2.CAP_PROP_FOURCC, fourcc)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
cap.set(cv2.CAP_PROP_FPS, 60)
sorry I only did this in Python, but I hope the same solution works in c++
I assume you can do something along the lines of
video_capture = cv::VideoCapture(device + 1 + cv::CAP_DSHOW);
With OpenCV 4.1.0, this achieved 4K video under Windows, with my Logitech BRIO. The important thing in the end seemed to be to use CAP_DSHOW and to set the resolution after initialising the camera, not before.
cv::VideoCapture capture;
capture = cv::VideoCapture(cv::CAP_DSHOW);
if (!capture.isOpened())
{
cerr << "ERROR: Can't initialize camera capture" << endl;
return 1;
}
capture.set(cv::CAP_PROP_FRAME_WIDTH, 3840);
capture.set(cv::CAP_PROP_FRAME_HEIGHT, 2160);
capture.set(cv::CAP_PROP_FPS, 30);
I think the problem has nothing to do with the camera. The code might not work because you are creating a separate scope for opening the video capture. Upon exiting that scope, the destructor of video_capture instance will be called and therefore the !isOpened() check will always return true. I can't understand why you use those braces. Instead it should be:
INFO_STREAM("Attempting to capture from device: " << device);
auto video_capture = cv::VideoCapture(device);
if (!video_capture.isOpened())
{
FATAL_STREAM("Failed to open video source");
return 1;
}
cv::Mat captured_image;
video_capture.set(cv::CAP_PROP_FRAME_WIDTH, 1920);
video_capture.set(cv::CAP_PROP_FRAME_HEIGHT, 1080);
video_capture.set(cv::CAP_PROP_FPS, 60);
INFO_STREAM("Device or file opened");
video_capture >> captured_image;
After some troubleshooting of my own, I found that #ffarhour's solution worked for me.
fourcc = cv2.VideoWriter_fourcc('M','J','P','G')
cap = cv2.VideoCapture()
cap.open(cameraNumber + 1 + cv2.CAP_DSHOW)
cap.set(cv2.CAP_PROP_FOURCC, fourcc)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
cap.set(cv2.CAP_PROP_FPS, 60)
But for anyone troubleshooting this in the future, I also want to add that you need a good USB cable and preferably direct access to a usb 3.0 port. I had the camera in my dock first, and only 1080p worked.
A good check is the windows 10 built in camera tool. My experience is that high resolutions will only show as options here, if your cable and usb port support it. So do not bother with Opencv if this does not work first.
Aditionally for those just starting out: the code snippit above goes before your opencv while loop. and Inside your while loop you add:
while True:
ret, frame = cap.read()
frame = cv2.cvtColor(frame, 1)
cv2.imshow('original image', frame)
cv2.waitKey(2)
Finally I want to note that 30 fps worked best for me (better than 24 fps) and that the max available resolution from the camera is NOT 3840 x 2160 pixel but 4096 x 2160, how cool is that?
I also strongly advise to download the logitech driver for brio called 'logitech camera settings' it allows you to set the FOV, autofocus and other things you otherwise could never access.
Related
I know that this is an opencv error, and I know that Flask has nothing to do with opencv. However, please stick with me through the end.
I'm getting this really weird error ONLY when I'm streaming the CV frames:
VIDEOIO ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV
Unable to stop the stream: Device or resource busy
My code:
// my camera_detector class does some AI works on the camera frame, other than that nothing special
camera = camera_detector(my_arguments)
#app.route('/')
def index():
return render_template('index.html')
def gen(camera):
while True:
print('getting frame')
frame = camera.get_frame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
#app.route('/feed')
def video_feed():
return Response(gen(camera), mimetype='multipart/x-mixed-replace; boundary=frame')
Now here is why I said this only happens with Flask, if I just grab the camera frame like this:
while True:
frame = camera.get_frame()
without ever using flask, everything runs just fine o_0
If it makes any difference, I'm using python3.7 on the pi4. My camera also does some AI works on camera_frame produced by open cv, draw boxes, labels, before returning the frame to Flask:
def get_frame(self):
ret, frame = self.camera.read()
# processing, does AI works, draw boxes and labels
ret, jpeg = cv2.imencode('.jpg', frame)
return jpeg.tobytes()
[Edit] camera info if it helps:
{20-04-22 15:39}raspberrypi:~/detect pi% v4l2-ctl -d /dev/video0 --list-formats
ioctl: VIDIOC_ENUM_FMT
Type: Video Capture
[0]: 'YUYV' (YUYV 4:2:2)
[1]: 'MJPG' (Motion-JPEG, compressed)
[SOLVED]: Answer is below for those who are interested.
For those who got had the same issue, I found out what was causing it. The problem was that I created a camera instance like this:
camera = camera_detector(my_arguments)
and then passed that into my route function:
#app.route('/feed')
def video_feed():
return Response(gen(camera), mimetype='multipart/x-mixed-replace; boundary=frame')
Turn out opencv did not like that so much. I found this very odd, but it works fine after I changed it to:
#app.route('/feed')
def video_feed():
return Response(gen(camera_detector(my_arguments)), mimetype='multipart/x-mixed-replace; boundary=frame')
Any body who have an explanation for this would be nice!
It looks like you're borrowing code from https://blog.miguelgrinberg.com/post/video-streaming-with-flask
Comparing the two, your snippet has an extra \r\n' at the end of each frame. Try removing that.
my goal is to capture a frame from a rtmp stream every second, and process it using OpenCV. I'm using FFmpeg version N-71899-g6ef3426 and OpenCV 2.4.9 with the Java interface (but I'm first experimenting with Python).
For the moment, I can only take the simple and dirty solution, which is to capture images using FFmpeg, store them in disk, and then read those images from my OpenCV program. This is the FFmpeg command I'm using:
ffmpeg -i "rtmp://antena3fms35livefs.fplive.net:1935/antena3fms35live-live/stream-lasexta_1 live=1" -r 1 capImage%03d.jpg
This is currently working for me, at least with this concrete rtmp source. Then I would need to read those images from my OpenCV program in a proper way. I have not actually implemented this part, because I'm trying to find a better solution.
I think the ideal way would be to capture the rtmp frames directly from OpenCV, but I cannot find the way to do it. This is the code in Python I'm using:
cv2.namedWindow("camCapture", cv2.CV_WINDOW_AUTOSIZE)
cap = cv2.VideoCapture()
cap.open('"rtmp://antena3fms35livefs.fplive.net:1935/antena3fms35live-live/stream-lasexta_1 live=1"')
if not cap.open:
print "Not open"
while (True):
err,img = cap.read()
if img and img.shape != (0,0):
cv2.imwrite("img1", img)
cv2.imshow("camCapture", img)
if err:
print err
break
cv2.waitKey(30)
Instead of read() function, I'm also trying with grab() and retrieve() functions without any good result. The read() function is being executed every time, but no "img" or "err" is received.
Is there any other way to do it? or maybe there is no way to get frames directly from OpenCV 2.4.9 from a stream like this?
I've read OpenCV uses FFmpeg to do this kind of tasks, but as you can see, in my case FFmpeg is able to get frames from the stream while OpenCV is not.
In the case I could not find the way to get the frames directly from OpenCV, my next idea is to pipe somehow, FFmpeg output to OpenCV, which seems harder to implement.
Any idea,
thank you!
UPDATE 1:
I'm in Windows 8.1. Since I was running the python script from Eclipse PyDev, this time I run it from cmd instead, and I'm getting the following warning:
warning: Error opening file (../../modules/highgui/src/cap_ffmpeg_impl.hpp:545)
This warning means, as far as I could read, that either the file-path is wrong, or either the codec is not supported. Now, the question is the same. Is OpenCV not capable of getting the frames from this source?
Actually I have spent more that one day to figure out how to solve this issue. Finally I have solved this problem with the help of this link.
Here is client side code.
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
using namespace cv;
int main(int, char**) {
cv::VideoCapture vcap;
cv::Mat image;
const std::string videoStreamAddress = "rtmp://192.168.173.1:1935/live/test.flv";
if(!vcap.open(videoStreamAddress)) {
std::cout << "Error opening video stream or file" << std::endl;
return -1;
}
cv::namedWindow("Output Window");
cv::Mat edges;
for(;;) {
if(!vcap.read(image)) {
std::cout << "No frame" << std::endl;
cv::waitKey();
}
cv::imshow("Output Window", image);
if(cv::waitKey(1) >= 0) break;
}
}
Note: In this case I have created a android application to get real time video and send it to rtmp server wowza which is deployed in PC.So that is where I created this c++ implementation for real time video processing.
python -c "import cv2; print(cv2.getBuildInformation())"
check build opencv with ffmpeg。If it is correct, your code should be fine。
If not, rebuild opencv with ffmpeg。
Under osx
brew install opencv --with-ffmpeg
I am trying to write a video with some sequence of depth map.
I have converted the depth image from cv::Mat_ to cv::Mat with single channel.
But no codec I use is able to open the avi file I want to write. The VideoCapture.open(...) doesn't seem to be able to either create the file or open it.
I think its the problem choosing the right codec. I might be wrong. I have posted a small code snippet.
cv::VideoWriter outputVideo_;
source_ = "~/Hello.avi";
cv::Size S(480, 640);
outputVideo_.open(source_, CV_FOURCC('D','I','B', ' '), 20, S, false);
if (!outputVideo_.isOpened())
{
std::cout << "Could not open the output video for write: " << source_ << std::endl;
return;
}
How do I get opencv to work correctly in this case. I am using linux 12.04, ROS (Robot Operating System) and OpenCV 2.4.2
Try to use open() function with only file name. because here with me it works well.
VideoWriter outputVideo_;
source_ = "~/Hello.avi";
// cv::Size S(480, 640);
outputVideo_.open(source_);
if (!outputVideo_.isOpened())
{
std::cout << "Could not open the output video for write: " << source_ << std::endl;
return;
Recently I migrated to OpenCV 2.4.3 from OpenCV 2.4.1.
My program which worked well with 2.4.1 version now encounters problem with 2.4.3.
The problem is related to VideoCapture that can not open my video file.
I saw a similar problem while searching the internet, but I couldn't find a proper solution for this. Here is my sample code:
VideoCapture video(argv[1]);
while(video.grab())
{
video.retrieve(imgFrame);
imshow("Video",ImgFrame);
waitKey(1);
}
It's worth mentioning that capturing video from webcam device works well, but I want to grab stream from file.
I'm using QT Creator 5 and I compiled OpenCV with MinGW. I'm using Windows.
I tried several different video formats and I rebuilt OpenCV with and without ffmpeg, but the problem still persists.
Any idea how to solve the problem?
Try this:
VideoCapture video(argv[1]);
int delay = 1000.0/video.get(CV_CAP_PROP_FPS);
while(1)
{
if ( !video.read(ImgFrame)) break;
imshow("Video",ImgFrame);
waitKey(delay);
}
In my experience with OpenCV I struggled using IP cams until my mentor discovered how to get them to work, don't forget to plug your IP address in otherwise it won't work!
import cv2
import numpy as np
import urllib.request
# Sets up the webcam and connects to it and initalizes a variable we use for it
stream=urllib.request.urlopen('http://xx.x.x.xx/mjpg/video.mjpg')
bytes=b''
while True:
# Takes frames from the camera that we can use
bytes+=stream.read(16384)
a = bytes.find(b'\xff\xd8')
b = bytes.find(b'\xff\xd9')
if a!=-1 and b!=-1:
jpg = bytes[a:b+2]
bytes= bytes[b+2:]
frame = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8),cv2.IMREAD_COLOR)
img = frame[0:400, 0:640] # Camera dimensions [0:WIDTH, 0:HEIGHT]
# Displays the final product
cv2.imshow('frame',frame)
cv2.imshow('img',img)
# Hit esc to kill
if cv2.waitKey(1) ==27:
exit(0)
This is a code snippet from O'Reilly Learning Opencv,
cvNamedWindow("Example3", CV_WINDOW_AUTOSIZE);
g_capture = cvCreateFileCapture(argv[1]);
int frames = (int) cvGetCaptureProperty(g_capture, CV_CAP_PROP_FRAME_COUNT);
if (frames != 0) {
cvCreateTrackbar("Position", "Example3", &g_slider_postion, frames, onTrackbarSlide);
}
But unfortunately, cvGetCaptureProperty always return 0. I have searched opencv group in Yahoo, found the same problem.
Oh, I get it. I have found these code snippet in the Learning OpenCV's samples codes:
/*
OK, you caught us. Video playback under linux is still just bad. Part of this is due to FFMPEG, part of this
is due to lack of standards in video files. But the position slider here will often not work. We tried to at least
find number of frames using the "getAVIFrames" hack below. Terrible. But, this file shows something of how to
put a slider up and play with it. Sorry.
*/
//Hack because sometimes the number of frames in a video is not accessible.
//Probably delete this on Widows
int getAVIFrames(char * fname) {
char tempSize[4];
// Trying to open the video file
ifstream videoFile( fname , ios::in | ios::binary );
// Checking the availablity of the file
if ( !videoFile ) {
cout << "Couldn’t open the input file " << fname << endl;
exit( 1 );
}
// get the number of frames
videoFile.seekg( 0x30 , ios::beg );
videoFile.read( tempSize , 4 );
int frames = (unsigned char ) tempSize[0] + 0x100*(unsigned char ) tempSize[1] + 0x10000*(unsigned char ) tempSize[2] + 0x1000000*(unsigned char ) tempSize[3];
videoFile.close( );
return frames;
}
I had the same problem. It says it would work on Windows but it does not. I guess it is because I use Dev-C++ and Dev-C++ uses gcc. Though I'm not sure if that is the reason.
I don't seem to have this problem in the linux version (the one installed after doing a ROS installation), but I keep running into it on OSX. I thought it had to do with the OpenCV version I was using (I installed the linux one rather recently) so I installed OpenCV 2.2 on my mac, but the problem persists.
Does anyone know if this has been corrected completely on the latest version of the repository?
Worse is I didn't have this problem on Windows 7, and then a few days later I did, with the same video file. No rhyme or reason.