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