I've got a Raspberry Pi Display screen project working, displaying 2 CCTV feeds via rtsp into a couple of Tkinter labels, problem is its so slow and up to 10s behind the live feed. After doing research I now know I have to separate out the actual capture of frames away from the main thread to speed things up but even after reading several tutorials I can't get it to work.
This works but is slow, clearly its blocking which is where the delay is introduced
def garden1():
cap2 = cv2.VideoCapture("LOCAL URL")
cap2.set(cv2.CAP_PROP_BUFFERSIZE, 3)
while True:
try:
if cap2.isOpened():
status, frame = cap2.read()
if status:
frame = cv2.resize(frame, (350,200))
cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
img = Image.fromarray(cv2image)
imgtk = ImageTk.PhotoImage(image=img)
gardenlbl.imgtk = imgtk
gardenlbl.configure(image=imgtk)
else:
t_stamp = error_timestamp()
logging.info(t_stamp +" Garden Videostream restarted")
cap2 = cv2.VideoCapture("LOCAL URL")
continue
except cv2.error as e:
print ("Something went wrong with garden video")
pass
I know I have to go down this route, so setting up a class I can use for each feed and then a separate thread to read the frames and place them into labels - Code snippet below:
def garden():
while True:
try:
frame = video_stream2.read()
cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
img = Image.fromarray(cv2image)
imgtk = ImageTk.PhotoImage(image=img)
gardenlbl.imgtk = imgtk
gardenlbl.configure(image=imgtk)
time.sleep(1)
except cv2.error as e:
print (str(e) + "Something went wrong with garden video")
pass
class streamvideo(object):
def __init__(self, src=0):
self.capture = cv2.VideoCapture(src)
self.thread = Thread(target=self.update, args=())
self.thread.daemon = True
self.thread.start()
print ("thread started")
def update(self):
print ("Update started")
while True:
if self.capture.isOpened():
(self.status, self.frame) = self.capture.read()
def read(self):
if self.status:
self.frame = self.resize_frame(self.frame, width=350)
return self.frame
def resize_frame(self, image, width=None, height=None, inter=cv2.INTER_AREA):
dim = None
(h, w) = image.shape[:2]
if width is None and height is None:
return image
if width is None:
r = height / float(h)
dim = (int(w * r), height)
else:
r = width / float(w)
dim = (width, int(h * r))
return cv2.resize(image, dim, interpolation=inter)
stream_garden = local url
video_stream2 = streamvideo(stream_garden)
t_e = threading.Thread(target=garden, name="Garden", daemon=True)
t_e.start()
The error I'm currently getting is:
Update started
thread started
Exception in thread Garden:
Traceback (most recent call last):
File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/usr/lib/python3.7/threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "monitor2.py", line 422, in garden
frame = video_stream2.read()
File "monitor2.py", line 448, in read
if self.status:
AttributeError: 'streamvideo' object has no attribute 'status'
I've always avoided classes as I always find myself tripping up - Can anyone suggest any improvements?