Video Streaming from webcam and image processing with Python
I'm using the multiprocessing module in python to help speed up my main program. However I believe I might be doing something incorrectly, as I don't think the computations are happening quite in parallel.
I want my program to read in images from a video stream in the main process, and pass on the frames to two child processes that do computations on them and send text back (containing the results of the computations) to the main process.
However, the main process seems to lag when I use multiprocessing, running about half as fast as without it, leading me to believe that the processes aren't running completely in parallel.
After doing some research, I surmised that the lag may have been due to communicating between the processes using a queue (passing an image from the main to the child, and passing back text from child to main).
However I commented out the computational step and just had the main process pass an image and the child return blank text, and in this case, the main process did not slow down at all. It ran at full speed.
Perhaps an easier way to think of this is that I'm doing image recognition on what the webcam sees. I send one frame at a time to a separate process to do recognition analysis on the frame, and send the text back to be put as a caption on the live feed. Obviously the processing takes more time than simply grabbing frames from the webcam and showing them, so if there is a delay in what the caption is and what the webcam feed shows, that's acceptable and expected.
What's happening now is that the live video I'm displaying is lagging due to the other processes (when I don't send frames to the process for computing, there is no lag). I've also ensured only one frame is enqueued at a time so avoid overloading the queue and causing lag.
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()
#Creating window and starting video capturer from camera
cv2.namedWindow("preview")
vc = cv2.VideoCapture(0)
#Try to get the first frame
if vc.isOpened():
rval, frame = vc.read()
else:
rval = False
while rval:
if tasks.empty():
tasks.put(frame)
else:
text = tasks.get()
#Add text to frame
cv2.putText(frame,text,(50,50), cv2.FONT_HERSHEY_SIMPLEX, 1, 255)
#Showing the frame with all the applied modifications
cv2.imshow("preview", frame)
#Getting next frame from camera
rval, frame = vc.read()
you're reading into
frame
, but you sendìmage
(which probably is invalid) to your queue. ??also, putText() needs more params. in othere words, i do not beleieve, your code ever ran.
The first was a type I meant to use
frame
instead ofimage
. I knowputText()
needs more parameters, but this is just a stub. The code runs. It's just slow.well, it behaves very odd here. it seems like the main code is executed several times, alterrnating to your consumer code.
why multiprocessing and not multithreading ?
btw, your main code needs wrapping with:
https://pymotw.com/2/multiprocessing/...
I can't use mutithreading for this purpose because of python's GIL lock. I'll try the main wrapping and report back to you.
Wrapping with main didn't make a difference. Any other suggestions?