Video Streaming from webcam and image processing with Python

asked 2016-08-22 18:37:43 -0600

bfc_opencv gravatar image

updated 2016-08-23 00:57:12 -0600

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()
edit retag flag offensive close merge delete

Comments

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.

berak gravatar imageberak ( 2016-08-23 00:13:19 -0600 )edit

The first was a type I meant to use frame instead of image. I know putText() needs more parameters, but this is just a stub. The code runs. It's just slow.

bfc_opencv gravatar imagebfc_opencv ( 2016-08-23 00:55:38 -0600 )edit

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 ?

berak gravatar imageberak ( 2016-08-23 01:02:47 -0600 )edit

btw, your main code needs wrapping with:

if __name__ == '__main__':

https://pymotw.com/2/multiprocessing/...

berak gravatar imageberak ( 2016-08-23 01:24:51 -0600 )edit

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.

bfc_opencv gravatar imagebfc_opencv ( 2016-08-23 01:37:52 -0600 )edit

Wrapping with main didn't make a difference. Any other suggestions?

bfc_opencv gravatar imagebfc_opencv ( 2016-08-26 19:55:15 -0600 )edit