371 lines
15 KiB
Python
Executable File
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)
|