You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
5.4 KiB
134 lines
5.4 KiB
7 months ago
|
import threading
|
||
|
import importlib.util
|
||
|
import time
|
||
|
from myutils.MyDeque import MyDeque
|
||
|
from myutils.ConfigManager import myCongif
|
||
|
from myutils.MyLogger_logger import LogHandler
|
||
|
from core.ACLModelManager import ACLModeManger
|
||
|
from core.DataStruct import ModelinData,ModeloutData
|
||
|
from threading import Lock
|
||
|
|
||
|
class ModelNode:
|
||
|
def __init__(self,device,model_path):
|
||
|
self.device = device
|
||
|
self.model_path = model_path
|
||
|
self.model = None #模型对象
|
||
|
self.model_th = None #模型线程句柄
|
||
|
self.brun = True #模型控制标识
|
||
|
self.model_th_status = 0 #模型线程运行状态 0--初始状态,1-线程执行成功,2-线程退出
|
||
|
self.in_mq = MyDeque(50) #
|
||
|
self.channel_list = {} #channel_id out_mq --需要线程安全
|
||
|
self.clist_Lock = Lock() #channel_list的维护锁
|
||
|
self.ch_count = 0 #关联启动的通道数量
|
||
|
self.count_Lock = Lock() #count的维护锁
|
||
|
self.model_platform = myCongif.get_data("model_platform")
|
||
|
self.logger = LogHandler().get_logger("ModelNode")
|
||
|
|
||
|
|
||
|
|
||
|
def __del__(self):
|
||
|
pass
|
||
|
|
||
|
def _reset(self): #重置数据
|
||
|
#self.model_th_status = 0 # 模型线程运行状态 0--初始状态,1-线程执行成功,2-线程退出
|
||
|
self.in_mq.myclear()
|
||
|
|
||
|
def _import_model(self,model_path,threshold=0.5,iou_thres=0.5):
|
||
|
'''
|
||
|
根据路径,动态导入模块
|
||
|
:param model_path: 模块路径
|
||
|
:param threshold: 置信阈值
|
||
|
:param iou_thres: iou阈值
|
||
|
:return:
|
||
|
'''
|
||
|
try:
|
||
|
module_path = model_path.replace("/", ".").rsplit(".", 1)[0]
|
||
|
print(module_path)
|
||
|
# 动态导入模块
|
||
|
module = importlib.import_module(module_path)
|
||
|
# 从模块中获取指定的类
|
||
|
Model = getattr(module, "Model")
|
||
|
# 使用 Model 类
|
||
|
model_instance = Model(model_path,threshold,iou_thres)
|
||
|
return model_instance
|
||
|
except ModuleNotFoundError as e:
|
||
|
print(f"Module not found: {e}")
|
||
|
return None
|
||
|
except AttributeError as e:
|
||
|
print(f"Class not found in module: {e}")
|
||
|
return None
|
||
|
except Exception as e:
|
||
|
print(f"An unexpected error occurred: {e}")
|
||
|
return None
|
||
|
|
||
|
def _model_th(self):
|
||
|
# 加载自定义模型文件
|
||
|
self.model = self._import_model(self.model_path) # 动态加载模型处理文件py
|
||
|
if not self.model:
|
||
|
self.logger.error("自定义模型文件加载失败,退出model线程")
|
||
|
self.model_th_status = 2
|
||
|
return
|
||
|
# 初始化模型运行资源
|
||
|
context = None
|
||
|
if self.model_platform == "acl": # ACL线程中初始化内容
|
||
|
context = ACLModeManger.th_inti_acl(self.device) # 创建context
|
||
|
# 初始化模型资源 -- 加载模型文件
|
||
|
ret = self.model.init_acl_resource() # 加载和初始化离线模型文件--om文件
|
||
|
if not ret:
|
||
|
print("初始化模型资源出错,退出线程!")
|
||
|
self.model_th_status = 2
|
||
|
return
|
||
|
#执行工作
|
||
|
self.model_th_status = 1
|
||
|
while self.brun:
|
||
|
inData = self.in_mq.mypopleft() #空时,返回None #(self,channel_id,img,image,scale_ratio, pad_size):
|
||
|
if inData:
|
||
|
outputs = self.model.execute([inData.img,])#创建input,执行模型,返回结果 --失败返回None
|
||
|
outdata = ModeloutData(inData.image,inData.scale_ratio,inData.pad_size,outputs)
|
||
|
del inData.img
|
||
|
with self.clist_Lock:
|
||
|
if inData.channel_id in self.channel_list:
|
||
|
self.channel_list[inData.channel_id].myappend(outdata)
|
||
|
else:
|
||
|
time.sleep(0.05)
|
||
|
|
||
|
#结束线程,释放资源
|
||
|
self.model_th_status = 0
|
||
|
self._reset()
|
||
|
# 反初始化
|
||
|
if self.model_platform == "acl":
|
||
|
try:
|
||
|
self.model.release() # 释放模型资源资源
|
||
|
# 删除模型对象
|
||
|
del self.model
|
||
|
# 释放context
|
||
|
if context: # ACL线程中反初始化内容 -- 若线程异常退出,这些资源就不能正常释放了
|
||
|
# 再释放context
|
||
|
ACLModeManger.th_del_acl(context)
|
||
|
except Exception as e:
|
||
|
print(e)
|
||
|
|
||
|
def start_model_th(self,channel_id,out_mq):
|
||
|
with self.count_Lock:
|
||
|
with self.clist_Lock:
|
||
|
if channel_id in self.channel_list:
|
||
|
return #这个可以删除老的,新增新的
|
||
|
self.channel_list[channel_id] = out_mq
|
||
|
if self.ch_count == 0: #第一次启动线程
|
||
|
self.brun = True
|
||
|
self.model_th = threading.Thread(target=self._model_th)
|
||
|
self.model_th.start()
|
||
|
self.ch_count += 1 #有通道调用一次就加一
|
||
|
|
||
|
def stop_model_th(self,channel_id):
|
||
|
with self.count_Lock:
|
||
|
with self.clist_Lock:
|
||
|
if channel_id in self.channel_list:
|
||
|
del self.channel_list[channel_id]
|
||
|
self.ch_count -= 1
|
||
|
if self.ch_count == 0: #所有通道结束
|
||
|
self.brun = False
|
||
|
self.model_th.join()
|
||
|
self.model_th = None
|
||
|
|