OpenCV VideoCapture running in a background thread
Project description
Threaded-VideoCapture
A direct drop-in replacement for OpenCV's VideoCapture
that runs in a background thread, allowing the main thread to
do useful work instead of waiting on frames.
This library is useful if your code spend a lot of time waiting for new frames, or if you are processing a stream in realtime and cannot process frames fast enough to keep up with the stream.
Threaded-VideoCapture
requires opencv-python
4.0.0.21 or greater. It has been tested on Python 3.6, 3.7, 3.8. 3.9,
3.10, and 3.11.
It is a young library. Therefore bugs may exist, and useful features may be missing. Bug reports, feature requests, and pull requests are therefore highly appreciated!
How to install
PyPi package is currently being worked on and should be ready before December 2022. For now, you can download this repository directly.
Simple example
Threaded-VideoCapture
can be used exactly like the normal VideoCapture
:
import cv2
from threaded_videocapture import ThreadedVideoCapture
with ThreadedVideoCapture(0) as tvc: # Open webcam stream
while True:
ret, frame = tvc.read()
if ret: # ret is True if a frame was obtained with tvc.read()
cv2.imshow('frame', frame)
if ret is None: # ret is None if tvc has stopped.
print("End of stream.")
break
if cv2.waitKey(1) == ord('q'):
break
Documentation
ThreadedVideoCapture
creates a background thread with a VideoCapture
instance in it. This instance will
continuously read frames and place them on a FIFO queue. When you call ThreadedVideoCapture.read()
, the oldest
frame is returned from the queue. If there are no frames in the queue, a (False, None)
tuple is returned.
An instantiated ThreadedVideoCapture
will eventually stop yielding frames. This is normal, and occurs for example
when:
- There are no more frames in the video file
- A stream times out
- An exception occurs
When ThreadedVideoCapture
stops, it will place a (None, None)
tuple on the queue. This signifies that
ThreadedVideoCapture.read()
will never yield new frames until a new source has been opened with
ThreadedVideoCapture.open()
. This can also be checked with ThreadedVideoCapture.is_alive()
.
Instantiation parameters
ThreadedVideoCapture
takes additional parameters compared to VideoCapture
during instantiation: frame_queue_size
,
timeout
, poll_rate
, and logger
.
They are explained here.
Frame queue size
Frames read by the VideoCapture
instance in the background thread will be placed on a queue, as explained above. When
the queue becomes full, the oldest item is deleted to make room for the new frame. The length of the queue can be
specified when instantiating ThreadedVideoCapture
to suit your needs. Be default, the queue length is 1, meaning that
only the most recent frame is available.
Timeout
If ThreadedVideoCapture
does not receive a new frame within a specified time, it will time out and quit. This is
useful for
example when you are capturing a stream and you do not know when it will end. You can set the timeout value both when
instantiating, and at any other time. By default, the timeout is set to 1 second. The following example shows how to
start a ThreadedVideoCapture
that will wait indefinitely for a single frame, then change its timeout and quit if
no frames are received within the timeout value.
with ThreadedVideoCapture(0, timeout=0) as tvc: # Open webcam stream with timeout disabled.
# Poll for a single frame for eternity due to no timeout
while True:
ret, frame = cap.read()
if ret:
break
tvc.timeout = 2.5 # Set timeout to 2.5 seconds
# Poll for frames for 2.5 seconds before ThreadedVideoCapture times out
while True:
ret, frame = tvc.read()
if ret is None: # ret is only None if tvc has stopped.
print("ThreadedVideoCapture has timed out.")
break
Polling rate
You can limit how often the VideoCapture
instance calls grab()
by specifying the polling rate at instantiation, or
at any other time. By default, it is not limited.
Logger
The Threaded-VideoCapture
library uses Pythons excellent logging
library to log events. By default
ThreadedVideoCapture
uses its own logger named 'TVC', but you can provide it with a custom logger object at
instantiation. The logger is found at ThreadedVideoCapture.logger
.
Reusing a ThreadedVideoCapture instance
You can open a new video source without having to close your original ThreadedVideoCapture
instance and creating a
new one. Simply call ThreadedVideoCapture.open()
with your new source parameters. This will release the VideoCapture
instance for your old source, join
the background thread, and create a new VideoCapture
in its own thread for the
new video source. Example:
# Example showing how to switch to a different webcam after 1 second with the same ThreadedVideoCapture instance.
from time import time
with ThreadedVideoCapture(0) as tvc: # Open webcam 0 stream
tick = time()
while True:
ret, frame = tvc.read()
if ret: # ret is True if a frame was obtained with tvc.read()
cv2.imshow('frame', frame)
if cv2.waitKey(1) == ord('q'):
break
# After one second of opening the stream from webcam 0, we switch seamlessly to webcam 1.
if time() - tick > 1:
tvc.open(1)
Statistics
The current frames per second (FPS) and actual polling rate can be obtained with ThreadedVideoCapture.fps
and
ThreadedVideoCapture.actual_poll_rate
. These values are updated once per second.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file threaded_videocapture-1.0.0.tar.gz
.
File metadata
- Download URL: threaded_videocapture-1.0.0.tar.gz
- Upload date:
- Size: 24.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.8.0 pkginfo/1.9.2 readme-renderer/34.0 requests/2.27.1 requests-toolbelt/0.10.1 urllib3/1.26.13 tqdm/4.64.1 importlib-metadata/4.2.0 keyring/23.4.1 rfc3986/1.5.0 colorama/0.4.5 CPython/3.6.15
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6db1ecb3b5eb79b37fb10bf5b0d547a191a85802fde4f2735f59a42ab72cb538 |
|
MD5 | d50e03563cf2f805c4c101660c901ee0 |
|
BLAKE2b-256 | 882f86513177ed17887d6edd2062571bfa8a765c4d7071e75e692ab557778c40 |
File details
Details for the file threaded_videocapture-1.0.0-py3-none-any.whl
.
File metadata
- Download URL: threaded_videocapture-1.0.0-py3-none-any.whl
- Upload date:
- Size: 9.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.8.0 pkginfo/1.9.2 readme-renderer/34.0 requests/2.27.1 requests-toolbelt/0.10.1 urllib3/1.26.13 tqdm/4.64.1 importlib-metadata/4.2.0 keyring/23.4.1 rfc3986/1.5.0 colorama/0.4.5 CPython/3.6.15
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 34fb9f977a1d843d145384b3510796054cbf5fe5fac40573858ab2060348de51 |
|
MD5 | 8ec21e617e563d4cb77bf81be0cd9da7 |
|
BLAKE2b-256 | ab7498aefb36680d254d0c4c47355a0c855f3e62647dfe03e1f9b432b8d16028 |