I've written several solutions to similar problems, but it's been a little while so here we go:

I would use shared_memory as a buffer to read frames into, which can then be read by another process. My first inclination is to initialize the camera and read frames in the child process, because that seems like it would be a "set it and forget it" kind of thing.

import numpy as np
import cv2
from multiprocessing import Process, Queue
from multiprocessing.shared_memory import SharedMemory

def produce_frames(q):
    #get the first frame to calculate size of buffer
    cap = cv2.VideoCapture(0)
    success, frame = cap.read()
    shm = SharedMemory(create=True, size=frame.nbytes)
    framebuffer = np.ndarray(frame.shape, frame.dtype, buffer=shm.buf) #could also maybe use array.array instead of numpy, but I'm familiar with numpy
    framebuffer[:] = frame #in case you need to send the first frame to the main process
    q.put(shm) #send the buffer back to main
    q.put(frame.shape) #send the array details
    q.put(frame.dtype)
    try:
        while True:
            cap.read(framebuffer)
    except KeyboardInterrupt:
        pass
    finally:
        shm.close() #call this in all processes where the shm exists
        shm.unlink() #call from only one process

def consume_frames(q):
    shm = q.get() #get the shared buffer
    shape = q.get()
    dtype = q.get()
    framebuffer = np.ndarray(shape, dtype, buffer=shm.buf) #reconstruct the array
    try:
        while True:
            cv2.imshow("window title", framebuffer)
            cv2.waitKey(100)
    except KeyboardInterrupt:
        pass
    finally:
        shm.close()

if __name__ == "__main__":
    q = Queue()
    producer = Process(target=produce_frames, args=(q,))
    producer.start()
    consume_frames(q)
Answer from Aaron on Stack Overflow
🌐
Stack Overflow
stackoverflow.com › questions › 59960938 › read-webcam-in-python-with-multiprocessing
opencv - Read webcam in python with multiprocessing - Stack Overflow
import cv2 import numpy as np import multiprocessing def get(): global cap cap = cv2.VideoCapture(0) return cap def video(cap): _, frame = cap.read() frame = cv2.flip(frame, 1) return frame if __name__ == "__main__": p1 = multiprocessing.Process(target = get) p1.start() p1.join() while True: frame = video(cap) cv2.imshow("frame", frame) key = cv2.waitKey(1) if key == 27: #Key 'S' break cv2.waitKey(0) cv2.destroyAllWindows()
🌐
OpenCV Q&A Forum
answers.opencv.org › question › 100839 › video-streaming-from-webcam-and-image-processing-with-python
Video Streaming from webcam and image processing with Python - OpenCV Q&A Forum
August 22, 2016 - Here's the code, if anyone can help me use OpenCV to stream video from the webcam without lag, that would greatly be appreciated. class Consumer(multiprocessing.Process): def __init__(self, task_queue, result_queue): multiprocessing.Process.__init__(self) self.task_queue = task_queue self.result_queue = result_queue #other initialization stuff def run(self): while True: image = self.task_queue.get() #Do computations on image self.result_queue.put("text") return import cv2 tasks = multiprocessing.Queue() results = multiprocessing.Queue() consumer = Consumer(tasks,results) consumer.start() #Crea
🌐
Nrsyed
nrsyed.com › 2018 › 07 › 05 › multithreading-with-opencv-python-to-improve-video-processing-performance
Multithreading with OpenCV-Python to improve video processing performance • Najam R. Syed
July 6, 2018 - In a single-threaded video processing application, we might have the main thread execute the following tasks in an infinitely looping while loop: 1) get a frame from the webcam or video file with cv2.VideoCapture.read(), 2) process the frame as we need, and 3) display the processed frame on the screen with a call to cv2.imshow().
Author: faisalshahbaz
🌐
Blogger
kieleth.blogspot.com › 2014 › 05 › webcam-capture-with-opencv-and-tkinter.html
Kieleth: Webcam capture with OpenCV and multiprocessing.
May 20, 2014 - import multiprocessing import cv2 def cam_loop(pipe_parent): cap = cv2.VideoCapture(0) while True: _ , img = cap.read() if img is not None: pipe_parent.send(img) def show_loop(pipe_child): cv2.namedWindow('pepe') while True: from_queue = pipe_child.recv() cv2.imshow('pepe', from_queue) cv2.waitKey(1) if __name__ == '__main__': logger = multiprocessing.log_to_stderr() logger.setLevel(multiprocessing.SUBDEBUG) pipe_parent, pipe_child = multiprocessing.Pipe() cam_process = multiprocessing.Process(target=cam_loop,args=(pipe_parent, )) cam_process.start() show_process = multiprocessing.Process(target=show_loop,args=(pipe_child, )) show_process.start() cam_process.join() show_loop.join() This code will create one main process and two child ones, one for each function, plus a pipe that is how the images that one captures, the other consumes.
🌐
GitHub
github.com › mahdizynali › OpenCV-video-multiprocessing
GitHub - mahdizynali/OpenCV-video-multiprocessing: opencv python video multiprocessing besides tkinter video multiprocessing
with this script, it will be possible ... mode, by multiprocessing and seprating frames into some parts and process each part by a thread and add them into a queue, so finally stick the queue processing result together....
Author: mahdizynali
Top answer
1 of 1
6

I've written several solutions to similar problems, but it's been a little while so here we go:

I would use shared_memory as a buffer to read frames into, which can then be read by another process. My first inclination is to initialize the camera and read frames in the child process, because that seems like it would be a "set it and forget it" kind of thing.

import numpy as np
import cv2
from multiprocessing import Process, Queue
from multiprocessing.shared_memory import SharedMemory

def produce_frames(q):
    #get the first frame to calculate size of buffer
    cap = cv2.VideoCapture(0)
    success, frame = cap.read()
    shm = SharedMemory(create=True, size=frame.nbytes)
    framebuffer = np.ndarray(frame.shape, frame.dtype, buffer=shm.buf) #could also maybe use array.array instead of numpy, but I'm familiar with numpy
    framebuffer[:] = frame #in case you need to send the first frame to the main process
    q.put(shm) #send the buffer back to main
    q.put(frame.shape) #send the array details
    q.put(frame.dtype)
    try:
        while True:
            cap.read(framebuffer)
    except KeyboardInterrupt:
        pass
    finally:
        shm.close() #call this in all processes where the shm exists
        shm.unlink() #call from only one process

def consume_frames(q):
    shm = q.get() #get the shared buffer
    shape = q.get()
    dtype = q.get()
    framebuffer = np.ndarray(shape, dtype, buffer=shm.buf) #reconstruct the array
    try:
        while True:
            cv2.imshow("window title", framebuffer)
            cv2.waitKey(100)
    except KeyboardInterrupt:
        pass
    finally:
        shm.close()

if __name__ == "__main__":
    q = Queue()
    producer = Process(target=produce_frames, args=(q,))
    producer.start()
    consume_frames(q)
🌐
OpenCV Q&A Forum
answers.opencv.org › question › 229866 › how-to-capture-multi-camera-with-opencv-multi-threading-python
How to capture Multi camera with Opencv Multi threading (python) [closed] - OpenCV Q&A Forum
May 5, 2020 - I am trying to achieve to get the streams from multiple ip cameras and display it. I have two ipcamera with urls : rtsp and rtsp1 When i run the following program, Only first window loads and works fine until the second thread kicks in. Things works fine with multiple streams in the following methods : Works without threads. i.e : cam0 = cv2.VideoCapture(rtsp) cam1 = cv2.VideoCapture(rtsp1) ret, frame0 = cam0.read() ret, frame1 = cam1.read() show imshow(frame0) & (frame1) But this method is primitive and get lags.
Find elsewhere
Top answer
1 of 3
11

The simplest approach is to use the newer cv2 module that's based on NumPy arrays. That way you don't have to mess with manual pickling. Here's the fix (I just changed 4 lines of code):

import multiprocessing
import cv2

queue_from_cam = multiprocessing.Queue()

def cam_loop(queue_from_cam):
    print 'initializing cam'
    cap = cv2.VideoCapture(0)
    print 'querying frame'
    hello, img = cap.read()
    print 'queueing image'
    queue_from_cam.put(img)
    print 'cam_loop done'

cam_process = multiprocessing.Process(target=cam_loop,args=(queue_from_cam,))
cam_process.start()

while queue_from_cam.empty():
    pass

print 'getting image'
from_queue = queue_from_cam.get()
print 'saving image'
cv2.imwrite('temp.png', from_queue)
print 'image saved'
2 of 3
6

It appears that the solution was to convert the opencv iplimage object to string, then pickle it before adding it to the queue:

import multiprocessing
import cv
import Image
import pickle
import time

queue_from_cam = multiprocessing.Queue()

def cam_loop(queue_from_cam):
    print 'initializing cam'
    cam = cv.CaptureFromCAM(-1)
    print 'querying frame'
    img = cv.QueryFrame(cam)
    print 'converting image'
    pimg = img.tostring()
    print 'pickling image'
    pimg2 = pickle.dumps(pimg,-1)
    print 'queueing image'
    queue_from_cam.put([pimg2,cv.GetSize(img)])
    print 'cam_loop done'


cam_process = multiprocessing.Process(target=cam_loop,args=(queue_from_cam,))
cam_process.start()

while queue_from_cam.empty():
    pass

print 'getting pickled image'
from_queue = queue_from_cam.get()
print 'unpickling image'
pimg = pickle.loads(from_queue[0])
print 'unconverting image'
cv_im = cv.CreateImageHeader(from_queue[1], cv.IPL_DEPTH_8U, 3)
cv.SetData(cv_im, pimg)
print 'saving image'
cv.SaveImage('temp.png',cv_im)
print 'image saved'
🌐
PyImageSearch
pyimagesearch.com › home › blog › multiprocessing with opencv and python
Multiprocessing with OpenCV and Python - PyImageSearch
December 29, 2022 - Now, let’s assume we launch our Python script. The operating system will assign the process to a single one of those cores: Figure 2: Without multiprocessing, your OpenCV program may not be efficiently using all cores or processors available on your machine.
🌐
GitHub
github.com › opencv › opencv › issues › 6034
Python Multiprocessing Problem · Issue #6034 · opencv/opencv
January 30, 2016 - class Consumer(multiprocessing.Process): def __init__(self, task_queue, result_queue): multiprocessing.Process.__init__(self) self.task_queue = task_queue self.result_queue = result_queue def run(self): #Creating window and starting video camputer from camera cv2.namedWindow("preview") vc = cv2.VideoCapture(0) vc.set(cv.CV_CAP_PROP_FRAME_WIDTH, 640) vc.set(cv.CV_CAP_PROP_FRAME_HEIGHT, 480) if vc.isOpened(): rval, frame = vc.read() else: rval = False while rval: cv2.imshow("preview", frame) rval, frame = vc.read() key = cv2.waitKey(20) if key == 27: break cv2.destroyWindow("preview") return ################################## #MAIN PROGAM ################################## #SETTING UP MULTIPROCESSING STUFF tasks = multiprocessing.JoinableQueue() results = multiprocessing.Queue() consumer = Consumer(tasks,results) consumer.start() #Rest of main program
Author: opencv
Top answer
1 of 1
28

Using threading to handle I/O heavy operations (such as reading frames from a webcam) is a classic programming model. Since accessing the webcam/camera using cv2.VideoCapture().read() is a blocking operation, our main program is stalled until the frame is read from the camera device and returned to our script. Essentially the idea is to spawn another thread to handle grabbing the frames in parallel instead of relying on a single thread (our 'main' thread) to grab the frames in sequential order. This will allow frames to be continuously read from the I/O thread, while our root thread processes the current frame. Once the root thread finishes processing its frame, it simply needs to grab the current frame from the I/O thread without having to wait for blocking I/O operations.

Thus we can improve performance by creating a new thread that does nothing but poll for new frames while our main thread handles processing the current frame. For an implementation to handle multiple camera streams, take a look at capture multiple camera streams with OpenCV

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

Related camera/IP/RTSP, 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

🌐
Stack Overflow
stackoverflow.com › questions › 72681054 › constant-camera-grabbing-with-opencv-python-multiprocessing-follow-up
Constant camera grabbing with OpenCV & Python multiprocessing - Follow up - Stack Overflow
This is a followup on this where @Aaron helped quite a lot. Context: OpenCV, Python, a USB Webcam and multiprocessing - Grabbing all the time from the camera on a subprocess and returning a single ...
🌐
Medium
yakhyo.medium.com › multiprocessing-in-python-reading-from-webcam-video-using-multiprocessing-d78c15d1a7e6
Multiprocessing in Python. Reading from webcam/video using multiprocessing. | by Yakhyokhuja Valikhujaev | Medium
April 16, 2021 - from multiprocessing import Pool import os import cv2 def webcam(src): cap = cv2.VideoCapture(src) # webcam:0 ,ip camera: 'link address' fps = cap.get(cv2.CAP_PROP_FPS) while True: ret, frame = cap.read() if ret: frame = cv2.flip(frame, 1) frame = cv2.putText(frame, f'FPS: {str(fps)}', (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255)) cv2.imshow('multiprocessing', frame) if cv2.waitKey(1) == ord('q'): break else: break if __name__ == "__main__": with Pool(os.cpu_count()) as p: p.map(webcam, [0]) Reference · https://www.ellicium.com/python-multiprocessing-pool-process/ https://github.com/yakhyo/Python-Packages/blob/main/multiprocessing ·
Starred by 15 users
Forked by 3 users
Languages: Python
🌐
OpenCV
forum.opencv.org › python
How many parallel VideoCapture's can one camera handle? - Python - OpenCV
February 9, 2024 - I want to read from one camera in many parallel processes. Here is what I’ve tried. from multiprocessing import Process import cv2 import time import random def get_capture(): time.sleep(random.randint(0, 3)) cap = cv2.VideoCapture(0) w, h = cap.get(cv2.CAP_PROP_FRAME_WIDTH), cap.get(cv2.CAP_PROP_FRAME_HEIGHT) if (w, h) == (0, 0): print("Seemingly failed to construct the capture.") print(f"Feed dimensions are {w}x{h}.") success, _ = cap.read() if not s...
🌐
Medium
gvasu.medium.com › faster-real-time-video-processing-using-multi-threading-in-python-8902589e1055
Faster Real-Time Video Processing using Multi-Threading in Python | by Vasu Gupta | Medium
September 28, 2021 - # importing required libraries import cv2 # OpenCV library import time # time library from threading import Thread # library for multi-threading
🌐
GitHub
github.com › vmlaker › sherlock
GitHub - vmlaker/sherlock: High-performance realtime video processing. In Python!! · GitHub
A collection of small codes for processing live video (like from a webcam) with OpenCV. Image data in memory (NumPy arrays) are shared by multiple processes using numpy-sharedmem Python module.
Author: vmlaker