I have multiple recorded video samples, when I run these through my program it returns the FPS among other things. It is accurate enough for all of my video samples (see table below) but when I run a video sample taken through my smartphone it is returning the FPS at 90000, this happens with every video that captured through my smartphone so it is not just a problem with a single video file.
File Actual FPS OpenCV FPS ffmpeg FPS
action-60fps 60 59 60
action-24fps 24 24 24
phone_panning 29 90000 29
What is causing this problem?
EDIT: Managed to forget to add my code...
VideoCapture capture(argv[1]);
Mat frame;
if(capture.isOpened()) {
int fps = capture.get(CV_CAP_PROP_FPS);
int width = capture.get(CV_CAP_PROP_FRAME_WIDTH);
int height = capture.get(CV_CAP_PROP_FRAME_HEIGHT);
cout << "FPS: " << fps << ", width: " << width << ", height: " << height << endl;
VideoWriter writer("output.mpg",
CV_FOURCC('P','I','M','1'), fps, cvSize(width, height), 0); // 0 means gray, 1 means color
if(writer.isOpened()) {
while(true) {
capture >> frame;
if(!frame.empty()) {
imshow("Video", frame);
}
Mat frame_gray = frame.clone();
cvtColor(frame, frame_gray, CV_RGB2GRAY);
writer << frame_gray;
int key = waitKey(25);
if((char)key == 'q') {
break;
}
}
}
}
I had the same problem with opencv in calculating the FPS and number of frames in a video. (It was returning 90,000 for FPS and 5,758,245 for frame count for a 64-second video!!)
According to this answer:
OpenCV captures only a fraction of the frames from a video file
it's an opencv issue and they are working on it.
Another reason could be a problem with file header, mine was caused by converting video format. I solved it by using original video format mp4, instead of avi.
Related
The operations I did were quite simple:
I read an .avi file with a dimension of 1280x720, stored one frame of the video to a Mat object and displayed it.
Here is part of the code:
VideoCapture capL;
capL.open("F:/renderoutput/cube/left.avi");
Mat frameL;
cout << capL.get(CAP_PROP_FRAME_WIDTH) << ", " << capL.get(CAP_PROP_FRAME_HEIGHT) << endl;
for (;;)
{
capL.read(frameL);
cout << frameL.size() << endl;
if (frameL.empty())
break;
imshow("Output", frameL);
waitKey(200);
}
......
But the dimensions of the capL and frameL are not he same, with the former being 1280x720 and latter 1280x360. Why is this happening? I have been using OpenCV 3.3.1 in Visual Studio for quite a long time and some day this happened.
Most likely the video is interlaced. So you have only half height of it in every frame.
I would like to capture images with a webcam (i.e. logitech C922) with C++. Does anyone succeed in capturing images with the webcam at 60fps and 720p? I read the code in the following thread and add "cap.set(CAP_PROP_FPS, 60)", but the frame rate was maintained at about 30fps.
How to set camera fps in opencv?
Then I posted the same question, but the forum is under maintenance.
http://answers.opencv.org/question/172992/streaming-logitec-c922-at-60fps-with-c/
I added the both proposed codes to mine.
As the result, the value of fps was 33.3... and FPS was 60.0 in the case that I used cap.set(CAP_PROP_EXPOSURE, -5) because I'm in office and at night here.
I tried to use lower value for CAP_PROP_EXPOSURE (e.g. -10), but the fps didn't change.
The image shown with imshow wasn't updated obviously at 60fps.
Is there anything I can do?
This is the code I used.
VideoCapture cap(0); //capture the video from web cam
if (!cap.isOpened()) // if not success, exit program
{
cout << "Cannot open the web cam" << endl;
return -1;
}
cap.set(CV_CAP_PROP_FOURCC, CV_FOURCC('M','J','P','G'));
cap.set(CAP_PROP_FPS, 60);
cap.set(CAP_PROP_EXPOSURE, -5);
cap.set(CV_CAP_PROP_FRAME_WIDTH, 1280);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 720);
cout << cap.get(CAP_PROP_FPS) << endl;
cvNamedWindow("img");
time_t cap_start, cap_end;
Mat frame;
double MAX_FRAME_NUM = 100;
time(&cap_start);
for (int n = 0; n < MAX_FRAME_NUM; n++) {
cap >> frame;
}
time(&cap_end);
double fps = MAX_FRAME_NUM / difftime(cap_end, cap_start);
cout << "fps:" << fps << endl;
cv::waitKey(0);
Environment Information OpenCv: 3.3.0 OS: Windows 10 Pro IDE: Visual Studio 2017 CPU: i7-7560U RAM 16GB USB: 3.0
Best regards, gellpro
I stumbled upon the same issue with this camera.
My environment is Ubuntu 18.04, python 3.6.5 and OpenCV 3.4.
I found this solution from your first link to be working:
cap.set(CV_CAP_PROP_FOURCC, CV_FOURCC('M', 'J', 'P', 'G'));
For python, the code I use is:
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M','J','P','G'))
cap.set(cv2.CAP_PROP_FPS, 60)
I am using the following code for capturing video frames from a USB webcam using openCV3 in MS VC++ 2012. But the problem is that sometimes I am able to display the captured frames # 30 fps but sometimes I get black frames with a very low fps (or with a high delay). In other words, the program works randomly. Do you know how I can solve this problem? I tried different solutions suggested in stackoverflow or some other places but none of them solved the problem.
VideoCapture v(1);
v.set(CV_CAP_PROP_FRAME_WIDTH, 720);
v.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
if(!v.isOpened()){
cout << "Error opening video stream or file" << endl;
return;
}
Mat Image;
namedWindow("win",1);
while(1){
v >> Image;
imshow("win", Image);
}
try this:
while(1){
v >> Image;
imshow("win", Image);
char c=waitKey(10);//add a 10ms delay per frame to sync with cam fps
if(c=='b')
{
break;//break when b is pressed
}
}
I am trying to process recorded videos for feature point recognition. When I process the video at it's full resolution (1280*720) the video playback is slower than it should be. Whenever I reduce the resolution down to 640*360 the fps drops dramatically. What would be the cause of this?
if(captureOpen == false){
img_scene = cvCaptureFromFile("20151115_154042_582.mp4");
}
while(1) {
image = cvQueryFrame(img_scene);
if(image.empty()) {
cout << "IMAGE EMPTY" << endl;
continue;
}
else {
frameCount++;
}
cvtColor(image, gray, CV_BGR2GRAY);
captureOpen = true;
processingThread(gray, imageIndex);
myfile << cvGetCaptureProperty(img_scene, CV_CAP_PROP_POS_FRAMES) << endl;
imshow("Output", gray);
key = cvWaitKey(5);
I've tried reducing cvWaitKey(); to 1 but it doesn't seem to have any noticeable effect on fps, I've also tried removing the gray scale conversion but that does not have a noticeable effect either.
(I've tried both handbrake and ffmpeg to reduce the resolution)
I am using opencv to show frames from camera. I want to show that frames in to two separation windows. I want show real frame from camera into first window (show frames after every 30 mili-seconds) and show the frames in second window with some delay (that means it will show frames after every 1 seconds). Is it possible to do that task. I tried to do it with my code but it is does not work well. Please give me one solution to do that task using opencv and visual studio 2012. Thanks in advance
This is my code
VideoCapture cap(0);
if (!cap.isOpened())
{
cout << "exit" << endl;
return -1;
}
namedWindow("Window 1", 1);
namedWindow("Window 2", 2);
long count = 0;
Mat face_algin;
while (true)
{
Mat frame;
Mat original;
cap >> frame;
if (!frame.empty()){
original = frame.clone();
cv::imshow("Window 1", original);
}
if (waitKey(30) >= 0) break;// Delay 30ms for first window
}
You could write the loop to display frames in a single function with the video file name as the argument and call them simultaneously by multi-threading.
The pseudo code would look like,
void* play_video(void* frame_rate)
{
// play at specified frame rate
}
main()
{
create_thread(thread1, play_video, normal_frame_rate);
create_thread(thread2, play_video, delayed_frame_rate);
join_thread(thread1);
join_thread(thread2);
}