Qtimer and opencv are slow
I am writing code that uses QTimer to call opencv videoCapture calls to read video frames. I usually read large chunks of video, so I wonder if there is another way to speed things up.
here's a snapshot of my code that uses QTimer:
timer = new QTimer();
timer->setTimerType(Qt::PreciseTimer);
connect(timer, SIGNAL(timeout()), this, SLOT(read_shape_params()));
//in a loop stop timer and setup the next video stream then start
void next(){
timer->stop();
stream = new video_stream_reader();
stream->setColorGray(grayImage);
stream->set_begin_end(begin_at,end_at);
stream->open(video_base_path+video_path);
timer->start(0);
}
void shape_param_finder::read_shape_params(){
Mat frame;
frame = stream->read_frame();
}
Mat video_stream_reader::read_frame(){
Mat frame;
bool bSuccess = capture->read(frame);
return frame;
}
source to share
It has nothing to do with QTimer. But
timer->start(0);
- the problem. On your video, you enter the camera, there is frame per second
, which means the period for the frame. For example, 25fps means you'll get a new frame every time, 40ms
in this case.
Short answer:
Without proper hardware timing, set the timer timeout to 1000 / expected fps
.
Long answer:
Timer s timeout = 0
will schedule read_shape_params
as fast as possible. this means that the performance bottleneck will end up being capture->read(frame);
, assuming another piece of code (display, etc.) works just fine.
There are 3 cases about capture->read(frame)
:
- It takes longer to resolve this time period: there is nothing you can do. It will be slow.
- The same time. It's a sweet spot. This is also unlikely.
-
It takes less time to resolve this time period: should it be good? Wrong. You are reading the same image multiple times. This means, at best, you are wasting CPU resources. In the worst case, everything starts to behave like in case 1 from your point of view. How so? Let's say it takes 30ms to represent a frame (read and show, I assume you are doing this linearly).
Read 1 : 30 ms, frame 1 Read 2 : 30 ms, frame 1 // wasted read, the other party has not updated the frame yet Read 3 : 30 ms, frame 2 // your second frame has 60 ms latency, not 40 ms Read 4 : 30 ms, frame 3 // frame 3 has 120 ms latency, sweet spot. Read 5 : 30 ms, frame 3 // wasted read Read 6 : 30 ms, frame 4 // frame 3 has 120 ms latency, sweet spot.
If, in addition, you are storing the queue position for display and the display is slow, your perceived fps will be lower.
- You need to check the lead time
video_stream_reader::read_frame
. - You also need to check what code the image will display. I suspect there is a bottleneck there.
source to share