You need to move this line up, outside your acquisition loop:
cap = cv2.VideoCapture(0)
It does a one-time only initialisation.
Answer from Mark Setchell on Stack OverflowIncrease Camera FPS OpenCV python
opencv with the camera framerate 120 FPS
IMX298 low FPS with OpenCV
python - low fps by using cv2.VideoCapture - Stack Overflow
You need to move this line up, outside your acquisition loop:
cap = cv2.VideoCapture(0)
It does a one-time only initialisation.
I know I'm late but, if anyone else is facing this...
Check if you're using the right codec. In my case for a Logitech OrbiCam I had to set it to MJPG:
For C++:
cv::VideoCapture camera;
camera.open(0);
auto codec = cv::VideoWriter::fourcc('M','J','P','G');
camera.set(cv::CAP_PROP_FOURCC, codec);
In Python:
import cv2
camera = cv2.VideoCapture(0)
camera.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('m','j','p','g'))
For Kotlin:
var capture: VideoCapture = VideoCapture()
camera.open(deviceId)
val mjpg = VideoWriter.fourcc('M', 'J', 'P', 'G')
capture.set(Videoio.CAP_PROP_FOURCC, mjpg.toDouble())
etc...
...and then set your target resolution
I'm currently learning how to do hand recognition with OpenCV and Mediapipe on Python
However, the course video shows the instructor getting a full 30-40 FPS, but however, I can't seem to reach 30. It's somehow capped 15 FPS. (Logitech C270 webcam) Any ideas?
OpenCV comes with prebuild libraries. When you use them in an application you actually want to deploy make sure you use the release libraries. In debug mode you have lots of additional checks in the form of asserts as well as debug symbols allowing you to step into the libraries with a debugger that are removed in release mode.
Another more specific advise regarding the code you posted: Avoid calls to cv::waitKey() as every single call, who would have guessed, makes your main thread wait the specified amount of time in milliseconds. Do not drop calls to it entirely as e.g. cv::imshow() will only work appropriately with these in place.
Edit:
Reduce your while loop to:
while ( true ) {
capture >> cap_img;
imshow("Result", cap_img);
if(waitKey(1) == 27)
break;
}
When you know how much time you need for capturing the image and just displaying it, then you can compare how much of an impact whatever algorithm you are running has on your performance.
Here is solution...everytime you read!!!..everytime you use vcap>>cap or cap.read(vcap)... you must set FPS ..25 is max..if i try to set 26 or higher it runs slow. ...this runs 30 fps for me If you not set FPS...it runs slow too
if (cap.read(vcap)){
imshow("Cam Feed", vcap);
cap.set(CV_CAP_PROP_FPS, 25);
}
Setting a frame rate doesn't always work like you expect. It depends on two things:
- What your camera is capable of outputting.
- Whether the current capture backend you're using supports changing frame rates.
So point (1). Your camera will have a list of formats which it is capable of delivering to a capture device (e.g. your computer). This might be 1920x1080 @ 30 fps or 1920x1080 @ 60 fps and it also specifies a pixel format. The vast majority of consumer cameras do not let you change their frame rates with any more granularity than that. And most capture libraries will refuse to change to a capture format that the camera isn't advertising.
Even machine vision cameras, which allow you much more control, typically only offer a selection of frame rates (e.g. 1, 2, 5, 10, 15, 25, 30, etc). If you want a non-supported frame rate at a hardware level, usually the only way to do it is to use hardware triggering.
And point (2). When you use cv.VideoCapture you're really calling a platform-specific library like DirectShow or V4L2. We call this a backend. You can specify exactly which backend is in use by using something like:
cv2.VideoCapture(0 + cv2.CAP_DSHOW)
There are lots of CAP_X's defined, but only some will apply to your platform (e.g CAP_V4L2 is for Linux only). On Windows, forcing the system to use DirectShow is a pretty good bet. However as above, if your camera only reports it can output 30fps and 60fps, requesting 10fps will be meaningless. Worse, a lot of settings simply report True in OpenCV when they're not actually implemented. You've seen that most of the time reading parameters will give you sensible results though, however if the parameter isn't implemented (e.g exposure is a common one that isn't) then you might get nonsense.
You're better off waiting for a period of time and then reading the last image.
Be careful with this strategy. Don't do this:
while capturing:
res, image = cap.read()
time.sleep(1)
you need to make sure you're continually purging the camera's frame buffer otherwise you will start to see lag in your videos. Something like the following should work:
frame_rate = 10
prev = 0
while capturing:
time_elapsed = time.time() - prev
res, image = cap.read()
if time_elapsed > 1./frame_rate:
prev = time.time()
# Do something with your image here.
process_image()
For an application like a hand detector, what works well is to have a thread capturing images and the detector running in another thread (which also controls the GUI). Your detector pulls the last image captured, runs and display the results (you may need to lock access to the image buffer while you're reading/writing it). That way your bottleneck is the detector, not the performance of the camera.
I could not set the FPS for my camera so I manage to limit the FPS based on time so that only 1 frame per second made it into the rest of my code. It is not exact, but I do not need exact, just a limiter instead of 30fps. HTH
import time
fpsLimit = 1 # throttle limit
startTime = time.time()
cv = cv2.VideoCapture(0)
While True:
frame = cv.read
nowTime = time.time()
if (int(nowTime - startTime)) > fpsLimit:
# do other cv2 stuff....
startTime = time.time() # reset time