多线程实现多路rtsp视频opencv处理

多路视频需要并行分析,其中需要使用一些深度学习模型进行目标检测和跟踪等操作.

一开始采用多进程,但是实验下来发现每个进程会分配一个GPU模型,无法共享全局模型/变量. 系统压力巨大,无法分配这么多GPU显存.

于是把模型封装成http服务api,让多进程调用服务进行视频分析,结果发现路数一多会崩.

最终还是考虑了多线程:

多线程可以共享全局变量/模型!!!!

1.ipcamCapture类用于接收串流影像,降低延迟

2.利用multiprocessing.dummy的ThreadPool,可以控制进程一样控制线程

3.利用map函数实现多线程并行处理图像,并放入缓存队列

4.从缓存队列中获取图像结果并显示出来

# -*- coding: utf-8 -*-
import cv2
import time
import threading
from multiprocessing.dummy import Pool as ThreadPool
import numpy as np
from collections import deque
from time import sleep
 
# 接收摄影机串流影像,采用多线程的方式,降低缓冲区栈图帧的问题。
class ipcamCapture:
    def __init__(self, URL):
        self.Frame = []
        self.URL = URL
        self.status = False
        self.isstop = False
		
	# 摄影机连接。
        self.capture = cv2.VideoCapture(URL)
 
    def start(self):
	# 把程序放进子线程,daemon=True 表示该线程会随着主线程关闭而关闭。
        print('ipcam started!')
        threading.Thread(target=self.queryframe, daemon=True, args=()).start()
 
    def stop(self):
	# 记得要设计停止无限循环的开关。
        self.isstop = True
        print('ipcam stopped!')
   
    def getframe(self):
	# 当有需要影像时,再回传最新的影像。
        return self.Frame
        
    def queryframe(self):
        while (not self.isstop):
            self.status, self.Frame = self.capture.read()            
        self.capture.release()
 
def image_infer(source_id):
    i= source_id
    try:
        frame = ipcams[i].getframe() 
        #****************do someting with the frame************#
        # Fortunately,global variables can be used here!       #
        #eg.                                                   #
        #1.object detection#                                   # 
        #2.segmentation                                        #
        #3.classify                                            #
        #4...                                                  #
        ########################################################
        recent_Frames[i].append(frame) #最终结果放入缓存队列
    except Exception as e:
        Nosignal_wall_paper = np.zeros((400,720,3))
        cv2.putText(Nosignal_wall_paper,'NOSIGNALS',(100,250),cv2.FONT_HERSHEY_SIMPLEX,3,(0,255,0),15)
        recent_Frames[i].append(Nosignal_wall_paper)
        print(e.__traceback__.tb_lineno,e.args)               
 
def multi_infer(source_ids):
    pool = ThreadPool(8)
    while True:
        start_time = time.time()
        pool.map(image_infer,source_ids)
        print('用时共: %s ms' % ((time.time() - start_time)*1000))
        # 多线程无法在内部show图像,所以把图像结果缓存到队列中,最后一起显示
        for i,Frame in enumerate(recent_Frames):
            cv2.imshow('source{}'.format(i),cv2.resize(Frame[0],(720,400))) #队列第一帧
            cv2.waitKey(1)
 
if __name__ == "__main__":
    URLS = [
    "rtsp://**********",
    "rtsp://**********",
    "rtsp://**********",
    "rtsp://**********"] #rtsp地址列表
 
    ipcams =[] #摄像机对象列表
    recent_Frames= [deque(maxlen=10) for _ in range(len(URLS))]#存放结果图像的队列
    source_ids = list(range(len(URLS))) #rtsp源编号
    for URL in URLS:
        # 连接摄影机
        ipc = ipcamCapture(URL)
        ipcams.append(ipc)
    for  ipcam in  ipcams:
        # 启动子线程
        ipcam.start()
    # 暂停1秒,确保影像已经填充
    time.sleep(1)
    # 使用无穷循环撷取影像,直到按下Esc键结束
    multi_infer(source_ids)

 

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值