19 changed files with 474 additions and 399 deletions
@ -0,0 +1,63 @@ |
|||||
|
from myutils.ConfigManager import myCongif |
||||
|
if myCongif.get_data("model_platform") == "acl": |
||||
|
import acl |
||||
|
|
||||
|
SUCCESS = 0 # 成功状态值 |
||||
|
FAILED = 1 # 失败状态值 |
||||
|
|
||||
|
class ACLModeManger: |
||||
|
def __init__(self,): |
||||
|
self.acl_ok = False |
||||
|
|
||||
|
def __del__(self): |
||||
|
pass |
||||
|
|
||||
|
#初始化acl相关资源--一个进程内只能调用一次acl.init接口 |
||||
|
@staticmethod |
||||
|
def init_acl(device_id): |
||||
|
# '''acl初始化函数''' |
||||
|
ret = acl.init() # 0-成功,其它失败 |
||||
|
if ret: |
||||
|
raise RuntimeError(ret) |
||||
|
|
||||
|
ret = acl.rt.set_device(device_id) # 指定当前进程或线程中用于运算的Device。可以进程或线程中指定。*多设备时可以放线程* |
||||
|
# 在某一进程中指定Device,该进程内的多个线程可共用此Device显式创建Context(acl.rt.create_context接口)。 |
||||
|
if ret: |
||||
|
raise RuntimeError(ret) |
||||
|
print('ACL init Device Successfully') |
||||
|
|
||||
|
return True |
||||
|
|
||||
|
#去初始化 |
||||
|
@staticmethod |
||||
|
def del_acl(device_id): |
||||
|
'''Device去初始化''' |
||||
|
ret = acl.rt.reset_device(device_id) # 释放Device |
||||
|
if ret: |
||||
|
raise RuntimeError(ret) |
||||
|
|
||||
|
ret = acl.finalize() # 去初始化 0-成功,其它失败 --官方文档不建议放析构函数中执行 |
||||
|
if ret: |
||||
|
raise RuntimeError(ret) |
||||
|
print('ACL finalize Successfully') |
||||
|
return True |
||||
|
|
||||
|
@staticmethod |
||||
|
def th_inti_acl(device_id): |
||||
|
# 线程申请context |
||||
|
context, ret = acl.rt.create_context(device_id) # 显式创建一个Context |
||||
|
if ret: |
||||
|
raise RuntimeError(ret) |
||||
|
print('Init TH-Context Successfully') |
||||
|
return context |
||||
|
|
||||
|
@staticmethod |
||||
|
def th_del_acl(context): |
||||
|
#线程释放context |
||||
|
ret = acl.rt.destroy_context(context) # 释放 Context |
||||
|
if ret: |
||||
|
raise RuntimeError(ret) |
||||
|
print('Deinit TH-Context Successfully') |
||||
|
return True |
||||
|
|
||||
|
|
@ -0,0 +1,120 @@ |
|||||
|
import threading |
||||
|
from collections import deque |
||||
|
import numpy as np |
||||
|
import time |
||||
|
import copy |
||||
|
import queue |
||||
|
|
||||
|
class ChannelData: |
||||
|
def __init__(self, str_url, int_type, bool_run, deque_length,icount_max): |
||||
|
self.str_url = str_url #视频源地址 |
||||
|
self.int_type = int_type #视频源类型,0-usb,1-rtsp,2-hksdk |
||||
|
self.bool_run = bool_run #线程运行标识 |
||||
|
self.deque_frame = deque(maxlen=deque_length) |
||||
|
self.last_frame = None # 保存图片数据 |
||||
|
self.frame_queue = queue.Queue(maxsize=1) |
||||
|
self.counter = 0 #帧序列号--保存报警录像使用 |
||||
|
self.icount_max = icount_max #帧序列号上限 |
||||
|
self.lock = threading.RLock() # 用于保证线程安全 |
||||
|
|
||||
|
#添加一帧图片 |
||||
|
def add_deque(self, value): |
||||
|
self.deque_frame.append(value) #deque 满了以后会把前面的数据移除 |
||||
|
|
||||
|
#拷贝一份数据 |
||||
|
def copy_deque(self): |
||||
|
return copy.deepcopy(self.deque_frame) |
||||
|
|
||||
|
#获取最后一帧图片 |
||||
|
def get_last_frame(self): |
||||
|
with self.lock: |
||||
|
frame = self.last_frame |
||||
|
return frame |
||||
|
# if not self.frame_queue.empty(): |
||||
|
# return self.frame_queue.get() |
||||
|
# else: |
||||
|
# return None |
||||
|
|
||||
|
|
||||
|
def update_last_frame(self,buffer): |
||||
|
if buffer: |
||||
|
with self.lock: |
||||
|
self.last_frame = None |
||||
|
self.last_frame = buffer |
||||
|
# if not self.frame_queue.full(): |
||||
|
# self.frame_queue.put(buffer) |
||||
|
# else: |
||||
|
# self.frame_queue.get() # 丢弃最旧的帧 |
||||
|
# self.frame_queue.put(buffer) |
||||
|
|
||||
|
|
||||
|
#帧序列号自增 一个线程中处理,不用加锁 |
||||
|
def increment_counter(self): |
||||
|
self.counter += 1 |
||||
|
if self.counter > self.icount_max: |
||||
|
self.counter = 0 |
||||
|
|
||||
|
def get_counter(self): |
||||
|
return self.counter |
||||
|
|
||||
|
#清空数据,主要是删除deque 和 last_frame |
||||
|
def clear(self): |
||||
|
with self.lock: |
||||
|
self.bool_run = False |
||||
|
time.sleep(1) #休眠一秒,等待通道对应的子线程,停止工作。 |
||||
|
self.deque_frame.clear() |
||||
|
self.last_frame = None |
||||
|
|
||||
|
def stop_run(self): |
||||
|
self.bool_run = False |
||||
|
|
||||
|
|
||||
|
class ChannelManager: |
||||
|
def __init__(self): |
||||
|
self.channels = {} |
||||
|
self.lock = threading.RLock() # 用于保证字典操作的线程安全 |
||||
|
|
||||
|
#增加节点 |
||||
|
def add_channel(self, channel_id, str_url, int_type, bool_run, deque_length=10,icount_max=100000): |
||||
|
with self.lock: |
||||
|
if channel_id in self.channels: #若已经有数据,先删除后再增加 |
||||
|
self.channels[channel_id].clear() # 手动清理资源 |
||||
|
del self.channels[channel_id] |
||||
|
self.channels[channel_id] = ChannelData(str_url, int_type, bool_run, deque_length,icount_max) |
||||
|
|
||||
|
#删除节点 |
||||
|
def delete_channel(self, channel_id): |
||||
|
with self.lock: |
||||
|
if channel_id in self.channels: |
||||
|
self.channels[channel_id].clear() # 手动清理资源 |
||||
|
del self.channels[channel_id] |
||||
|
|
||||
|
#获取节点 |
||||
|
def get_channel(self, channel_id): |
||||
|
with self.lock: |
||||
|
return self.channels.get(channel_id) |
||||
|
|
||||
|
#停止工作线程 |
||||
|
def stop_channel(self,channel_id): |
||||
|
with self.lock: |
||||
|
if channel_id == 0: |
||||
|
for clannel_id,clannel_data in self.channels.items(): |
||||
|
clannel_data.clear() |
||||
|
del self.channels |
||||
|
else: |
||||
|
if channel_id in self.channels: |
||||
|
self.channels[channel_id].clear() # 手动清理资源 |
||||
|
del self.channels[channel_id] |
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
# 示例使用 |
||||
|
manager = ChannelManager() |
||||
|
manager.add_channel('channel_1', 'test', 123, True, deque_length=5) |
||||
|
|
||||
|
# 更新和读取操作 |
||||
|
manager.update_channel_deque('channel_1', 'data1') |
||||
|
manager.update_channel_buffer('channel_1', np.array([[1, 2], [3, 4]])) |
||||
|
manager.increment_channel_counter('channel_1') |
||||
|
|
||||
|
channel_data = manager.get_channel_data('channel_1') |
||||
|
print(channel_data) |
@ -1,49 +0,0 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html lang="en"> |
|
||||
<head> |
|
||||
<meta charset="UTF-8"> |
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
||||
<title>YOLOv5 Video Streams</title> |
|
||||
<style> |
|
||||
body { |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
height: 100vh; |
|
||||
margin: 0; |
|
||||
background-color: #f0f0f0; |
|
||||
} |
|
||||
.grid-container { |
|
||||
display: grid; |
|
||||
grid-template-columns: repeat(3, 1fr); |
|
||||
grid-template-rows: repeat(3, 1fr); |
|
||||
gap: 10px; |
|
||||
width: 90vw; |
|
||||
height: 90vh; |
|
||||
} |
|
||||
.grid-item { |
|
||||
position: relative; |
|
||||
width: 100%; |
|
||||
padding-top: 75%; /* 4:3 aspect ratio */ |
|
||||
} |
|
||||
.grid-item img { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
left: 0; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
object-fit: cover; |
|
||||
border-radius: 8px; |
|
||||
} |
|
||||
</style> |
|
||||
</head> |
|
||||
<body> |
|
||||
<div class="grid-container"> |
|
||||
{% for stream_id in streams %} |
|
||||
<div class="grid-item"> |
|
||||
<img src="{{ url_for('video_feed', stream_id=stream_id) }}" alt="Stream {{ stream_id }}"> |
|
||||
</div> |
|
||||
{% endfor %} |
|
||||
</div> |
|
||||
</body> |
|
||||
</html> |
|
Binary file not shown.
Loading…
Reference in new issue