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.

Answer from raspberry_next 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
Capture speed / framerate of cv2.VideoCapture - Python - OpenCV
October 16, 2021 - Hi all, I’ve been playing around ... theory, do 1920x1080@30fps. I’m not aiming for that but what I’m getting is more like 2-3 fps when using videocapture....
Discussions

OpenCV VideoCapture recording is sped up - Python - OpenCV
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 ... More on forum.opencv.org
🌐 forum.opencv.org
0
September 29, 2024
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
Increase the capture and stream speed of a video using OpenCV and Python - Stack Overflow
OpenCV real time streaming video capture is slow. How to drop frames or get synced with real time? (4 answers) Closed 3 years ago. I need to take a video and analyze it frame-by-frame. This is what I have so far: ... cap = cv2.VideoCapture(CAM) # CAM = path to the video cap.set(cv2.CAP_PRO... 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 - The actual frame throughput processing rate is much faster, clocking in at 30.75 frames per second, an improvement of 52.15%. Threading can dramatically improve the speed of your video processing pipeline — use it whenever you can.
🌐
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...
🌐
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 ! ...
🌐
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.
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
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.

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.

🌐
GitHub
github.com › opencv › opencv › issues › 19740
VideoCapture faster than imread when reading image files · Issue #19740 · opencv/opencv
March 17, 2021 - I assume cv2.imread() is the faster/preferred method for loading images but cv2.VideoCapture is approximately 0.002 milliseconds faster per image/frame.
Author: opencv
🌐
OpenCV
forum.opencv.org › python
Help with optimization opencv videocapture optical flow analysis - Python - OpenCV
March 28, 2024 - 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 ...
🌐
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 - In this article, we’ll walk through code examples and use multi-threading to significantly improve processing speed. Let’s start by looking at the basics of OpenCV Multithreading, a linear method for capturing and displaying video frames using OpenCV. Below is a simple Python code snippet that illustrates this: import cv2 # Create a capture object to load the video cap = cv2.VideoCapture('sea.mp4') while True: ret, frame = cap.read() # Capture frame if not ret: break # End video when no frames are left cv2.imshow('Frame', frame) # Display the frame if cv2.waitKey(1) == 27: # Exit when 'ESC' key is pressed break cap.release() cv2.destroyAllWindows()
🌐
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 ...
🌐
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 as quickly as it can because OpenCV is not a video player, it's a library for computer vision. if you need "playback" to be at a certain speed, you have to vary the argument to waitKey according to when the next ...
🌐
Quora
quora.com › How-do-I-decrease-the-frames-per-second-in-OpenCV-python
How to decrease the frames per second in OpenCV python - Quora
I want to make a slow motion video using openCV which has the same frame rate as the original speed of 24 FPS.
🌐
OpenCV Q&A Forum
answers.opencv.org › question › 148835 › videocapture-captures-at-low-fps
VideoCapture captures at low fps - OpenCV Q&A Forum
May 16, 2017 - Hello I have a camera that captures video (according to the specifications) at a resolution of 640x480 at 120fps. I use the script below to check the speed I can capture frames with OpenCV on Python, but unfortunately I can't capture at the same speed, not even close. import cv2 from time import ...