简体   繁体   中英

Measure OpenCV FPS

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.

帧率图

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!在此处输入图片说明

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;
}    

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.

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;
}

I would just measure the walltime and simply divide the frames by time elapsed. On linux:

/*
* compile with:
*   g++ -ggdb webcam_fps_example2.cpp -o webcam_fps_example2 `pkg-config --cflags --libs opencv`
*/

#include "opencv2/opencv.hpp"
#include <time.h>
#include <sys/time.h>


using namespace cv;
using namespace std;

double get_wall_time(){
    struct timeval time;
    if (gettimeofday(&time,NULL)){
        //  Handle error
        return 0;
    }
    return (double)time.tv_sec + (double)time.tv_usec * .000001;
}


int main(int argc, char** argv)
{
    VideoCapture cap;
    // open the default camera, use something different from 0 otherwise;
    // Check VideoCapture documentation.
    if(!cap.open(0))
        return 0;

    cap.set(CV_CAP_PROP_FRAME_WIDTH,1920);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT,1080);

    double wall0 = get_wall_time();
    for(int x = 0; x < 500; x++)
    {
          Mat frame;
          cap >> frame;
          if( frame.empty() ) break; // end of video stream
          //imshow("this is you, smile! :)", frame);
          if( waitKey(10) == 27 ) break; // stop capturing by pressing ESC 
    }
    double wall1 = get_wall_time();
    double fps = 500/(wall1 - wall0);
    cout << "Wall Time = " << wall1 - wall0 << endl;
    cout << "FPS = " << fps << endl;
    // the camera will be closed automatically upon exit
    // cap.close();
    return 0;
}

Wall Time = 43.9243 FPS = 11.3832

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM