参考原文:读取多个(海康大华)网络摄像头的视频流 (使用opencv-python),解决实时读取延迟问题 - 2019.11.19
作者:曾伊言
作用:实时读取多个网络摄像头 rtsp 或 rtmp 流
Python 实现:
import time
import multiprocessing as mp
import cv2
def image_put(q, rtsp):
#cap = cv2.VideoCapture("rtsp://xxxx")
cap = cv2.VideoCapture(rtsp)
if cap.isOpened():
print('True')
else:
pass
while True:
q.put(cap.read()[1])
q.get() if q.qsize() > 1 else time.sleep(0.01)
def image_get(q, window_name):
cv2.namedWindow(window_name, flags=cv2.WINDOW_FREERATIO)
while True:
frame = q.get()
cv2.imshow(window_name, frame)
cv2.waitKey(1)
def run_opencv_camera():
cap_path = 0 # local camera
# cap_path = 'video.avi' # the path of video file
# cap_path = "rtsp://xxx"
cap = cv2.VideoCapture(cap_path)
while cap.isOpened():
is_opened, frame = cap.read()
cv2.imshow('frame', frame)
cv2.waitKey(1000)
cap.release()
def run_single_camera(rtsp, camera_ip='192.168.1.111'):
mp.set_start_method(method='spawn') # init
queue = mp.Queue(maxsize=2)
processes = [
mp.Process(target=image_put, args=(queue, rtsp)),
mp.Process(target=image_get, args=(queue, camera_ip))]
[process.start() for process in processes]
[process.join() for process in processes]
def run_multi_camera():
camera_ip_l = ["rtsp://1_xxxx",
"rtsp://2_xxxx"]
mp.set_start_method(method='spawn') # init
queues = [mp.Queue(maxsize=4) for _ in camera_ip_l]
processes = []
for queue, rtsp in zip(queues, camera_ip_l):
processes.append(mp.Process(target=image_put, args=(queue, rtsp)))
processes.append(mp.Process(target=image_get, args=(queue, rtsp)))
for process in processes:
process.daemon = True
process.start()
for process in processes:
process.join()
def image_collect(queue_list, camera_ip_l):
import numpy as np
"""
show in single opencv-imshow window
"""
window_name = "single_opencv_imshow_window"
cv2.namedWindow(window_name, flags=cv2.WINDOW_FREERATIO)
while True:
imgs = [q.get() for q in queue_list]
imgs = np.concatenate(imgs, axis=1)
cv2.imshow(window_name, imgs)
cv2.waitKey(1)
# """show in multiple opencv-imshow windows"""
# [cv2.namedWindow(window_name, flags=cv2.WINDOW_FREERATIO)
# for window_name in camera_ip_l]
# while True:
# for window_name, q in zip(camera_ip_l, queue_list):
# cv2.imshow(window_name, q.get())
# cv2.waitKey(1)
def run_multi_camera_in_a_window():
camera_ip_l = ["rtsp://1_xxxx",
"rtsp://2_xxxx"]
mp.set_start_method(method='spawn') # init
queues = [mp.Queue(maxsize=4) for _ in camera_ip_l]
processes = [mp.Process(target=image_collect, args=(queues, camera_ip_l))]
for queue, rtsp in zip(queues, camera_ip_l):
processes.append(mp.Process(target=image_put, args=(queue, rtsp)))
for process in processes:
process.daemon = True # setattr(process, 'deamon', True)
process.start()
for process in processes:
process.join()
def run():
# run_opencv_camera() # slow, with only 1 thread
run_single_camera(rtsp) # quick, with 2 threads
# run_multi_camera() # with 1 + n threads
# run_multi_camera_in_a_window() # with 1 + n threads
pass
if __name__ == '__main__':
run()
其中,解决实时读取延迟卡顿的关键代码如下,采用 python 自带的多线程队列:
import multiprocessing as mp
img_queues = [mp.Queue(maxsize=2) for _ in camera_ip_l] #queue
q.put(frame) if is_opened else None # 线程A不仅将图片放入队列
q.get() if q.qsize() > 1 else time.sleep(0.01) #线程A还负责移除队列中的旧图