I'm working on a small project for personal use where I want to load the CCTV streams I have from home into Opencv. I've done alot of research and understand that I need to use multithreading to get them to work correctly. and using the following code I've got it working on one camera perfectly!
from threading import Thread
import imutils
import cv2, time
camlink1 = "rtsp://xx.xx.xx.xx.:xxx/user=xxx&password=xxx&channel=1&stream=0./"
class VideoStreamWidget(object):
def __init__(self, link, camname, src=0):
self.capture = cv2.VideoCapture(link)
# Start the thread to read frames from the video stream
self.thread = Thread(target=self.update, args=())
self.thread.daemon = True
self.thread.start()
self.camname = camname
self.link = link
print(camname)
print(link)
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
frame = imutils.resize(self.frame, width=400)
cv2.imshow('Frame ' + self.camname, frame)
key = cv2.waitKey(1)
if key == ord('q'):
self.capture.release()
cv2.destroyAllWindows()
exit(1)
if __name__ == '__main__':
video_stream_widget = VideoStreamWidget(camlink1,"Cam1")
while True:
try:
video_stream_widget.show_frame()
except AttributeError:
pass
But now I want run another camera alongside it (in parallel) but I'm not sure how what i need to change to the code to start another thread and run it side by side. I thought I did by using the following:
from threading import Thread
import imutils
import cv2, time
camlink1 = "rtsp://xx.xx.xx.xx.:xxx/user=xxx&password=xxx&channel=1&stream=0./"
camlink2 = "rtsp://xx.xx.xx.xx.:xxx/user=xxx&password=xxx&channel=2&stream=0./"
class VideoStreamWidget(object):
def __init__(self, link, camname, src=0):
self.capture = cv2.VideoCapture(link)
# Start the thread to read frames from the video stream
self.thread = Thread(target=self.update, args=())
self.thread.daemon = True
self.thread.start()
self.camname = camname
self.link = link
print(camname)
print(link)
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
frame = imutils.resize(self.frame, width=400)
cv2.imshow('Frame ' + self.camname, frame)
key = cv2.waitKey(1)
if key == ord('q'):
self.capture.release()
cv2.destroyAllWindows()
exit(1)
if __name__ == '__main__':
video_stream_widget = VideoStreamWidget(camlink1,"Cam1")
video_stream_widget = VideoStreamWidget(camlink2,"Cam2")
while True:
try:
video_stream_widget.show_frame()
except AttributeError:
pass
But this just shows the second camera only, overriding the first. I know somewhere I'm missing something simple but after looking at this for hours I can't figure it out. Any help is appreciated
Cheers Chris
The problem is in these lines of code:
if __name__ == '__main__':
video_stream_widget = VideoStreamWidget(camlink1,"Cam1")
video_stream_widget = VideoStreamWidget(camlink2,"Cam2")
while True:
try:
video_stream_widget.show_frame()
except AttributeError:
pass
To be precise, you are overwriting the the variable video_stream_widget
and then calling once video_stream_widget.show_frame()
This will be only call in the last one (even if the thread that captures the images is still working), so only the last one will be showing, i.e. "Cam2".
Add different names for each and call the show_frame()
function on both, like this:
if __name__ == '__main__':
video_stream_widget = VideoStreamWidget(camlink1,"Cam1")
video_stream_widget2 = VideoStreamWidget(camlink2,"Cam2")
while True:
try:
video_stream_widget.show_frame()
video_stream_widget2.show_frame()
except AttributeError:
pass