Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Measure OpenCV FPS

Tags:

c++

opencv

I'm looking for a correct way to measure openCV FPS. I've found several ways to do it. but none of them looks right for me.

The first one I've tested, uses time_t start and time_t end. I think that one is wrong once it returns me a dumped function as fps x time plot (I really can't imagine how a fps plot could be a dumped function).

Here the image of this plot.

FPS PLOT

The second I've tested uses t = (double)cvGetTickCount() to measure fps. This way is wrong once it returns 120 fps as result, but, for a 30 seconds length video captured with 120 fps shouldn't take more than 1 minute to be processed. so this is a wrong way to measure FPS.

Someone knows another way to measure FPS in openCV?

Ps. I'm trying to find circles in each frame of the video. The video frame size is 320x240 pixels.

Update 2 The code that I'm trying to measure FPS.

for(;;)
    {

        clock_t start=CLOCK();

        Mat frame, finalFrame;
        capture >> frame; 

        finalFrame = frame;

        cvtColor(frame, frame, CV_BGR2GRAY);

        GaussianBlur(frame, frame, Size(7,7), 1.5, 1.5);
        threshold(frame, frame, 20, 255, CV_THRESH_BINARY);

        dilate(frame, frame, Mat(), Point(-1, -1), 2, 1, 1);
        erode(frame, frame, Mat(), Point(-1, -1), 2, 1, 1);

        Canny(frame, frame, 20, 20*2, 3 );

        vector<Vec3f> circles;

        findContours(frame,_contours,_storage,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE );

        vector<vector<Point> > contours_poly( _contours.size() );
        vector<Rect> boundRect( _contours.size() );
        vector<Point2f>center( _contours.size() );
        vector<float>radius( _contours.size() );


        int temp = 0;

        for( int i = 0; i < _contours.size(); i++ )
        { 
            if( _contours[i].size() > 100 )
            {
               approxPolyDP( Mat(_contours[i]), contours_poly[i], 3, true );
               boundRect[i] = boundingRect( Mat(_contours[i]) );
               minEnclosingCircle( (Mat)_contours[i], center[i], radius[i] );
               temp = i;
               break;
            }
        }



        double dur = CLOCK()-start;
            printf("avg time per frame %f ms. fps %f. frameno = %d\n",avgdur(dur),avgfps(),frameno++ );

        frameCounter++;

        if(frameCounter == 3600)
        break;

        if(waitKey(1000/120) >= 0) break;
    }

Update

Program execution using the Zaw Lin method! enter image description here

like image 352
MSO Avatar asked Mar 03 '14 14:03

MSO


3 Answers

I have posted a way to do that @ Getting current FPS of OpenCV. It is necessary to do a bit of averaging otherwise the fps will be too jumpy.

edit

I have put a Sleep inside process() and it gives correct fps and duration(+/- 1ms).

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv/cv.h>
#include <sys/timeb.h>
using namespace cv;

#if defined(_MSC_VER) || defined(WIN32)  || defined(_WIN32) || defined(__WIN32__) \
    || defined(WIN64)    || defined(_WIN64) || defined(__WIN64__) 

#include <windows.h>
bool _qpcInited=false;
double PCFreq = 0.0;
__int64 CounterStart = 0;
void InitCounter()
{
    LARGE_INTEGER li;
    if(!QueryPerformanceFrequency(&li))
    {
        std::cout << "QueryPerformanceFrequency failed!\n";
    }
    PCFreq = double(li.QuadPart)/1000.0f;
    _qpcInited=true;
}
double CLOCK()
{
    if(!_qpcInited) InitCounter();
    LARGE_INTEGER li;
    QueryPerformanceCounter(&li);
    return double(li.QuadPart)/PCFreq;
}

#endif

#if defined(unix)        || defined(__unix)      || defined(__unix__) \
    || defined(linux)       || defined(__linux)     || defined(__linux__) \
    || defined(sun)         || defined(__sun) \
    || defined(BSD)         || defined(__OpenBSD__) || defined(__NetBSD__) \
    || defined(__FreeBSD__) || defined __DragonFly__ \
    || defined(sgi)         || defined(__sgi) \
    || defined(__MACOSX__)  || defined(__APPLE__) \
    || defined(__CYGWIN__) 
double CLOCK()
{
    struct timespec t;
    clock_gettime(CLOCK_MONOTONIC,  &t);
    return (t.tv_sec * 1000)+(t.tv_nsec*1e-6);
}
#endif

double _avgdur=0;
double _fpsstart=0;
double _avgfps=0;
double _fps1sec=0;

double avgdur(double newdur)
{
    _avgdur=0.98*_avgdur+0.02*newdur;
    return _avgdur;
}

double avgfps()
{
    if(CLOCK()-_fpsstart>1000)      
    {
        _fpsstart=CLOCK();
        _avgfps=0.7*_avgfps+0.3*_fps1sec;
        _fps1sec=0;
    }
    _fps1sec++;
    return _avgfps;
}

void process(Mat& frame)
{
    Sleep(3);
}
int main(int argc, char** argv)
{
    int frameno=0;
    cv::Mat frame;
    cv::VideoCapture cap(0);
    for(;;)
    {
        //cap>>frame;
        double start=CLOCK();
        process(frame);
        double dur = CLOCK()-start;
        printf("avg time per frame %f ms. fps %f. frameno = %d\n",avgdur(dur),avgfps(),frameno++ );
        if(waitKey(1)==27)
            exit(0);
    }
    return 0;
}    
like image 111
Zaw Lin Avatar answered Nov 09 '22 14:11

Zaw Lin


You can use opencv helper cv::getTickCount()

#include <iostream>
#include <string>

#include "opencv2/core.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/video.hpp"
#include "opencv2/highgui.hpp"

using namespace cv;


int main(int ac, char** av) {

    VideoCapture capture(0);
    Mat frame;

    for (;;) {

        int64 start = cv::getTickCount();

        capture >> frame;
        if (frame.empty())
            break;

        /* do some image processing here */

        char key = (char)waitKey(1);

        double fps = cv::getTickFrequency() / (cv::getTickCount() - start);
        std::cout << "FPS : " << fps << std::endl;
    }
    return 0;
}
like image 26
d00d Avatar answered Nov 09 '22 14:11

d00d


You can use OpenCV's API to get the original FPS if you are dealing with video files. The following method will not work when capturing from a live stream:

cv::VideoCapture capture("C:\\video.avi");
if (!capture.isOpened())
{
    std::cout  << "!!! Could not open input video" << std::endl;
    return;
}

std::cout << "FPS: " << capture.get(CV_CAP_PROP_FPS) << std::endl;

To get the actual FPS after the processing, you can try Zaw's method.

like image 1
karlphillip Avatar answered Nov 09 '22 12:11

karlphillip