# -*- coding:utf-8 -*- import cv2 import queue import time import redis import time import threading from System_I import Check_start,Density_mul,Detecntion_mul,SaveImage_mul,Detection_Y5,Density,Fine_grained from common import global_para as gp r_db = None import logging from logging.handlers import TimedRotatingFileHandler import os from video_notice import VideoNotice class videoSaveThread(threading.Thread): def __init__(self, invoker, prefix, filePath, fps, video, frameSize, dQueue, queueSize, sectionCnt): threading.Thread.__init__(self) self.invoker = invoker # 存储文件前缀 self.prefix = prefix # 存储路径 self.filePath = filePath # 帧率 self.fps = fps # 传入缓存队列 self.dQueue = dQueue self.queueSize = queueSize # 缓存队列大小 self.frameSize = frameSize # frame帧尺寸 # 传入cv2videowriter对象 self.out = video self.sectionCnt = sectionCnt def run(self): framecount = 0 # # 这里采用h264编码 # fourcc = cv2.VideoWriter_fourcc(*"MP4V") # # 命名里不要使用不允许的字符, # fname = self.filePath + self.prefix + time.strftime("%Y%m%d%H%M%S", time.localtime()) + '.mp4' # out = cv2.VideoWriter(fname, fourcc, self.fps, self.frameSize) # while not self.dQueue.empty(): # try: # frame = self.dQueue.get() # #print(frame.size) # out.write(frame) # except Exception as e: # log.info(e) # out.release() # out = None # log.debug(self.invoker + "-END" + str(time.time())) i_temp = 0 while framecount < self.queueSize: try: if (self.dQueue.empty()): if gp.DebugPrint_flag: print("kong") else: frame = self.dQueue.get() # print(frame.size) #frame = cv2.resize(frame, self.frameSize) t11 = time.time() self.out.write(frame) i_temp +=1 t12 = time.time() if gp.DebugPrint_flag: print("一帧写入时间是: ", (t12-t11)*1000," ",i_temp) framecount += 1 # print(count) # except Exception as e: # log.info(e) except: pass # out.release() # out = None # log.debug(self.invoker + "-END" + str(time.time())) if gp.DebugPrint_flag: print(self.sectionCnt," Video Saving is over") print("aaaaaaaa",(int(750/self.queueSize)-1)," ",self.sectionCnt) if self.sectionCnt == (int(750/self.queueSize)-1): time.sleep(0.1) self.out.release() self.out = None gp.Vedio_thread_flag = False if gp.DebugPrint_flag: print("Video Saving is over") class cusLogger: def __init__(self, loggerName): # 创建一个logger self.logger = logging.getLogger(loggerName) self.logger.setLevel(logging.DEBUG) # 创建一个handler,用于写入日志文件。如果当前目录下没有logs目录,需要手动创建 logPath = ".\\logs\\" # 日志文件名 #print(logPath) logName = os.path.join(logPath + loggerName + '.log') #print(logName) # 创建一个每日可更新的handler,用于将日志输出文件 fileHandler = TimedRotatingFileHandler(logName, when='D',encoding='utf-8') fileHandler.setLevel(logging.DEBUG) # 创建一个handler,用于将日志输出到控制台 consoleHandler = logging.StreamHandler() consoleHandler.setLevel(logging.DEBUG) # 定义handler的输出格式 formatter = logging.Formatter( '%(asctime)s-%(name)s-%(levelname)s:%(message)s') fileHandler.setFormatter(formatter) consoleHandler.setFormatter(formatter) self.logger.addHandler(fileHandler) #如果不需要控制台,可以注释掉 self.logger.addHandler(consoleHandler) def getLogger(self): return self.logger log = cusLogger("rtsp_process").getLogger() class rtspThread(threading.Thread): def __init__(self, thName, rtspUrl, prefix, filePath, fps, frameSize, queueSize, timer, eventKey, eventValue, DensityClass,DetectionClass,Fine_grianedClass): threading.Thread.__init__(self) # name self.thName = thName # rtsp流地址 self.rtspUrl = rtspUrl # 帧率 self.fps = fps # 帧大小(width,height) self.frameSize = frameSize # 存储队列大小,fps * 10秒 self.queueSize = queueSize # 总视频帧数 = fps * 存储时间 self.sumframesize = fps * timer # redis的key self.eventKey = eventKey # key值 self.eventValue = eventValue # 存储文件前缀 self.prefix = prefix # 存储路径 self.filePath = filePath # 存储视频帧大小 self.videoframesize = (1920, 1080) # cv2writer对象 self.video = None self.DensityClass = DensityClass self.DetectionClass = DetectionClass self.Fine_grianedClass = Fine_grianedClass def run(self): # ThreadMonitor_mul1 = ThreadMonitor_mul("0001","ThreadMonitor_mul") #开启线程管理 # ThreadMonitor_mul1.start() videoFlag = False # 视频缓存队列 videoSaveQueue = [queue.Queue(self.queueSize), queue.Queue(self.queueSize)] # 队列索引编号 curQueueIdx = 0 # 错误标志位 closed = False # 错误计数 failCnt = 0 # 存视频标志 saveFlag = False # 视频段落计数 sectionCnt = 0 # 获取cap对象 cap = cv2.VideoCapture(self.rtspUrl) winName = self.rtspUrl + "_" + str(time.time()) num_detection = 0 num_append = 0 # 只有当这个计数是0的时候,才可以根据目标检测的结果开启后面的三个线程,否则就是正在执行当前的30s线程,不需要再开,直到这30s结束 if cap.isOpened(): res, frame = cap.read() if res: for i in range(20): t1 = time.time() print("initing.....") self.DetectionClass.check_object(frame) self.DensityClass.inference_init(frame) t2 = time.time() print((t2 - t1) * 1000) history = 0 j=0 while(j<100): print("system start") j+=1 while True: time0 = time.time() if cap.isOpened(): res, frame = cap.read() if res: time1 = time.time() #print("两次间隔时间 is ",(time1-history)*1000) history = time1 if (gp.destory_image == True) and (gp.Density_thread_flag == False) and (gp.SaveImage_thread_flag == False) and (gp.Detection_thread_flag == False)and (gp.Vedio_thread_flag == False): # 说明三个进程都已经结束了 gp.ImgDealQueue = [] gp.destory_image = False notice_model = VideoNotice('http://192.168.200.29:1001/guangyd/videoNotice', gp.image_time) content = notice_model.send_notice() print("一批数据处理完毕,已发送信号至服务端来取") closed = False failCnt = 0 if gp.is_ex_bird and gp.Density_thread_flag and gp.SaveImage_thread_flag and gp.Detection_thread_flag and gp.Vedio_thread_flag and num_append>24: #说明已经检测到目标,开始识别30s的视频,则需要开始存数据了 gp.ImgDealQueue.append(frame) print(len(gp.ImgDealQueue)) gp.eventDensity.set() gp.eventDetection.set() gp.eventSaveimage.set() num_append = 0 print(gp.Camera_device,gp.Density_thread_flag,gp.Detection_thread_flag,gp.SaveImage_thread_flag,gp.Vedio_thread_flag,gp.is_ex_bird,num_detection) if (gp.Vedio_thread_flag == False) and ( gp.Density_thread_flag== False) and ( gp.Detection_thread_flag== False) and ( gp.SaveImage_thread_flag== False) and (gp.is_ex_bird == False) and num_detection>74: Check_start1 = Check_start("0002","check_start",frame,self.DetectionClass) Check_start1.start() num_detection=0 if gp.is_ex_bird and ( gp.Density_thread_flag== False) and (gp.SaveImage_thread_flag == False) and (gp.Detection_thread_flag == False) and (gp.Vedio_thread_flag==False): #开启,密度估计线程,目标检测线程,第一次识别出来有目标 data_today = time.strftime('%H', time.localtime(time.time())) #print(int(data_today)) if (int(data_today) > 7) & (int(data_today) < 18): if not os.path.exists(os.path.join(gp.root,gp.image_time)): os.mkdir(os.path.join(gp.root,gp.image_time)) Detecntion_mul1 = Detecntion_mul("0003", name="Detecntion_mul", imagetime=gp.image_time,DetectionClass=self.DetectionClass,Fine_grainedClass=self.Fine_grianedClass) Detecntion_mul1.start() Density_mul1 = Density_mul("0004",name="Density_mul",imagetime=gp.image_time,DensityClass=self.DensityClass) Density_mul1.start() SaveImage_mul1 = SaveImage_mul("0005","SaveImage_mul",imagetime=gp.image_time,root=gp.root) SaveImage_mul1.start() videoFlag = True else: pass num_detection+=1 num_append +=1 if num_detection>10000: num_detection=24 gp.Vedio_thread_flag = False gp.Detection_thread_flag = False gp.Density_thread_flag = False gp.SaveImage_thread_flag = False if num_append > 10000: num_append = 24 else: failCnt += 1 if(failCnt >= 15): closed = True if (videoFlag): # 删除键值 if gp.DebugPrint_flag: print("Video Saving is starting") videoFlag = False # 存储标志位 saveFlag = True gp.Vedio_thread_flag = True # 这里采用h264编码 fourcc = cv2.VideoWriter_fourcc(*"MP4V") # 命名里不要使用不允许的字符, video_path = os.path.join(gp.root, gp.image_time, "Video") if not os.path.exists(video_path): os.makedirs(video_path) #fname = os.path.join(video_path,gp.image_time,'.mp4') #fname = video_path+"/{}.mp4".format(gp.image_time) # fname =os.path.join(video_path,) # 创建cv2video对象 out = [] for i in range(int(750/self.queueSize)): fname = video_path+"/{}{}.mp4".format(gp.image_time,str(i).zfill(2)) out.append(cv2.VideoWriter(fname, fourcc, self.fps, self.videoframesize)) #out = cv2.VideoWriter(fname, fourcc, self.fps, self.videoframesize) self.video = out if saveFlag: try: if not videoSaveQueue[curQueueIdx].full(): rsframe = cv2.resize(frame, self.videoframesize) videoSaveQueue[curQueueIdx].put(rsframe) if gp.DebugPrint_flag: print( "当前" + str(curQueueIdx) +" " +str(videoSaveQueue[curQueueIdx].qsize())) else: if gp.DebugPrint_flag: print(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) print(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 存视频 videoSaveProc = videoSaveThread(self.thName, self.prefix, self.filePath, self.fps, self.video[sectionCnt], self.videoframesize, videoSaveQueue[curQueueIdx], self.queueSize, sectionCnt) videoSaveProc.start() sectionCnt += 1 # 存图 # jpgSaveSaveProc = jpgSaveThread(self.thName, self.prefix, self.filePath, self.fps, # self.frameSize, jpgSaveQueue[curQueueIdx]) # jpgSaveSaveProc.start() # 切换缓存队列 curQueueIdx = (curQueueIdx + 1) % 2 except: pass if sectionCnt < int(self.sumframesize / self.queueSize): pass else: # 释放资源 saveFlag = False sectionCnt = 0 else: closed = True if closed: # 休眠10秒钟 重连 #time.sleep(1) cap.open(self.rtspUrl) if __name__ == '__main__': r_db = redis.StrictRedis(host='localhost', port=6379, db=0) log = cusLogger("rtsp_process").getLogger() Density1 = Density(gp.devices,gp.root) Detection1 = Detection(gp.devices, gp.root) Fine_grained1 = Fine_grained(gp.devices,gp.root) # Density1.inference(image,image_time,str(1)) # Detection1.inference(image,image_time,str(1),Fine_grained1) try: # 如果有多个流要同时取存,可以创建多个线程 t1 = time.time() thread1 = rtspThread("thread_vs", "rtsp://admin:glodon123@192.168.116.13:554/Streaming/Channels/101", "ch1_", "../data_MPKFNet/RTSP",# 为空串时,默认保存在当前目录 25, (3840, 2160), #(3264,2448), 1500, "key", 1, Density1, Detection1, Fine_grained1 ) t2 = time.time() print("multi is ",(t2-t1)*1000) thread1.start() except Exception as e: log.info(e)