Files
MPKFNet/rtsp_process.py
T
2022-05-07 16:25:11 +08:00

371 lines
15 KiB
Python
Executable File

# -*- 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)