I recently started working with OpenCV. While I made a lot of progress in the beginning, I'm now close to losing my mind over what appears to be a simple task: Recording a simple video using the Raspberry Pi cam. The problem is that the resulting video appears to be fast forward, and the reason seems to be that not half the necessary frames are actually written upon recording.
After many an hour of experimenting with codecs and time-measuring my code in order to find the bottleneck, I now discovered that the problem appears to be somewhat related to the OpenCV VideoCapture class, whose instance in my code actually delivers far less frames than expected.
So I wrote a simple piece that counts the number of frames delivered by VideoCapture in five seconds. Setting the captures' properties to 640x480x30fps works fine and delivers around 150 frames. But dialing it up to 1920x1080x30fps (which is a valid camera mode according to the specs and works fine in other applications) ends up with only around 15 frames in 5 seconds.
There is probably a very obvious solution, but I'm totally blanking. Can anyone help me? Thanks!
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <ctime>
float getElapsedCPUTime(std::clock_t begin){
return float(clock() - begin)/CLOCKS_PER_SEC;
}
std::time_t getCurrentWallTime(){
return std::time(nullptr);
}
int main (){
// int cols(640);
// int rows(480);
int cols(1920);
int rows(1080);
cv::Mat currentFrame;
// set capture properties
cv::VideoCapture cap(0);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, rows);
cap.set(CV_CAP_PROP_FRAME_WIDTH, cols);
cap.set(cv::CAP_PROP_FPS, 30);
cap.set(cv::CAP_PROP_FOURCC, 0x21);
// control capture properties
int rows_c(cap.get(CV_CAP_PROP_FRAME_HEIGHT));
int cols_c(cap.get(CV_CAP_PROP_FRAME_WIDTH));
int fps(cap.get(cv::CAP_PROP_FPS));
std::cout << "rows: " << rows_c << ", cols " << cols_c << ", fps " << fps << ", CPS: " << CLOCKS_PER_SEC << std::endl;
int cnt(0);
std::time_t loopExecution_begin(getCurrentWallTime());
while(1){
std::string msg("");
// capture frame
std::clock_t capture_begin(clock());
cap >> currentFrame;
float time_for_capture = getElapsedCPUTime(capture_begin);
++cnt;
// get elapsed wall time
std::time_t loopRunTime = getCurrentWallTime() - loopExecution_begin;
// output message
msg += "#: " + std::to_string(cnt);
msg += "\tTicks begin: " + std::to_string(capture_begin);
msg += "\tCapturetime: " + std::to_string(time_for_capture) + "s";
msg += "\tLoop Runtime: " + std::to_string(loopRunTime) + "s";
std::cout << msg << std::endl;
// break after 5s
if (loopRunTime > 5.0) break;
}
}
Edit: This is the output:
rows: 1080, cols 1920, fps 30, CPS: 1000000
#: 1 Ticks begin: 362378 Capturetime: 0.055826s Loop Runtime: 1s
#: 2 Ticks begin: 418543 Capturetime: 0.022631s Loop Runtime: 1s
#: 3 Ticks begin: 441338 Capturetime: 0.022695s Loop Runtime: 1s
#: 4 Ticks begin: 464196 Capturetime: 0.023302s Loop Runtime: 2s
#: 5 Ticks begin: 487659 Capturetime: 0.022729s Loop Runtime: 2s
#: 6 Ticks begin: 510551 Capturetime: 0.022631s Loop Runtime: 2s
#: 7 Ticks begin: 533349 Capturetime: 0.022663s Loop Runtime: 2s
#: 8 Ticks begin: 556176 Capturetime: 0.023194s Loop Runtime: 3s
#: 9 Ticks begin: 579535 Capturetime: 0.022640s Loop Runtime: 3s
#: 10 Ticks begin: 602337 Capturetime: 0.023267s Loop Runtime: 3s
#: 11 Ticks begin: 625789 Capturetime: 0.022741s Loop Runtime: 3s
#: 12 Ticks begin: 648694 Capturetime: 0.023210s Loop Runtime: 3s
#: 13 Ticks begin: 672069 Capturetime: 0.022487s Loop Runtime: 4s
#: 14 Ticks begin: 694721 Capturetime: 0.023162s Loop Runtime: 4s
#: 15 Ticks begin: 718051 Capturetime: 0.022611s Loop Runtime: 4s
#: 16 Ticks begin: 740822 Capturetime: 0.023602s Loop Runtime: 4s
#: 17 Ticks begin: 764600 Capturetime: 0.022555s Loop Runtime: 5s
#: 18 Ticks begin: 787321 Capturetime: 0.022532s Loop Runtime: 5s
#: 19 Ticks begin: 810019 Capturetime: 0.022626s Loop Runtime: 5s
#: 20 Ticks begin: 832813 Capturetime: 0.023161s Loop Runtime: 5s
#: 21 Ticks begin: 856138 Capturetime: 0.022543s Loop Runtime: 6s