使用opencv打开rtsp视频流时,会因为网络问题导致VideoCapture掉线;也会因为图像的后处理阶段耗时过长导致opencv缓冲区数据堆积,从而使程序无法及时处理最新的数据。为此对cv2.VideoCapture进行封装,实现0缓存掉线重连的rtsp直播流播放器,让程序能一直处理最新的数据。
from collections import deque
import threading
import cv2,time
#接收摄影机串流影像,采用多线程的方式,降低缓冲区栈图帧的问题。
class VideoCapture:
def __init__(self, URL):
self.URL = URL
self.isstop = False
self.lock = threading.RLock()
self.q=deque(maxlen=100)
# 摄影机连接。
self.capture = cv2.VideoCapture(self.URL)
threading.Thread(target=self.readframe, daemon=True, args=()).start()
print('VideoCapture started!')
def release(self):
# 记得要设计停止无限循环的开关。
self.isstop = True
print('VideoCapture stopped!')
def read(self):
i=0
while len(self.q)==0 and i<100: #尽可能避免读不到数据
time.sleep(0.005)
i+=1
if len(self.q)>0:
res=self.q.pop()# 只要最新的数据
self.q.clear()# 直接清空原先的数据
return res
else:
return False,None
#进行实时数据读取
def readframe(self):
while (not self.isstop):
ok, frame = self.capture.read()
if ok:
self.q.append((ok, frame))
else:
self.capture = cv2.VideoCapture(self.URL) #掉线重连
self.capture.release()
if __name__ == '__main__':
path="rtmp://rtmp.rtc.qq.com/pull/19"
cap = VideoCapture(path)
while True:
ok, frame = cap.read()
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if not ok:
continue
cv2.imshow("cam", frame)
cap.release()
cv2.destroyAllWindows()
使用代码如下所示,与cv2.VideoCapture是一模一样的用法,具备0缓存,自动断线重连的特点
if __name__ == '__main__':
path="rtmp://rtmp.rtc.qq.com/pull/19"
cap = VideoCapture(path)
while True:
ok, frame = cap.read()
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if not ok:
continue
cv2.imshow("cam", frame)
cap.release()
cv2.destroyAllWindows()
与vlc相比,通过本程序读取出的视频帧实时性更高