Try this and look at elapsed time to compute fps. Then add other process.
Work with gray images from the beginning is a good idea. if faces images are in color save it in gray and use only gray images. Avoid the process repeats same things if not necessary.

import numpy as np
import cv2
import time 

cap = cv2.VideoCapture(0)

start_time = time.time()
end_time = start_time
elapsed_time = 0

font = cv2.FONT_HERSHEY_SIMPLEX
  
org = (50, 50)
fontScale = 1  
color = (255, 0, 0)
thickness = 2
   
while(True):

    start_time = time.time()
    
    # Capture frame-by-frame
    ret, frame = cap.read()

    # Our operations on the frame come here
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # Display the resulting frame

    cv2.putText(gray, str(1 / elapsed_time) + "fps", org, font, 
                   fontScale, color, thickness, cv2.LINE_AA)
    
    cv2.imshow('frame',gray)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

    end_time = time.time()
    elapsed_time = end_time - start_time


# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
Answer from Mario Abbruscato on Stack Overflow
🌐
Reddit
reddit.com › r/computervision › speeding up frame capture in opencv
r/computervision on Reddit: Speeding up frame capture in opencv
January 15, 2020 -

I'm working on an application in python using opencv for use in athletic coaching. I'd like it to run at 60fps, but I can't seem to get it to that speed. I've determined that the part that is slowing everything down is the capture process; frames aren't getting from the camera to the cpu fast enough. All testing I've done so far indicates that the processing and the rendering are not the bottleneck; it's specifically the video input that is slowing everything down.

Now, I know it is possible for the camera to run at 60fps, because when I open up the same camera in guvcview (at the same resolution), I can get a full 60fps.

I don't want to share my entire project, but here's the part that manages frame capture: https://pastebin.com/nnx32rQK. My main app calls the get_frame() function in its own thread. I'm running this on an intel NUC6CAYH (celeron CPU, 2.3 ghz), running linux.

Any help would be welcome!

EDIT: I went into more detail below, but it looks like having the cap.read() within the Feed class is a whole lot slower than just accessing cap.read() directly..... and I have no idea why

🌐
OpenCV
forum.opencv.org › python
OpenCV VideoCapture recording is sped up - Python - OpenCV
September 29, 2024 - I am trying to save some footage from a webcam but am coming across some issues. My webcam supports compressed (MJPG) and raw (YUYv 4:2:2) formats and I am trying to get MJPG due to the faster fps. I have simplified my code (below) and have reproduced the issue. import cv2 from datetime import datetime, timedelta fourcc = cv2.VideoWriter_fourcc(*'avc1') fn = "out.mp4" cap = cv2.VideoCapture(0, cv2.CAP_V4L2) #tried with and without cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*"MJPG...
Discussions

python - how to speed up video capture from webcam in opencv? - Stack Overflow
I need real time video capture i've tried reducing resolution, setting a static fps and none worked why am i getting a slow video feed although it says my fps is 30 i don't really know where exactl... More on stackoverflow.com
🌐 stackoverflow.com
How to increase the speed of Opencv "capture >> frame"
Hi folks, I am testing the TX2’s onboard CSI camera using Opencv3.2 with Gstreamer pipeline. Here is part of the code: ... src_selection = "nvcamerasrc ! video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080,format=(string)I420, framerate=(fraction)60/1 ! nvvidconv flip-method=2 ! ... More on forums.developer.nvidia.com
🌐 forums.developer.nvidia.com
7
0
July 9, 2017
python - Make faster videocapture opencv - Stack Overflow
So I create a Neural Network(CNN) that can predict in real-time using opencv the gender of a person, everything works perfect, but, when I run the code OpenCv has so much lag, my webcam is not that... More on stackoverflow.com
🌐 stackoverflow.com
python 3.x - how to make cv2.videoCapture.read() faster? - Stack Overflow
My question : I was working on my computer vision project. I use opencv(4.1.2) and python to implement it. I need a faster way to pass the reading frame into image processing on my Computer(Ubun... More on stackoverflow.com
🌐 stackoverflow.com
🌐
PyImageSearch
pyimagesearch.com › home › blog › faster video file fps with cv2.videocapture and opencv
Faster video file FPS with cv2.VideoCapture and OpenCV - PyImageSearch
April 17, 2021 - Figure 3: Utilizing threading with cv2.VideoCapture and OpenCV leads to higher FPS and a larger throughput rate. As we can see from the results we were able to process the entire 31 second video clip in 31.09 seconds — that’s an improvement ...
🌐
GeeksforGeeks
geeksforgeeks.org › python › faster-video-file-fps-with-cv2-videocapture-and-opencv
Faster video file FPS with cv2.VideoCapture and OpenCV - GeeksforGeeks
July 23, 2025 - To increase the video FPS in Python, we will use cv2.VideoCapture function of the OpenCV library. This can be done by reading the frames of the input video at a certain FPS and writing them to an output video file at a higher FPS.
🌐
NVIDIA Developer Forums
forums.developer.nvidia.com › robotics & edge computing › jetson systems › jetson tx2
How to increase the speed of Opencv "capture >> frame" - Jetson TX2 - NVIDIA Developer Forums
July 9, 2017 - Hi folks, I am testing the TX2’s onboard CSI camera using Opencv3.2 with Gstreamer pipeline. Here is part of the code: ... src_selection = "nvcamerasrc ! video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080,format=(string)I420, framerate=(fraction)60/1 ! nvvidconv flip-method=2 ! ...
🌐
Pysource
pysource.com › home › blog › increase opencv speed by 2x with python and multithreading | tutorial
Increase OpenCV speed by 2x with Python and Multithreading | Tutorial - Pysource
October 15, 2024 - Therefore, speeding up OpenCV is not just a luxury but often a necessity. In this article, we’ll walk through code examples and use multi-threading to significantly improve processing speed.
Top answer
1 of 1
4

I've had this same problem using openCV video capture with text-detection. It's not the webcam quality, but the fact that openCV can only show you frames as fast as you can process them in your gender detection. The solution that worked for me is to use multi-threading.

You can create a thread for the OpenCV video capture, then another thread for your image processing. The caveat: you can't magically make your image processing happen quicker without making changes the image process itself. It takes as long as it takes. What you can do is allow openCV to work on its own and send the frames to an exchange class, then allow the image processing to grab a frame and work at its own pace as CV2 continues as normal.

Here is a (shortened) version of my class for OCR image processing. You can see that in start() i'm creating a thread pointed at the ocr() process. This is where your gender identification process can go.

class OCR:

    # def __init__(self, exchange: VideoStream, language=None):
    def __init__(self):
        self.exchange = None
        # init stuff for OCR not relevant to my example, but note that it 
        # takes a VideoStream class called exchange which is where this class 
        # grabs frames to process

    def start(self):
        Thread(target=self.ocr, args=()).start()
        return self

    def set_exchange(self, video_stream):
        self.exchange = video_stream

    def ocr(self):

        while not self.stopped:
            if self.exchange is not None:
                frame = self.exchange.frame

                # # # OCR stuff goes here

Now here is the VideoStream class that grabs frames at its own pace, in a different thread. The image processing class (OCR) can then take these frames at it's own pace and the two don't affect each other's performance.

class VideoStream:
    """Class for CV2 video capture. The start() method will create a new 
thread to read the video stream"""
    def __init__(self, src=0):
        self.stream = cv2.VideoCapture(src)
        (self.grabbed, self.frame) = self.stream.read()
        # self._boxes = None
        self.stopped = False

    def start(self):
        Thread(target=self.get, args=()).start()
        return self

    def get(self):
        while not self.stopped:
            (self.grabbed, self.frame) = self.stream.read()

    def get_video_dimensions(self):
        width = self.stream.get(cv2.CAP_PROP_FRAME_WIDTH)
        height = self.stream.get(cv2.CAP_PROP_FRAME_HEIGHT)
        return int(width), int(height)

    def stop_process(self):
        self.stopped = True

Then you can do your CV2 imshow loop as you normally would.

exchange = VideoStream(0).start()
ocr = OCR().start()
ocr.set_exchange(exchange)

 while True:  # Begins a loop for the real-time OCR display
        pressed_key = cv2.waitKey(1) & 0xFF
        if pressed_key == ord('q'):
            stop_stream_ocr(exchange, ocr)
            break

        frame = exchange.frame 

        cv2.imshow("Video Get Frame", frame)
        cps1.increment()

Note that you can't really control what thread CV2 decides to use in its internal workings, but this approach will allow you to display your webcam at its natural fps and while image processing happens in the background.

Find elsewhere
Top answer
1 of 4
5

This comes a bit late, but I was wondering this with my Logitech C920 HD Pro USB-camera on Ubuntu 20.04 and OpenCV. I tried to command the capture session to run Full HD @ 30 FPS but the FPS was fluctuating between 4-5 FPS.

The capture format for my camera defaulted as "YUYV 4:2:2". No matter how I tried to alter the video capture settings, OpenCV did not magically change the video format to match e.g. the desired FPS setting.

When I listed the video formats for my Logitech C920, it revealed:

ubuntu:~$ v4l2-ctl --list-formats-ext

ioctl: VIDIOC_ENUM_FMT
    Type: Video Capture

    [0]: 'YUYV' (YUYV 4:2:2)
<clip>
        Size: Discrete 1600x896
            Interval: Discrete 0.133s (7.500 fps)
            Interval: Discrete 0.200s (5.000 fps)
        Size: Discrete 1920x1080
            Interval: Discrete 0.200s (5.000 fps)
        Size: Discrete 2304x1296
            Interval: Discrete 0.500s (2.000 fps)
    [1]: 'MJPG' (Motion-JPEG, compressed)
<clip>
        Size: Discrete 1920x1080
            Interval: Discrete 0.033s (30.000 fps)
            Interval: Discrete 0.042s (24.000 fps)
            Interval: Discrete 0.050s (20.000 fps)
            Interval: Discrete 0.067s (15.000 fps)
            Interval: Discrete 0.100s (10.000 fps)
            Interval: Discrete 0.133s (7.500 fps)
            Interval: Discrete 0.200s (5.000 fps)

The solution was to manually command the OpenCV capture device to use the compressed 'MJPG' format:

import numpy as np
import cv2

capture = cv2.VideoCapture(0)
W, H = 1920, 1080
capture.set(cv2.CAP_PROP_FRAME_WIDTH, W)
capture.set(cv2.CAP_PROP_FRAME_HEIGHT, H)
capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
capture.set(cv2.CAP_PROP_FPS, 30)
2 of 4
2

In my case, I have set camera like this (in c++ code):

// cam is cv::VideoCapture object
cam.set(cv::CAP_PROP_BUFFERSIZE, 1);
cam.set(cv::CAP_PROP_FPS, 20); // set fps before set fourcc
cam.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'));

CAP_PROP_BUFFERSIZE doesn't matter, but CAP_PROP_FPS must be set before CAP_PROP_FOURCC.
By this setup, my camera fps increases from 5 to 20.

🌐
OpenCV
forum.opencv.org › python
Capture speed / framerate of cv2.VideoCapture - Python - OpenCV
October 16, 2021 - Hi all, I’ve been playing around with python, opencv, a raspberry 4 and a “pi hq cam”. The thing is, the time it takes to capture is really long. The pi cam could, in theory, do 1920x1080@30fps. I’m not aiming for that but what I’m getting is more like 2-3 fps when using videocapture.
🌐
OpenCV Q&A Forum
answers.opencv.org › question › 215586 › why-does-videocapture1-take-so-long
Why does VideoCapture(1) take so long? - OpenCV Q&A Forum
July 12, 2019 - It seems like it takes forever for my external webcam to actually take the picture. As soon as the picture is taken, it works. When I set it to VideoCapture(0), it works much faster but I need to use my external webcam instead so I have to set it to VideoCapture(1). Does anyone know how to speed up this process?
🌐
OpenCV
forum.opencv.org › python
Help with optimization opencv videocapture optical flow analysis - Python - OpenCV
March 28, 2024 - Hello, I am now using python opencv in docker to analyse video files. There are about 24 files of 1 hour on which i do movement analysis with nvidia optical flow. However it takes about 40 minutes to analyze one day (24 hours, so 24 files of 1 hour). I would like this to speed up, i now do ...
🌐
Piborg
forum.piborg.org › node › 2363
Faster video processing | PiBorg
We usually run four at the same time, but you should be able to have any number from one upwards :) ... # Imports import cv2 import time import threading # Camera settings go here imageWidth = ... imageHeight = ... frameRate = ... processingThreads = 4 # Shared values global running global cap global frameLock global processorPool running = True # Setup the camera cap = cv2.VideoCapture(0) cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, imageWidth); cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, imageHeight); cap.set(cv2.cv.CV_CAP_PROP_FPS, frameRate); if not cap.isOpened(): cap.open() # Image processing th
Top answer
1 of 4
43

My hypothesis is that the jitter is most likely due to network limitations and occurs when a frame packet is dropped. When a frame is dropped, this causes the program to display the last "good" frame which results in the display freezing. This is probably a hardware or bandwidth issue but we can alleviate some of this with software. Here are some possible changes:

1. Set maximum buffer size

We set the cv2.videoCapture() object to have a limited buffer size with the cv2.CAP_PROP_BUFFERSIZE parameter. The idea is that by limiting the buffer, we will always have the latest frame. This can also help to alleviate the problem of frames randomly jumping ahead.

2. Set frame retrieval delay

Currently, I believe the read() is reading too fast even though it is in its own dedicated thread. This may be one reason why all the frames appear to pool up and suddenly burst in the next frame. For instance, say in a one second time interval, it may produce 15 new frames but in the next one second interval, only 3 frames are returned. This may be due to the network packet frame loss so to ensure that we obtain constant frame rates, we simply add a delay in the frame retrieval thread. A delay to obtain roughly ~30 FPS does a good job to "normalize" the frame rate and smooth the transition between frames incase there is packet loss.

Note: We should try to match the frame rate of the stream but I'm not sure what the FPS of the webcam is so I just guessed 30 FPS. Also, there is usually a "direct" stream link instead of going through a intermediate webserver which can greatly improve performance.


If you try using a saved .mp4 video file, you will notice that there is no jitter. This confirms my suspicion that the problem is most likely due to network latency.

from threading import Thread
import cv2, time

class ThreadedCamera(object):
    def __init__(self, src=0):
        self.capture = cv2.VideoCapture(src)
        self.capture.set(cv2.CAP_PROP_BUFFERSIZE, 2)
       
        # FPS = 1/X
        # X = desired FPS
        self.FPS = 1/30
        self.FPS_MS = int(self.FPS * 1000)
        
        # Start frame retrieval thread
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True
        self.thread.start()
        
    def update(self):
        while True:
            if self.capture.isOpened():
                (self.status, self.frame) = self.capture.read()
            time.sleep(self.FPS)
            
    def show_frame(self):
        cv2.imshow('frame', self.frame)
        cv2.waitKey(self.FPS_MS)

if __name__ == '__main__':
    src = 'https://videos3.earthcam.com/fecnetwork/9974.flv/chunklist_w1421640637.m3u8'
    threaded_camera = ThreadedCamera(src)
    while True:
        try:
            threaded_camera.show_frame()
        except AttributeError:
            pass

Related camera/IP/RTSP/streaming, FPS, video, threading, and multiprocessing posts

  1. Python OpenCV streaming from camera - multithreading, timestamps

  2. Video Streaming from IP Camera in Python Using OpenCV cv2.VideoCapture

  3. How to capture multiple camera streams with OpenCV?

  4. OpenCV real time streaming video capture is slow. How to drop frames or get synced with real time?

  5. Storing RTSP stream as video file with OpenCV VideoWriter

  6. OpenCV video saving

  7. Python OpenCV multiprocessing cv2.VideoCapture mp4

2 of 4
8

Attempt at threading

I've attempted this solution from nathancy with minor success.

It involves:

  • creating a separate thread for image capture from the source
  • using the main thread exclusively for display.

Code:

import cv2
from threading import Thread

class ThreadedCamera(object):
    def __init__(self, source = 0):

        self.capture = cv2.VideoCapture(source)

        self.thread = Thread(target = self.update, args = ())
        self.thread.daemon = True
        self.thread.start()

        self.status = False
        self.frame  = None

    def update(self):
        while True:
            if self.capture.isOpened():
                (self.status, self.frame) = self.capture.read()

    def grab_frame(self):
        if self.status:
            return self.frame
        return None  
if __name__ == '__main__':
    stream_link = "https://videos3.earthcam.com/fecnetwork/9974.flv/chunklist_w1421640637.m3u8"
    streamer = ThreadedCamera(stream_link)

    while True:
        frame = streamer.grab_frame()
        if frame is not None:
            cv2.imshow("Context", frame)
        cv2.waitKey(1) 

Jittery, but real-time results

.

The streaming works. It maintains real-time. However, it is as if all the frames pool up and suddenly burst into the video. I would like somebody to explain that.

Room for improvement

The real-time stream can be found here.

https://www.earthcam.com/usa/newyork/timessquare/?cam=tsstreet

This site is scraped for the m3u8 using python's streamlink stream scraper.


import streamlink

streams = streamlink.streams("https://www.earthcam.com/usa/newyork/timessquare/?cam=tsstreet")
print(streams)

which yeilds:

OrderedDict([

('720p',<HLSStream('https://videos3.earthcam.com/fecnetwork/9974.flv/chunklist_w202109066.m3u8')>),

('live', <RTMPStream({'rtmp': 'rtmp://videos3.earthcam.com/fecnetwork/', 'playpath': '9974.flv', 'pageUrl': 'https://www.earthcam.com/usa/newyork/timessquare/?cam=tsstreet','swfUrl': 'http://static.earthcam.com/swf/streaming/stream_viewer_v3.swf', 'live': 'true'}, redirect=False>),

('worst', <HLSStream('https://videos3.earthcam.com/fecnetwork/9974.flv/chunklist_w202109066.m3u8')>),

('best', <RTMPStream({'rtmp': 'rtmp://videos3.earthcam.com/fecnetwork/', 'playpath': '9974.flv', 'pageUrl': 'https://www.earthcam.com/usa/newyork/timessquare/?cam=tsstreet', 'swfUrl': 'http://static.earthcam.com/swf/streaming/stream_viewer_v3.swf', 'live': 'true'}, redirect=False>)

])


The possibility that the streams are being read wrong.

🌐
Reddit
reddit.com › r/opencv › [question] can you fast forward fps when doing work on video?
r/opencv on Reddit: [Question] Can you fast forward FPS when doing work on video?
September 15, 2020 -

Hey everyone!

I'm doing some work where I need to load in a video file. The work is simple enough, but it still takes a long time to complete due to the video being a long video.

For example if I wanted to work with a video that is 15 minutes long, my program goes through the whole video with a fixed framerate, and takes 15 minutes to complete. So I thought that there must be a better way of doing this. Maybe increasing the frame rate in the original video?

The captured frame rate varies, but is usually 30 fps.

I'm looping over each frame like this:

cap = cv2.VideoCapture("photos/football.mp4")
while(cap.isOpened()):
    ret, frame = cap.read()
    # Do work
vs.release()
cv2.destroyAllWindows()

I hope you understand what I mean, and have some tips that can help me !

Top answer
1 of 2
4

Most often, people don't consider the data rate (bandwidth) required to get their data across the wire.

1920 x 1080 pixels at 30 FPS with 24 bits per pixel would require 1.5 Gbit/s. That won't fit through USB 2.

That is why many webcams implement compression. A common compression is MJPEG, which is JPEG as video.

You can tell OpenCV to tell the media API (V4L, dshow, MSMF, AVFoundation...) to request that from the camera. It won't on its own, I have learned.

# cap = cv.VideoCapture(...)
cap.set(cv.CAP_PROP_FOURCC, cv.VideoWriter_fourcc(*"MJPG"))

Less data per frame means the transfer goes faster, allowing more frames per time.

When mixing that with other properties (FRAME_WIDTH etc), order matters. I believe the FOURCC setting needs to come first, but if that doesn't help, try other orders.

When a webcam notices that there isn't enough free data rate on the USB controller, it may decide to reduce frame size or frame rate, or apply stronger compression (worse pictures). When you attach multiple cameras to the same USB hub, this will happen. This negotiation may cause opening to take several seconds, a minute even. If opening the camera is slow, maybe the USB controller already has some bandwidth reservations for other devices.


What does affect frame rate is when your other code in that loop simply takes a lot of time! Can't work around that, except to make that part of the code faster.

What will not generally matter is moving the reading into its own thread. In the OpenCV case (with imshow), a thread makes no sense at all. A thread only makes sense if there's anything else to be done with the time ordinarily spent waiting, besides processing the next frame (e.g. a GUI loop). Communication with consumers needs to be proper. Busy loops aren't the solution.

In the case of actual GUIs (not OpenCV's imshow), the proper thing to do is a thread, but it needs to update the widget as a frame comes in. There must not be any spinning loop that repeatedly reads a variable and assigns a widget's image or anything.

The camera will produce frames at its own pace (no matter what you do), and put them into a queue. Reading a frame costs fairly little (but not nothing).

You must read from the camera, or else the frames queue up. If you read slower than the camera's frame rate, you'll see increasing latency, i.e. movement in front of the camera takes seconds to show up on your screen.

If you try to read quicker, the read() call will just block until a frame is available. Then you'll "waste" time in that call. What would you do with that time? You don't have new data yet, so there's nothing to compute, until that frame arrives. Might as well wait, right?

2 of 2
2

One potential reason could because of I/O latency when reading frames. Since cv2.VideoCapture().read() is a blocking operation, the main program is stalled until the frame is read from the camera device and returned. A method to improve performance would be to spawn another thread to handle grabbing frames in parallel instead of relying on a single thread to grab frames in sequential order. We can improve performance by creating a new thread that only polls for new frames while the main thread handles processing the current frame. Here's a snippet for multithreading frames.

from threading import Thread
import cv2, time

class VideoStreamWidget(object):
    def __init__(self, src=0):
        self.capture = cv2.VideoCapture(src)
        # Start the thread to read frames from the video stream
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True
        self.thread.start()

    def update(self):
        # Read the next frame from the stream in a different thread
        while True:
            if self.capture.isOpened():
                (self.status, self.frame) = self.capture.read()
            time.sleep(.01)

    def show_frame(self):
        # Display frames in main program
        cv2.imshow('frame', self.frame)
        key = cv2.waitKey(1)
        if key == ord('q'):
            self.capture.release()
            cv2.destroyAllWindows()
            exit(1)

if __name__ == '__main__':
    video_stream_widget = VideoStreamWidget()
    while True:
        try:
            video_stream_widget.show_frame()
        except AttributeError:
            pass
🌐
OpenCV
forum.opencv.org › android/java
How to get faster/lighter video decoding - Android/Java - OpenCV
September 16, 2021 - Hello and thank you in advance for your help! I’m building a simple app at Windows using Intellij and gradle that its purpose is to be able to show a couple, or maybe more, videos (mp4) simultaneously. The code is pretty simple, I am using a thread for capturing a frame and then I use the ...
🌐
Stack Overflow
stackoverflow.com › questions › 69620079 › video-recording-is-too-fast-in-opencv
python - Video Recording is too fast in opencv - Stack Overflow
VideoCapture gives you the data ... "playback" to be at a certain speed, you have to vary the argument to waitKey according to when the next frame is due to be displayed....