How to set camera fps with opencv

Hi, I want to set camera fps with opencv.
I don’t know if using cv::waitKey() is good idea to set it.
For example I have video 10fps and when I get the fps I have only 9fps.
I want to set the camera to for example 30fps and capture image every 10fps for example.

      {
       cv::VideoCapture cap(0,200);
        int fps = 10;
        double fps2 = cap.get(cv::CAP_PROP_FPS);
        std::cout << "fps2 : " << fps2 << std::endl;

        if (!cap.isOpened())
        {
            cap.release();
            return -1;
        }

        std::chrono::time_point<std::chrono::high_resolution_clock>
                   prev_frame_time(std::chrono::high_resolution_clock::now());
        std::chrono::time_point<std::chrono::high_resolution_clock>
                           new_frame_time;

        cv::Mat frame;
        while (true)
        {
            if (videoCapture.read(frame) == false)
            {
                if (frame.empty())
                {
                	break;
                }
            }
            else
            {
            	imshow("Frame", frame);

            }

            int key = cv::waitKey(1000/fps);
            if (key % 256 == key_esc)
            {
            	break; // (27)escape key
            }

            new_frame_time = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> duration1(new_frame_time - prev_frame_time);
            int fps = int(1/duration1.count());
            std::cout << "fps : " << fps << std::endl;

            prev_frame_time = new_frame_time;
        }

        cap.release();
}

use cap->set(CAP_PROP_FPS, fps);

it seems that cap->set(CAP_PROP_FPS, fps); doesn’t work to set camera ?

exact brand and model of camera, and exact code you tried to use, including the concrete value for fps?

I’am using a webcam or my phone camera. My camera fps is 30fps
But I want to set the framerate to 10 for example.

#include <chrono>
#include <ctime>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/videoio.hpp>
#include <iostream>


int main(int argc, const char ** argv)
{
       cv::VideoCapture cap(0,200);
        int fps = 10;
        double fps2 = cap.get(cv::CAP_PROP_FPS);
        std::cout << "fps2 : " << fps2 << std::endl;

        if (!cap.isOpened())
        {
            cap.release();
            return -1;
        }

        std::chrono::time_point<std::chrono::high_resolution_clock>
                   prev_frame_time(std::chrono::high_resolution_clock::now());
        std::chrono::time_point<std::chrono::high_resolution_clock>
                           new_frame_time;

        cv::Mat frame;
        while (true)
        {
            if (videoCapture.read(frame) == false)
            {
                if (frame.empty())
                {
                	break;
                }
            }
            else
            {
            	imshow("Frame", frame);

            }

            int key = cv::waitKey(1000/fps);
            if (key % 256 == key_esc)
            {
            	break; // (27)escape key
            }

            new_frame_time = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> duration1(new_frame_time - prev_frame_time);
            int fps = int(1/duration1.count());
            std::cout << "fps : " << fps << std::endl;

            prev_frame_time = new_frame_time;
        }

        cap.release();
 return 0;
}

a camera might just not support a specific frame rate. professional cameras are more flexible there. random webcams have a handful of frame rates they accept.

integer rounding. that’s what gives you “9” when the rate should be something close to 10 fps, because the calculation might be exactly 9.99. use proper rounding instead, or print floating point values.

you can’t throttle cameras. they produce frames at a fixed rate. you must read them all. if you don’t, they queue up, and that will cause problems, ranging from high latency (picture is several seconds old) to the device driver giving up and crashing your program.

what you do with waitKey there is a bad idea because of that. it’s best to use the lowest wait time possible here, which is 1 (or use pollKey()). you don’t have to spend all idle time in waitKey. it only has to be entered periodically to keep the GUI window somewhat responsive.

the cap.read() call will wait anyway, if new frames aren’t yet available.

if you need to do that, run a thread. the thread only reads frames from the camera and puts them somewhere. such a thread could read three frames, and then put one of them into a queue. that would turn 30 fps into 10 fps. your other code could then read from that queue.

Hi,
Thank you very much for you answers.
I read in other forum about the thread way but I want to try without thread.

what you do with waitKey there is a bad idea because of that . it’s best to use the lowest wait time possible here, which is 1 (or use pollKey() ). you don’t have to spend all idle time in waitKey . it only has to be entered periodically to keep the GUI window somewhat responsive.

Can you be more precise ?I did not understand everything this part cleary.

I modify my code to do something like this instead of using waitKey()

#include <chrono>
#include <ctime>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/videoio.hpp>
#include <iostream>


int main(int argc, const char ** argv)
{
       cv::VideoCapture cap(0,200);
        int fpsCamera = 30;
int fpsCapture = 10;
        double fps2 = cap.get(cv::CAP_PROP_FPS);
        std::cout << "fps2 : " << fps2 << std::endl;

        if (!cap.isOpened())
        {
            cap.release();
            return -1;
        }

        std::chrono::time_point<std::chrono::high_resolution_clock>
                   prev_frame_time(std::chrono::high_resolution_clock::now());
        std::chrono::time_point<std::chrono::high_resolution_clock>
                           new_frame_time;

        cv::Mat frame;
        while (true)
        {
            if (videoCapture.read(frame) == false)
            {
                if (frame.empty())
                {
                	break;
                }
            }

            new_frame_time = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> duration1(new_frame_time - prev_frame_time);
            double fps = 1/duration1.count();
            std::cout << "fps : " << fps << std::endl;

            if(duration1.count() > 1/fpsCapture)
              {
                        	prev_frame_time = new_frame_time;
                  
            	imshow("Frame", frame);
            }

            int key = cv::waitKey(1000/fpsCamera );
            if (key % 256 == key_esc)
            {
            	break; // (27)escape key
            }
        }

        cap.release();
 return 0;
}

I don’t know if it’s the write way.