I’m capturing from a global-shutter, b&w uvc camera.
On Linux and Windows I can capture about 120 fps which the camera is advertised at but under Mac OS I can only get 60 fps.
Does the camera suck or does my OS suck?
import cv2
import time
cap = cv2.VideoCapture(0)
cap.grab()
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 800)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 600)
cap.set(cv2.CAP_PROP_BUFFERSIZE, 100)
cap.set(cv2.CAP_PROP_FPS, 120)
prevTime = 0
currTime = 0
fps = 0
f = 0
total_fps = 0
print(f"CV@ Version: {cv2.__version__}")
print(f" Current Time Previous Time Difference FPS")
while cap.isOpened():
if f > 20:
break
currTime = time.time()
diff = currTime - prevTime
fps = 1 / (diff)
prevTime = currTime
total_fps += fps
if f> 0:
print(f"frame #: {f:2.0f} {currTime:10.9f} {prevTime:10.9f} diff: {diff:10.9f} FPS: {fps}")
f += 1
ret, frame = cap.read()
if not ret:
break
cv2.imshow("frame", frame)
if cv2.waitKey(1) == ord("q"):
break
avg = total_fps/f
print(f"avg fps: {avg:2.0f} ")
cap.release()
cv2.destroyAllWindows()
and never ever use time.time() for such measurements. use time.perf_counter() or time.perf_counter_ns(). and remember, things on a computer run in time slices. anything can happen to be delayed by some amount of time, sometimes by whole time quanta (time slices)
that is good, but maybe the code has to be capitalized like cv.VideoWriter.fourcc(*"MJPG")
also put this set() call last. one of those orders should work, but the order matters, so any other order might fail to set this mode.
remove the waitKey() and imshow() and other GUI presentation. then do your timing. waitKey might cause a delay of an entire scheduler time slice, which can be on the order of 64 fps, e.g. on Windows.
To me it looks like it’s purely the waitkey().
But if I remove the waitkey, I dont see any imshow window at all.
waitkey takes an integer, If waitkey <= 0 it waits indefinitely, so I can only capture blindly?
Neither the order or the lower/uppercase seems to make a difference.
Even when writing the file I now see 120 fps calculated.
[ WARN:0@0.017] global cap_gstreamer.cpp:1173 isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created
CV Version: 4.10.0-dev
FPS: per cap.get(cv2.CAP_PROP_FPS): 120.00048, calculated: 108
FPS: per cap.get(cv2.CAP_PROP_FPS): 120.00048, calculated: 122
FPS: per cap.get(cv2.CAP_PROP_FPS): 120.00048, calculated: 122
FPS: per cap.get(cv2.CAP_PROP_FPS): 120.00048, calculated: 121
FPS: per cap.get(cv2.CAP_PROP_FPS): 120.00048, calculated: 122
FPS: per cap.get(cv2.CAP_PROP_FPS): 120.00048, calculated: 120
swap waitKey() for pollKey(), which is supposed to be the alternative that doesn’t wait for something to happen.
very likely it’s a fallback to waitKey(1), and will behave accordingly. I don’t know if anyone has implemented it properly yet. AFAIK pollKey only does anything special on Win32. if you know some Apple GUI programming, you can dig around in OpenCV’s highgui and implement pollKey() yourself.
or you can display every other, third, … frame only.
or you can use Apple-native APIs yourself to do the GUI.
ok, (as far as the imshow limitation) that’s fine. For now I just want to validate that these cheap cameras work as advertised and I can get enough data out of them.
I can work on the GUI later after I process the very short (< 3sec sports movement) captures.
if you know some cocoa, here are the relevant places in the code, and example code for the Win32 backend:
so there’ll have to be some new pollkey function and I guess it’ll have to be stated in whatever defines the cocoa backend.
the cocoa backend sleeps like this: [NSThread sleepForTimeInterval:1/100.];
so I guess you could copy the entire cocoa waitkey function and strip it down like I did the win32 waitkey function, to build a pollkey function out of it.