|
@ -7,34 +7,35 @@ import numpy as np |
|
|
import threading |
|
|
import threading |
|
|
import importlib.util |
|
|
import importlib.util |
|
|
import datetime |
|
|
import datetime |
|
|
|
|
|
import queue |
|
|
|
|
|
from collections import deque |
|
|
from core.DBManager import mDBM,DBManager |
|
|
from core.DBManager import mDBM,DBManager |
|
|
from myutils.MyLogger_logger import LogHandler |
|
|
from myutils.MyLogger_logger import LogHandler |
|
|
from myutils.ConfigManager import myCongif |
|
|
from myutils.ConfigManager import myCongif |
|
|
from model.plugins.ModelBase import ModelBase |
|
|
from model.plugins.ModelBase import ModelBase |
|
|
|
|
|
import sys |
|
|
|
|
|
|
|
|
import acl |
|
|
|
|
|
from PIL import Image |
|
|
from PIL import Image |
|
|
|
|
|
|
|
|
ACL_MEM_MALLOC_HUGE_FIRST = 0 |
|
|
|
|
|
ACL_MEMCPY_HOST_TO_DEVICE = 1 |
|
|
|
|
|
ACL_MEMCPY_DEVICE_TO_HOST = 2 |
|
|
|
|
|
|
|
|
|
|
|
class VideoCaptureWithFPS: |
|
|
class VideoCaptureWithFPS: |
|
|
'''视频捕获的封装类,是一个通道一个''' |
|
|
'''视频捕获的封装类,是一个通道一个''' |
|
|
def __init__(self, source=0): |
|
|
def __init__(self, source): |
|
|
self.source = source |
|
|
self.source = source |
|
|
self.cap = cv2.VideoCapture(self.source) |
|
|
|
|
|
self.width = None |
|
|
self.width = None |
|
|
self.height = None |
|
|
self.height = None |
|
|
if self.cap.isOpened(): #若没有打开成功,在读取画面的时候,已有判断和处理 |
|
|
self.cap = cv2.VideoCapture(self.source) |
|
|
|
|
|
if self.cap.isOpened(): #若没有打开成功,在读取画面的时候,已有判断和处理 -- 这里也要检查下内存的释放情况 |
|
|
self.width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH)) |
|
|
self.width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH)) |
|
|
self.height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) |
|
|
self.height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) |
|
|
#self.fps = fps # 线程保持最大帧率的刷新画面---过高的帧率会影响CPU性能,但过地的帧率会造成帧积压 |
|
|
#self.fps = fps # 线程保持最大帧率的刷新画面---过高的帧率会影响CPU性能,但过地的帧率会造成帧积压 |
|
|
self.fps = self.cap.get(cv2.CAP_PROP_FPS) + 20 #只是个参考值,休眠时间要比帧率快点,由于read也需要耗时。 |
|
|
self.fps = self.cap.get(cv2.CAP_PROP_FPS) + 20 #只是个参考值,休眠时间要比帧率快点,由于read也需要耗时。 |
|
|
#print(self.fps) |
|
|
#print(self.fps) |
|
|
self.frame = None |
|
|
|
|
|
self.running = True |
|
|
self.running = True |
|
|
self.read_lock = threading.Lock() |
|
|
self.frame_queue = queue.Queue(maxsize=1) |
|
|
|
|
|
#self.frame = None |
|
|
|
|
|
#self.read_lock = threading.Lock() |
|
|
self.thread = threading.Thread(target=self.update) |
|
|
self.thread = threading.Thread(target=self.update) |
|
|
self.thread.start() |
|
|
self.thread.start() |
|
|
|
|
|
|
|
@ -42,15 +43,24 @@ class VideoCaptureWithFPS: |
|
|
while self.running: |
|
|
while self.running: |
|
|
ret, frame = self.cap.read() |
|
|
ret, frame = self.cap.read() |
|
|
if not ret: |
|
|
if not ret: |
|
|
|
|
|
#time.sleep(1.0 / self.fps) |
|
|
continue |
|
|
continue |
|
|
with self.read_lock: |
|
|
resized_frame = cv2.resize(frame, (int(self.width / 2), int(self.height / 2))) |
|
|
self.frame = frame |
|
|
# with self.read_lock: |
|
|
time.sleep(1.0 / self.fps) |
|
|
# self.frame = resized_frame |
|
|
|
|
|
if not self.frame_queue.full(): |
|
|
|
|
|
self.frame_queue.put(resized_frame) |
|
|
|
|
|
time.sleep(1.0 / self.fps) #按照视频源的帧率进行休眠 |
|
|
|
|
|
#print("Frame updated at:",time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def read(self): |
|
|
def read(self): |
|
|
with self.read_lock: |
|
|
# with self.read_lock: |
|
|
frame = self.frame |
|
|
# frame = self.frame.copy() if self.frame is not None else None |
|
|
return frame is not None, frame |
|
|
if not self.frame_queue.empty(): |
|
|
|
|
|
return True, self.frame_queue.get() |
|
|
|
|
|
else: |
|
|
|
|
|
return False, None |
|
|
|
|
|
|
|
|
def release(self): |
|
|
def release(self): |
|
|
self.running = False |
|
|
self.running = False |
|
@ -65,28 +75,21 @@ class ModelManager: |
|
|
self.logger = LogHandler().get_logger("ModelManager") |
|
|
self.logger = LogHandler().get_logger("ModelManager") |
|
|
# 本地YOLOv5仓库路径 |
|
|
# 本地YOLOv5仓库路径 |
|
|
self.yolov5_path = myCongif.get_data("yolov5_path") |
|
|
self.yolov5_path = myCongif.get_data("yolov5_path") |
|
|
self.buflen = myCongif.get_data("buffer_len") |
|
|
#self.buflen = myCongif.get_data("buffer_len") |
|
|
self.icout_max = myCongif.get_data("RESET_INTERVAL") #跟视频帧序用一个变量 |
|
|
self.icout_max = myCongif.get_data("RESET_INTERVAL") #跟视频帧序用一个变量 |
|
|
self.frame_rate = myCongif.get_data("frame_rate") |
|
|
self.frame_rate = myCongif.get_data("frame_rate") |
|
|
self.frame_interval = 1.0 / int(myCongif.get_data("verify_rate")) |
|
|
self.frame_interval = 1.0 / int(myCongif.get_data("verify_rate")) |
|
|
#保存视频相关内容 |
|
|
#保存视频相关内容 |
|
|
|
|
|
self.FPS = myCongif.get_data("verify_rate") # 视频帧率--是否能实现动态帧率 |
|
|
self.fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 使用 mp4 编码 |
|
|
self.fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 使用 mp4 编码 |
|
|
#基于模型运行环境进行相应初始化工作 |
|
|
#基于模型运行环境进行相应初始化工作 |
|
|
if myCongif.get_data("model_platform") == "acl": |
|
|
# self.model_platform = myCongif.get_data("model_platform") |
|
|
self._init_acl() |
|
|
# if self.model_platform == "acl": |
|
|
|
|
|
# self._init_acl() |
|
|
|
|
|
|
|
|
def __del__(self): |
|
|
def __del__(self): |
|
|
self.logger.debug("释放资源") |
|
|
self.logger.debug("释放资源") |
|
|
|
|
|
|
|
|
def _init_acl(self): |
|
|
|
|
|
'''acl初始化函数''' |
|
|
|
|
|
self.device_id = 0 |
|
|
|
|
|
#step1 初始化 |
|
|
|
|
|
ret = acl.init() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _open_view(self,url,itype): #打开摄像头 0--USB摄像头,1-RTSP,2-海康SDK |
|
|
def _open_view(self,url,itype): #打开摄像头 0--USB摄像头,1-RTSP,2-海康SDK |
|
|
if itype == 0: |
|
|
if itype == 0: |
|
|
cap = VideoCaptureWithFPS(int(url)) |
|
|
cap = VideoCaptureWithFPS(int(url)) |
|
@ -96,8 +99,14 @@ class ModelManager: |
|
|
raise Exception("视频参数错误!") |
|
|
raise Exception("视频参数错误!") |
|
|
return cap |
|
|
return cap |
|
|
|
|
|
|
|
|
def _import_model(self,model_name,model_path): |
|
|
def _import_model(self,model_name,model_path,threshold): |
|
|
'''根据路径,动态导入模块''' |
|
|
''' |
|
|
|
|
|
根据路径,动态导入模块 |
|
|
|
|
|
:param model_name: 模块名称 |
|
|
|
|
|
:param model_path: 模块路径 |
|
|
|
|
|
:param threshold: 置信阈值 |
|
|
|
|
|
:return: |
|
|
|
|
|
''' |
|
|
if os.path.exists(model_path): |
|
|
if os.path.exists(model_path): |
|
|
module_spec = importlib.util.spec_from_file_location(model_name, model_path) |
|
|
module_spec = importlib.util.spec_from_file_location(model_name, model_path) |
|
|
if module_spec is None: |
|
|
if module_spec is None: |
|
@ -105,7 +114,7 @@ class ModelManager: |
|
|
return None |
|
|
return None |
|
|
module = importlib.util.module_from_spec(module_spec) |
|
|
module = importlib.util.module_from_spec(module_spec) |
|
|
module_spec.loader.exec_module(module) |
|
|
module_spec.loader.exec_module(module) |
|
|
md = getattr(module, "Model")(model_path) |
|
|
md = getattr(module, "Model")(model_path,threshold) #实例化类 |
|
|
if not isinstance(md, ModelBase): |
|
|
if not isinstance(md, ModelBase): |
|
|
self.logger.error("{} not zf_model".format(md)) |
|
|
self.logger.error("{} not zf_model".format(md)) |
|
|
return None |
|
|
return None |
|
@ -160,36 +169,38 @@ class ModelManager: |
|
|
def verify(self,frame,myModle_list,myModle_data,channel_id,schedule_list,result_list,isdraw=1): |
|
|
def verify(self,frame,myModle_list,myModle_data,channel_id,schedule_list,result_list,isdraw=1): |
|
|
'''验证执行主函数,实现遍历通道关联的模型,调用对应模型执行验证,模型文件遍历执行''' |
|
|
'''验证执行主函数,实现遍历通道关联的模型,调用对应模型执行验证,模型文件遍历执行''' |
|
|
img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) |
|
|
img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) |
|
|
|
|
|
#img = np.ascontiguousarray(img, dtype=np.float32) / 255.0 # 转换为内存连续存储的数组 --该函数可以待定下是不是所有模型都可以做 |
|
|
# img = frame.to_ndarray(format="bgr24") |
|
|
# img = frame.to_ndarray(format="bgr24") |
|
|
|
|
|
#img = frame |
|
|
# 使用 模型 进行目标检测 |
|
|
# 使用 模型 进行目标检测 |
|
|
i_warn_count = 0 #报警标签 |
|
|
i_warn_count = 0 #报警标签 |
|
|
isverify = False |
|
|
isverify = False |
|
|
for i in range(len(myModle_list)): # 遍历通道关联的算法进行检测,若不控制模型数量,有可能需要考虑多线程执行。 |
|
|
# for i in range(len(myModle_list)): # 遍历通道关联的算法进行检测,若不控制模型数量,有可能需要考虑多线程执行。 |
|
|
model = myModle_list[i] |
|
|
# model = myModle_list[i] |
|
|
data = myModle_data[i] |
|
|
# data = myModle_data[i] |
|
|
schedule = schedule_list[i] |
|
|
# schedule = schedule_list[i] |
|
|
result = result_list[i] |
|
|
# result = result_list[i] |
|
|
#验证检测计划,是否在布防时间内 |
|
|
# #验证检测计划,是否在布防时间内 |
|
|
now = datetime.datetime.now() # 获取当前日期和时间 |
|
|
# now = datetime.datetime.now() # 获取当前日期和时间 |
|
|
weekday = now.weekday() # 获取星期几,星期一是0,星期天是6 |
|
|
# weekday = now.weekday() # 获取星期几,星期一是0,星期天是6 |
|
|
hour = now.hour |
|
|
# hour = now.hour |
|
|
result.pop(0) # 保障结果数组定长 --先把最早的结果推出数组 |
|
|
# result.pop(0) # 保障结果数组定长 --先把最早的结果推出数组 |
|
|
if schedule[weekday][hour] == 1: #不在计划则不进行验证,直接返回图片 |
|
|
# if schedule[weekday][hour] == 1: #不在计划则不进行验证,直接返回图片 |
|
|
# 调用模型,进行检测,model是动态加载的,具体的判断标准由模型内执行 ---- ********* |
|
|
# # 调用模型,进行检测,model是动态加载的,具体的判断标准由模型内执行 ---- ********* |
|
|
isverify = True |
|
|
# isverify = True |
|
|
detections, bwarn, warntext = model.verify(img, data,isdraw) #****************重要 |
|
|
# detections, bwarn, warntext = model.verify(img, data,isdraw) #****************重要 |
|
|
# 对识别结果要部要进行处理 |
|
|
# # 对识别结果要部要进行处理 |
|
|
if bwarn: # 整个识别有产生报警 |
|
|
# if bwarn: # 整个识别有产生报警 |
|
|
#根据模型设定的时间和占比判断是否 |
|
|
# #根据模型设定的时间和占比判断是否 |
|
|
# 绘制报警文本 |
|
|
# # 绘制报警文本 |
|
|
cv2.putText(img, 'Intruder detected!', (50, (i_warn_count + 1) * 50), |
|
|
# cv2.putText(img, 'Intruder detected!', (50, (i_warn_count + 1) * 50), |
|
|
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) |
|
|
# cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) |
|
|
i_warn_count += 1 |
|
|
# i_warn_count += 1 |
|
|
result.append(1) #要验证数组修改,是地址修改吗? |
|
|
# result.append(1) #要验证数组修改,是地址修改吗? |
|
|
else: #没有产生报警也需要记录,统一计算占比 |
|
|
# else: #没有产生报警也需要记录,统一计算占比 |
|
|
result.append(0) |
|
|
# result.append(0) |
|
|
else: |
|
|
# else: |
|
|
result.append(0) |
|
|
# result.append(0) |
|
|
if not isverify: #没做处理,直接返回的,需要控制下帧率,太快读取没有意义。 |
|
|
if not isverify: #没做处理,直接返回的,需要控制下帧率,太快读取没有意义。 |
|
|
time.sleep(1.0/self.frame_rate) #给个默认帧率,不超过30帧,---若经过模型计算,CPU下单模型也就12帧这样 |
|
|
time.sleep(1.0/self.frame_rate) #给个默认帧率,不超过30帧,---若经过模型计算,CPU下单模型也就12帧这样 |
|
|
|
|
|
|
|
@ -210,14 +221,14 @@ class ModelManager: |
|
|
def dowork_thread(self,channel_id): |
|
|
def dowork_thread(self,channel_id): |
|
|
'''一个通道一个线程,关联的模型在一个线程检测,局部变量都是一个通道独有''' |
|
|
'''一个通道一个线程,关联的模型在一个线程检测,局部变量都是一个通道独有''' |
|
|
channel_data = self.verify_list[channel_id] #一通道一线程 [url,type,True,img_buffer,img,icount] |
|
|
channel_data = self.verify_list[channel_id] #一通道一线程 [url,type,True,img_buffer,img,icount] |
|
|
|
|
|
view_buffer_deque = deque(maxlen=myCongif.get_data("buffer_len")) |
|
|
cap = None |
|
|
|
|
|
#查询关联的模型 --- 在循环运行前把基础数据都准备好 |
|
|
#查询关联的模型 --- 在循环运行前把基础数据都准备好 |
|
|
myDBM = DBManager() |
|
|
myDBM = DBManager() |
|
|
myDBM.connect() |
|
|
myDBM.connect() |
|
|
strsql = (f"select t1.model_id,t1.check_area,t1.polygon ,t2.duration_time,t2.proportion,t2.model_path,t1.ID," |
|
|
strsql = (f"select t1.model_id,t1.check_area,t1.polygon ,t2.duration_time,t2.proportion,t2.model_path,t1.ID," |
|
|
f"t2.model_name " |
|
|
f"t2.model_name,t1.conf_threshold " |
|
|
f"from channel2model t1 left join model t2 on t1.model_id = t2.ID where t1.channel_id ={channel_id};") |
|
|
f"from channel2model t1 left join model t2 on t1.model_id = t2.ID where t1.channel_id ={channel_id};") |
|
|
|
|
|
#print(strsql) |
|
|
myModels = myDBM.do_select(strsql) |
|
|
myModels = myDBM.do_select(strsql) |
|
|
#加载模型 --- 是不是要做个限制,一个视频通道关联算法模块的上限 --- 关联多了一个线程执行耗时较多,造成帧率太低,或者再多线程并发 #? |
|
|
#加载模型 --- 是不是要做个限制,一个视频通道关联算法模块的上限 --- 关联多了一个线程执行耗时较多,造成帧率太低,或者再多线程并发 #? |
|
|
|
|
|
|
|
@ -225,55 +236,50 @@ class ModelManager: |
|
|
myModle_data = [] #存放检测参数 一个模型一个 |
|
|
myModle_data = [] #存放检测参数 一个模型一个 |
|
|
schedule_list = [] #布防策略 -一个模型一个 |
|
|
schedule_list = [] #布防策略 -一个模型一个 |
|
|
result_list = [] #检测结果记录 -一个模型一个 |
|
|
result_list = [] #检测结果记录 -一个模型一个 |
|
|
proportion_lsit = []#占比设定 -一个模型一个 |
|
|
proportion_list = []#占比设定 -一个模型一个 |
|
|
warn_save_count = []#没个模型触发报警后,保存录像的最新帧序号 -一个模型一个 |
|
|
warn_save_count = []#没个模型触发报警后,保存录像的最新帧序号 -一个模型一个 |
|
|
|
|
|
threshold_list = [] #模型针对该通道的一个置信阈值, -个模型一个 |
|
|
|
|
|
|
|
|
view_buffer = [] |
|
|
view_buffer = [] |
|
|
ibuffer_count = 0 |
|
|
ibuffer_count = 0 |
|
|
last_img = None |
|
|
last_img = None |
|
|
|
|
|
|
|
|
|
|
|
#获取视频通道的模型相关数据-list |
|
|
for model in myModels: |
|
|
for model in myModels: |
|
|
#基于基类实例化模块类 |
|
|
#基于基类实例化模块类 |
|
|
m = self._import_model("",model[5]) #动态加载模型 |
|
|
m = self._import_model("",model[5],model[8]) #动态加载模型处理文件py --需要验证模型文件是否能加载 |
|
|
if m: |
|
|
if m: |
|
|
myModle_list.append(m) |
|
|
myModle_list.append(m) #没有成功加载的模型原画输出 |
|
|
myModle_data.append(model) |
|
|
myModle_data.append(model) |
|
|
#model[6] -- c2m_id --把通道对于模型的 0-周一,6-周日 |
|
|
#model[6] -- c2m_id --把通道对于模型的 0-周一,6-周日 |
|
|
schedule_list.append(self.getschedule(model[6],myDBM)) |
|
|
schedule_list.append(self.getschedule(model[6],myDBM)) |
|
|
result = [0 for _ in range(model[3] * myCongif.get_data("verify_rate"))] #初始化时间*验证帧率数量的结果list |
|
|
result = [0 for _ in range(model[3] * myCongif.get_data("verify_rate"))] #初始化时间*验证帧率数量的结果list |
|
|
result_list.append(result) |
|
|
result_list.append(result) |
|
|
proportion_lsit.append(model[4]) |
|
|
proportion_list.append(model[4]) #判断是否报警的占比 |
|
|
warn_save_count.append(0) #保存录像的最新帧初始化为0 |
|
|
warn_save_count.append(0) #保存录像的最新帧初始化为0 |
|
|
|
|
|
|
|
|
# if not myModle_list: #没有成功加载的模型原画输出 |
|
|
#开始拉取画面循环检测 |
|
|
# self.logger.info(f"视频通道:{channel_id},未配置算法模块,结束线程!") |
|
|
cap = None |
|
|
# return #可以不结束,直接返回未处理画面显示。 |
|
|
iread_count =0 #失败读取的次数 |
|
|
#开始循环检测 |
|
|
last_frame_time = time.time() #初始化个读帧时间 |
|
|
#print(mydata[0],mydata[1],mydata[2],mydata[3]) # url type tag img_buffer |
|
|
|
|
|
#[url,type,True,img_buffer] |
|
|
|
|
|
iread_count =0 |
|
|
|
|
|
last_frame_time = time.time() |
|
|
|
|
|
#保存视频录像使用 -- 放在循环外面,可以减少点消耗 |
|
|
|
|
|
FPS = myCongif.get_data("verify_rate") # 视频帧率 |
|
|
|
|
|
fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 使用 mp4 编码 |
|
|
|
|
|
while channel_data[2]: #基于tag 作为运行标识。 线程里只是读,住线程更新,最多晚一轮,应该不用线程锁。需验证 |
|
|
while channel_data[2]: #基于tag 作为运行标识。 线程里只是读,住线程更新,最多晚一轮,应该不用线程锁。需验证 |
|
|
# 需要控制帧率 |
|
|
# 帧率控制帧率 |
|
|
current_time = time.time() |
|
|
current_time = time.time() |
|
|
elapsed_time = current_time - last_frame_time |
|
|
elapsed_time = current_time - last_frame_time |
|
|
if elapsed_time < self.frame_interval: |
|
|
if elapsed_time < self.frame_interval: |
|
|
time.sleep(self.frame_interval - elapsed_time) #若小于间隔时间则休眠 |
|
|
time.sleep(self.frame_interval - elapsed_time) #若小于间隔时间则休眠 |
|
|
last_frame_time = time.time() |
|
|
|
|
|
#*********取画面************* |
|
|
#*********取画面************* |
|
|
if not cap: #还没连接视频源 |
|
|
if not cap: #第一次需要打开视频流 |
|
|
try: |
|
|
try: |
|
|
cap = self._open_view(channel_data[0],channel_data[1]) |
|
|
cap = self._open_view(channel_data[0],channel_data[1]) #创建子线程读画面 |
|
|
iread_count = 0 |
|
|
iread_count = 0 |
|
|
except: |
|
|
except: |
|
|
self.logger.error("参数错误,终止线程") |
|
|
self.logger.error("打开视频参数错误,终止线程!") |
|
|
return |
|
|
return |
|
|
ret,frame = cap.read() |
|
|
ret,frame = cap.read() |
|
|
if not ret: |
|
|
if not ret: |
|
|
if iread_count > 60: |
|
|
if iread_count > 30: |
|
|
self.logger.warning(f"通道-{channel_id}:view disconnected. Reconnecting...") |
|
|
self.logger.warning(f"通道-{channel_id}:view disconnected. Reconnecting...") |
|
|
cap.release() |
|
|
cap.release() |
|
|
cap = None |
|
|
cap = None |
|
@ -283,25 +289,23 @@ class ModelManager: |
|
|
time.sleep(1.0/20) #20帧只是作为个默认参考值,一般验证帧率都比这个慢 |
|
|
time.sleep(1.0/20) #20帧只是作为个默认参考值,一般验证帧率都比这个慢 |
|
|
continue #没读到画面继续 |
|
|
continue #没读到画面继续 |
|
|
iread_count = 0 #重置下视频帧计算 |
|
|
iread_count = 0 #重置下视频帧计算 |
|
|
|
|
|
last_frame_time = time.time() |
|
|
#执行图片推理 -- 如何没有模型或不在工作时间,返回的是原画,要不要控制下帧率? -- 在verify中做了sleep |
|
|
#执行图片推理 -- 如何没有模型或不在工作时间,返回的是原画,要不要控制下帧率? -- 在verify中做了sleep |
|
|
new_frame,img = self.verify(frame,myModle_list,myModle_data,channel_id,schedule_list,result_list) |
|
|
new_frame,img = self.verify(frame,myModle_list,myModle_data,channel_id,schedule_list,result_list) |
|
|
|
|
|
|
|
|
#分析图片放入内存中 |
|
|
#分析图片放入内存中 |
|
|
channel_data[3].append(img) |
|
|
channel_data[3].append(img) # 缓冲区大小由maxlen控制 超上限后,删除最前的数据 |
|
|
channel_data[5] += 1 #帧序列加一 |
|
|
channel_data[5] += 1 #帧序列加一 |
|
|
#print(self.verify_list[channel_id][5]) |
|
|
#print(self.verify_list[channel_id][5]) |
|
|
if channel_data[5] > self.icout_max: |
|
|
if channel_data[5] > self.icout_max: |
|
|
channel_data = 0 |
|
|
channel_data = 0 |
|
|
if len(channel_data[3]) > self.buflen: # 保持缓冲区大小---缓冲区可以用来保持录像 |
|
|
channel_data[4] = new_frame #一直更新最新帧********** |
|
|
channel_data[3].pop(0) |
|
|
#print(f"{channel_id}--Frame updated at:",time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) |
|
|
#self.logger.debug("drop one frame!") |
|
|
|
|
|
channel_data[4] = new_frame #一直更新最新帧 |
|
|
|
|
|
|
|
|
|
|
|
#验证result_list -是否触发报警要求 |
|
|
#验证result_list -是否触发报警要求 |
|
|
for i in range(len(result_list)): |
|
|
for i in range(len(result_list)): |
|
|
result = result_list[i] |
|
|
result = result_list[i] |
|
|
proportion = proportion_lsit[i] |
|
|
proportion = proportion_list[i] |
|
|
|
|
|
|
|
|
count_one = float(sum(result)) #1,0 把1累加的和就是1的数量 |
|
|
count_one = float(sum(result)) #1,0 把1累加的和就是1的数量 |
|
|
ratio_of_ones = count_one / len(result) |
|
|
ratio_of_ones = count_one / len(result) |
|
@ -311,7 +315,7 @@ class ModelManager: |
|
|
w_s_count = warn_save_count[i] |
|
|
w_s_count = warn_save_count[i] |
|
|
buffer_count = channel_data[5] |
|
|
buffer_count = channel_data[5] |
|
|
self.save_warn(model_name,w_s_count,buffer_count,channel_data[3],cap.width,cap.height, |
|
|
self.save_warn(model_name,w_s_count,buffer_count,channel_data[3],cap.width,cap.height, |
|
|
channel_id,myDBM,FPS,fourcc) |
|
|
channel_id,myDBM,self.FPS,self.fourcc) |
|
|
self.send_warn() |
|
|
self.send_warn() |
|
|
#更新帧序列号 |
|
|
#更新帧序列号 |
|
|
warn_save_count[i] = buffer_count |
|
|
warn_save_count[i] = buffer_count |
|
@ -327,7 +331,7 @@ class ModelManager: |
|
|
# break |
|
|
# break |
|
|
#结束线程 |
|
|
#结束线程 |
|
|
cap.release() |
|
|
cap.release() |
|
|
cv2.destroyAllWindows() |
|
|
#cv2.destroyAllWindows() |
|
|
|
|
|
|
|
|
def save_warn(self,model_name,w_s_count,buffer_count,buffer,width,height,channnel_id,myDBM,FPS,fourcc): |
|
|
def save_warn(self,model_name,w_s_count,buffer_count,buffer,width,height,channnel_id,myDBM,FPS,fourcc): |
|
|
''' |
|
|
''' |
|
@ -372,7 +376,6 @@ class ModelManager: |
|
|
ret = myDBM.do_sql(strsql) |
|
|
ret = myDBM.do_sql(strsql) |
|
|
return ret |
|
|
return ret |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def send_warn(self): |
|
|
def send_warn(self): |
|
|
'''发送报警信息''' |
|
|
'''发送报警信息''' |
|
|
pass |
|
|
pass |
|
@ -392,7 +395,7 @@ class ModelManager: |
|
|
strsql = f"select id,ulr,type from channel where is_work = 1 and id = {channel_id};" #单通道启动检测线程 |
|
|
strsql = f"select id,ulr,type from channel where is_work = 1 and id = {channel_id};" #单通道启动检测线程 |
|
|
datas = mDBM.do_select(strsql) |
|
|
datas = mDBM.do_select(strsql) |
|
|
for data in datas: |
|
|
for data in datas: |
|
|
img_buffer = [] |
|
|
img_buffer = deque(maxlen=myCongif.get_data("buffer_len")) #创建个定长的视频buffer |
|
|
img = None |
|
|
img = None |
|
|
icout = 0 #跟img_buffer对应,记录进入缓冲区的帧序列号 |
|
|
icout = 0 #跟img_buffer对应,记录进入缓冲区的帧序列号 |
|
|
run_data = [data[1],data[2],True,img_buffer,img,icout] |
|
|
run_data = [data[1],data[2],True,img_buffer,img,icout] |
|
@ -400,7 +403,6 @@ class ModelManager: |
|
|
th_chn = threading.Thread(target=self.dowork_thread, args=(data[0],)) #一个视频通道一个线程,线程句柄暂时部保留 |
|
|
th_chn = threading.Thread(target=self.dowork_thread, args=(data[0],)) #一个视频通道一个线程,线程句柄暂时部保留 |
|
|
th_chn.start() |
|
|
th_chn.start() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def stop_work(self,channel_id=0): |
|
|
def stop_work(self,channel_id=0): |
|
|
'''停止工作线程,0-停止所有,非0停止对应通道ID的线程''' |
|
|
'''停止工作线程,0-停止所有,非0停止对应通道ID的线程''' |
|
|
if channel_id ==0: #所有线程停止 |
|
|
if channel_id ==0: #所有线程停止 |
|
@ -418,38 +420,36 @@ class ModelManager: |
|
|
|
|
|
|
|
|
#print(f"Current working directory (ModelManager.py): {os.getcwd()}") |
|
|
#print(f"Current working directory (ModelManager.py): {os.getcwd()}") |
|
|
mMM = ModelManager() |
|
|
mMM = ModelManager() |
|
|
def test(): |
|
|
def test1(): |
|
|
buffer = [np.zeros((480, 640, 3), dtype=np.uint8) for _ in range(60)] # 示例帧列表 |
|
|
|
|
|
FRAME_WIDTH = 640 # 根据你的图像尺寸设置 |
|
|
print(cv2.getBuildInformation()) |
|
|
FRAME_HEIGHT = 480 # 根据你的图像尺寸设置 |
|
|
source = 'rtsp://192.168.3.44/live1' |
|
|
FPS = myCongif.get_data("verify_rate") # 你的视频帧率 |
|
|
gstreamer_pipeline = ( |
|
|
fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 使用 mp4 编码 |
|
|
f"rtspsrc location={source} protocols=udp latency=0 ! " |
|
|
now = datetime.datetime.now() # 获取当前日期和时间 |
|
|
"rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! appsink" |
|
|
current_time_str = now.strftime("%Y-%m-%d_%H-%M-%S") |
|
|
) |
|
|
filename = f"{2}_{current_time_str}.mp4" |
|
|
cap = cv2.VideoCapture(gstreamer_pipeline, cv2.CAP_GSTREAMER) |
|
|
#filename = "saved_video.mp4" |
|
|
if not cap.isOpened(): |
|
|
print(filename) |
|
|
print("Error: Unable to open the video source.") |
|
|
# 保存视频 |
|
|
return |
|
|
video_writer = cv2.VideoWriter(filename, fourcc, FPS, (FRAME_WIDTH, FRAME_HEIGHT)) |
|
|
|
|
|
if not video_writer.isOpened(): |
|
|
|
|
|
print(f"Failed to open video writer for filename") |
|
|
|
|
|
return False |
|
|
|
|
|
for frame in buffer: |
|
|
|
|
|
video_writer.write(frame) |
|
|
|
|
|
video_writer.release() |
|
|
|
|
|
# 保存图片 |
|
|
|
|
|
ret = cv2.imwrite("saved_frame.jpg", buffer[-1]) |
|
|
|
|
|
if ret: |
|
|
|
|
|
print("保存图片成功") |
|
|
|
|
|
else: |
|
|
else: |
|
|
print("保存图片失败") |
|
|
print("Successfully opened the video source.") |
|
|
return False |
|
|
ret, frame = cap.read() |
|
|
|
|
|
if ret: |
|
|
|
|
|
cv2.imshow('Frame', frame) |
|
|
|
|
|
cv2.waitKey(0) |
|
|
|
|
|
cap.release() |
|
|
|
|
|
cv2.destroyAllWindows() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
if __name__ == "__main__": |
|
|
#mMM.start_work() |
|
|
#mMM.start_work() |
|
|
# model = ModelManager()._import_model("", "../model/plugins/RYRQ/RYRQ_Model_ACL.py") |
|
|
test1() |
|
|
# model.testRun() |
|
|
print("111") |
|
|
test() |
|
|
# name = acl.get_soc_name() |
|
|
|
|
|
# count, ret = acl.rt.get_device_count() |
|
|
|
|
|
# print(name,count) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|