I am using python 3.5 with opencv.
I want to use 2 threads:
To view/capture the video from webcam i am using snippets of code from the following website: opencv video docs
I can capture and save the video using the following code:
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480))
while(True):
ret, frame = cap.read()
if ret==True:
frame = cv2.flip(frame,0)
# write the flipped frame
out.write(frame)
else:
break
out.release()
cv2.destroyAllWindows()
I can view the video using the following code:
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
Each of these pieces of code are in their own functions called capture and display. I then call them in separate threads with pythons threading library as follows:
cap = cv2.VideoCapture(0)
Thread(target=capture).start()
Thread(target=display).start()
cap.release()
I get an error I assume is related to both threads wanting to access the video buffer at the same time.
I understand this can be done without threads but there are other things I would like to do further than can only be done in separate threads.
How can I access the cap video capture from both threads?
My flask/django experience is increadibly limited, so I am not sure how to do it for that exactly, but I will answer the question posted directly.
First you need to create a thread-safe object to avoid calling at the same time the read function in different threads.
import cv2
import threading
class VideoCamera(object):
# filename can be 0 to access the webcam
def __init__(self, filename):
self.lock = threading.Lock()
self.openVideo(filename)
def openVideo(self, filename):
self.lock.acquire()
self.videoCap = cv2.VideoCapture(filename)
self.lock.release()
With this, you should be able to create an object with a lock and to open safely a video (in case that you want to open another video with the same object).
Now you have 2 options, either you create a thread that updates the frame and stores the current one internally or update do in a thread safe manner the get next frame function. I will do the second one here to show you:
def getNextFrame(self):
self.lock.acquire()
img = None
# if no video opened return None
if self.videoCap.isOpened():
ret, img = self.videoCap.read()
self.lock.release()
return img
This way you should be able to access the video cap with 2 frames... however, the frames will be different every time the function is called.
I hope this helps you.