updata
This commit is contained in:
commit
7625fff310
|
|
@ -0,0 +1,10 @@
|
|||
1.2025.01.21把之前的tuoheng alg仓库代码重新开个仓库 (1)在config/service/dsp_test_service.yml里面添加参数,控制存储用的oss还是minio storage_source: 1 2.2025.02.06 (1)修改代码,把mqtt读取加入到系统中。config/service/dsp_test_service.yml,中添加mqtt_flag,决定是否启用。 (2)修改了minio情况下的,文件名命名方式。 3.2025.02.12 (1)增加了对alg算法开发的代码。可以通过配置文件config/service/dsp_test_service.yml中algSwitch: true,决定是否启用。
|
||||
|
||||
4、2025.07.10 周树亮 - 增加人群计数,自研车牌模型,裸土覆盖3个场景
|
||||
|
||||
5、江朝庆 -- 0715
|
||||
1)代码整理,删除冗余代码。
|
||||
2)增加requirements.txt,方便部署
|
||||
3) logs
|
||||
|
||||
6 --0811
|
||||
|
|
@ -0,0 +1,443 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# 编码格式
|
||||
UTF_8 = "utf-8"
|
||||
|
||||
# 文件读模式
|
||||
R = 'r'
|
||||
ON_OR = "_on_or_"
|
||||
ON_AI = "_on_ai_"
|
||||
MP4 = ".mp4"
|
||||
# 初始化进度
|
||||
init_progess = "0.0000"
|
||||
# 进度100%
|
||||
success_progess = "1.0000"
|
||||
|
||||
# 拉流每帧图片缩小宽度大小限制, 大于1400像素缩小一半, 小于1400像素不变
|
||||
width = 1400
|
||||
|
||||
COLOR = (
|
||||
[0, 0, 255],
|
||||
[255, 0, 0],
|
||||
[211, 0, 148],
|
||||
[0, 127, 0],
|
||||
[0, 69, 255],
|
||||
[0, 255, 0],
|
||||
[255, 0, 255],
|
||||
[0, 0, 127],
|
||||
[127, 0, 255],
|
||||
[255, 129, 0],
|
||||
[139, 139, 0],
|
||||
[255, 255, 0],
|
||||
[127, 255, 0],
|
||||
[0, 127, 255],
|
||||
[0, 255, 127],
|
||||
[255, 127, 255],
|
||||
[8, 101, 139],
|
||||
[171, 130, 255],
|
||||
[139, 112, 74],
|
||||
[205, 205, 180])
|
||||
|
||||
ONLINE = "online"
|
||||
OFFLINE = "offline"
|
||||
PHOTO = "photo"
|
||||
RECORDING = "recording"
|
||||
|
||||
ONLINE_START_SCHEMA = {
|
||||
"request_id": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'regex': r'^[a-zA-Z0-9]{1,36}$'
|
||||
},
|
||||
"command": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'allowed': ["start"]
|
||||
},
|
||||
"pull_url": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'maxlength': 255
|
||||
},
|
||||
"push_url": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'maxlength': 255
|
||||
},
|
||||
"logo_url": {
|
||||
'type': 'string',
|
||||
'required': False,
|
||||
'nullable': True,
|
||||
'maxlength': 255
|
||||
},
|
||||
"models": {
|
||||
'type': 'list',
|
||||
'required': True,
|
||||
'nullable': False,
|
||||
'minlength': 1,
|
||||
'maxlength': 3,
|
||||
'schema': {
|
||||
'type': 'dict',
|
||||
'required': True,
|
||||
'schema': {
|
||||
"code": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'dependencies': "categories",
|
||||
'regex': r'^[a-zA-Z0-9]{1,255}$'
|
||||
},
|
||||
"is_video": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'dependencies': "code",
|
||||
'allowed': ["0", "1"]
|
||||
},
|
||||
"is_image": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'dependencies': "code",
|
||||
'allowed': ["0", "1"]
|
||||
},
|
||||
"categories": {
|
||||
'type': 'list',
|
||||
'required': True,
|
||||
'dependencies': "code",
|
||||
'schema': {
|
||||
'type': 'dict',
|
||||
'required': True,
|
||||
'schema': {
|
||||
"id": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'regex': r'^[a-zA-Z0-9]{0,255}$'},
|
||||
"config": {
|
||||
'type': 'dict',
|
||||
'required': False,
|
||||
'dependencies': "id",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ONLINE_STOP_SCHEMA = {
|
||||
"request_id": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'regex': r'^[a-zA-Z0-9]{1,36}$'
|
||||
},
|
||||
"command": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'allowed': ["stop"]
|
||||
}
|
||||
}
|
||||
|
||||
OFFLINE_START_SCHEMA = {
|
||||
"request_id": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'regex': r'^[a-zA-Z0-9]{1,36}$'
|
||||
},
|
||||
"command": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'allowed': ["start"]
|
||||
},
|
||||
"push_url": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'maxlength': 255
|
||||
},
|
||||
"pull_url": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'maxlength': 255
|
||||
},
|
||||
"logo_url": {
|
||||
'type': 'string',
|
||||
'required': False,
|
||||
'nullable': True,
|
||||
'maxlength': 255
|
||||
},
|
||||
"models": {
|
||||
'type': 'list',
|
||||
'required': True,
|
||||
'maxlength': 3,
|
||||
'minlength': 1,
|
||||
'schema': {
|
||||
'type': 'dict',
|
||||
'required': True,
|
||||
'schema': {
|
||||
"code": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'dependencies': "categories",
|
||||
'regex': r'^[a-zA-Z0-9]{1,255}$'
|
||||
},
|
||||
"is_video": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'dependencies': "code",
|
||||
'allowed': ["0", "1"]
|
||||
},
|
||||
"is_image": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'dependencies': "code",
|
||||
'allowed': ["0", "1"]
|
||||
},
|
||||
"categories": {
|
||||
'type': 'list',
|
||||
'required': True,
|
||||
'dependencies': "code",
|
||||
'schema': {
|
||||
'type': 'dict',
|
||||
'required': True,
|
||||
'schema': {
|
||||
"id": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'regex': r'^[a-zA-Z0-9]{0,255}$'},
|
||||
"config": {
|
||||
'type': 'dict',
|
||||
'required': False,
|
||||
'dependencies': "id",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OFFLINE_STOP_SCHEMA = {
|
||||
"request_id": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'regex': r'^[a-zA-Z0-9]{1,36}$'
|
||||
},
|
||||
"command": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'allowed': ["stop"]
|
||||
}
|
||||
}
|
||||
|
||||
IMAGE_SCHEMA = {
|
||||
"request_id": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'regex': r'^[a-zA-Z0-9]{1,36}$'
|
||||
},
|
||||
"command": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'allowed': ["start"]
|
||||
},
|
||||
"logo_url": {
|
||||
'type': 'string',
|
||||
'required': False,
|
||||
'nullable': True,
|
||||
'maxlength': 255
|
||||
},
|
||||
"image_urls": {
|
||||
'type': 'list',
|
||||
'required': True,
|
||||
'minlength': 1,
|
||||
'schema': {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'maxlength': 5000
|
||||
}
|
||||
},
|
||||
"models": {
|
||||
'type': 'list',
|
||||
'required': True,
|
||||
'schema': {
|
||||
'type': 'dict',
|
||||
'required': True,
|
||||
'schema': {
|
||||
"code": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'dependencies': "categories",
|
||||
'regex': r'^[a-zA-Z0-9]{1,255}$'
|
||||
},
|
||||
"is_video": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'dependencies': "code",
|
||||
'allowed': ["0", "1"]
|
||||
},
|
||||
"is_image": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'dependencies': "code",
|
||||
'allowed': ["0", "1"]
|
||||
},
|
||||
"categories": {
|
||||
'type': 'list',
|
||||
'required': True,
|
||||
'dependencies': "code",
|
||||
'schema': {
|
||||
'type': 'dict',
|
||||
'required': True,
|
||||
'schema': {
|
||||
"id": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'regex': r'^[a-zA-Z0-9]{0,255}$'},
|
||||
"config": {
|
||||
'type': 'dict',
|
||||
'required': False,
|
||||
'dependencies': "id",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RECORDING_START_SCHEMA = {
|
||||
"request_id": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'regex': r'^[a-zA-Z0-9]{1,36}$'
|
||||
},
|
||||
"command": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'allowed': ["start"]
|
||||
},
|
||||
"pull_url": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'maxlength': 255
|
||||
},
|
||||
"push_url": {
|
||||
'type': 'string',
|
||||
'required': False,
|
||||
'empty': True,
|
||||
'maxlength': 255
|
||||
},
|
||||
"logo_url": {
|
||||
'type': 'string',
|
||||
'required': False,
|
||||
'nullable': True,
|
||||
'maxlength': 255
|
||||
}
|
||||
}
|
||||
|
||||
RECORDING_STOP_SCHEMA = {
|
||||
"request_id": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'regex': r'^[a-zA-Z0-9]{1,36}$'
|
||||
},
|
||||
"command": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'allowed': ["stop"]
|
||||
}
|
||||
}
|
||||
|
||||
PULL2PUSH_START_SCHEMA = {
|
||||
"request_id": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'regex': r'^[a-zA-Z0-9]{1,36}$'
|
||||
},
|
||||
"command": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'allowed': ["start"]
|
||||
},
|
||||
"video_urls": {
|
||||
'type': 'list',
|
||||
'required': True,
|
||||
'nullable': False,
|
||||
'schema': {
|
||||
'type': 'dict',
|
||||
'required': True,
|
||||
'schema': {
|
||||
"id": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'dependencies': "pull_url",
|
||||
'regex': r'^[a-zA-Z0-9]{1,255}$'
|
||||
},
|
||||
"pull_url": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'dependencies': "push_url",
|
||||
'regex': r'^(https|http|rtsp|rtmp|artc|webrtc|ws)://\w.+$'
|
||||
},
|
||||
"push_url": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'dependencies': "id",
|
||||
'regex': r'^(https|http|rtsp|rtmp|artc|webrtc|ws)://\w.+$'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PULL2PUSH_STOP_SCHEMA = {
|
||||
"request_id": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'regex': r'^[a-zA-Z0-9]{1,36}$'
|
||||
},
|
||||
"command": {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'allowed': ["start", "stop"]
|
||||
},
|
||||
"video_ids": {
|
||||
'type': 'list',
|
||||
'required': False,
|
||||
'nullable': True,
|
||||
'schema': {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
'empty': False,
|
||||
'regex': r'^[a-zA-Z0-9]{1,255}$'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 服务配置路径
|
||||
service_yml_path = 'config/service/dsp_%s_service.yml'
|
||||
# kafka配置路径
|
||||
kafka_yml_path = 'config/kafka/dsp_%s_kafka.yml'
|
||||
# 阿里云配置路径
|
||||
aliyun_yml_path = "config/aliyun/dsp_%s_aliyun.yml"
|
||||
# 百度配置路径
|
||||
baidu_yml_path = 'config/baidu/dsp_%s_baidu.yml'
|
||||
# minio配置路径
|
||||
minio_yml_path = 'config/minio/dsp_%s_minio.yml'
|
||||
# mqtt配置路径
|
||||
mqtt_yml_path = 'config/mqtt/dsp_%s_mqtt.yml'
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
from threading import Thread
|
||||
from loguru import logger
|
||||
|
||||
|
||||
class Common(Thread):
|
||||
|
||||
__slots__ = ('__func', '__param1', '__param2', '__result')
|
||||
|
||||
def __init__(self, func, param1, param2):
|
||||
super(Common, self).__init__()
|
||||
self.__func = func
|
||||
self.__param1 = param1
|
||||
self.__param2 = param2
|
||||
self.__result = None
|
||||
|
||||
def get_result(self):
|
||||
self.join()
|
||||
return self.__result
|
||||
|
||||
def run(self):
|
||||
logger.info("开始执行线程!")
|
||||
self.__result = self.__func(self.__param1, self.__param2)
|
||||
logger.info("线程停止完成!")
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import time
|
||||
from threading import Thread
|
||||
from traceback import format_exc
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from util.KafkaUtils import CustomerKafkaProducer
|
||||
|
||||
'''
|
||||
问题反馈线程
|
||||
'''
|
||||
|
||||
|
||||
class FeedbackThread(Thread):
|
||||
__slots__ = ('__fbQueue', '__kafka_config')
|
||||
|
||||
def __init__(self, fbQueue, kafka_config):
|
||||
super().__init__()
|
||||
self.__fbQueue = fbQueue
|
||||
self.__kafka_config = kafka_config
|
||||
|
||||
'''
|
||||
阻塞获取反馈消息
|
||||
'''
|
||||
|
||||
def getFeedback(self):
|
||||
return self.__fbQueue.get()
|
||||
|
||||
def run(self):
|
||||
logger.info("启动问题反馈线程")
|
||||
kafkaProducer = CustomerKafkaProducer(self.__kafka_config)
|
||||
dsp_alg_results_topic = self.__kafka_config["topic"]["dsp-alg-results-topic"]
|
||||
dsp_recording_result_topic = self.__kafka_config["topic"]["dsp-recording-result-topic"]
|
||||
dsp_push_stream_result_topic = self.__kafka_config["topic"]["dsp-push-stream-result-topic"]
|
||||
while True:
|
||||
logger.info("问题反馈发送消息循环")
|
||||
feedback = None
|
||||
recording = None
|
||||
pull_stream = None
|
||||
try:
|
||||
fb = self.getFeedback()
|
||||
if fb is not None and len(fb) > 0:
|
||||
feedback = fb.get("feedback")
|
||||
recording = fb.get("recording")
|
||||
pull_stream = fb.get("pull_stream")
|
||||
if feedback is not None and len(feedback) > 0:
|
||||
kafkaProducer.sender(dsp_alg_results_topic, feedback["request_id"], feedback, 1)
|
||||
feedback = None
|
||||
if recording is not None and len(recording) > 0:
|
||||
kafkaProducer.sender(dsp_recording_result_topic, recording["request_id"], recording, 1)
|
||||
recording = None
|
||||
if pull_stream is not None and len(pull_stream) > 0:
|
||||
kafkaProducer.sender(dsp_push_stream_result_topic, pull_stream["request_id"], pull_stream, 1)
|
||||
pull_stream = None
|
||||
else:
|
||||
time.sleep(1)
|
||||
except Exception:
|
||||
if feedback and feedback.get("request_id"):
|
||||
logger.error("问题反馈异常:{}, requestId:{}", format_exc(), feedback.get("request_id"))
|
||||
elif recording and recording.get("request_id"):
|
||||
logger.error("问题反馈异常:{}, requestId:{}", format_exc(), recording.get("request_id"))
|
||||
elif pull_stream and pull_stream.get("request_id"):
|
||||
logger.error("问题反馈异常:{}, requestId:{}", format_exc(), pull_stream.get("request_id"))
|
||||
else:
|
||||
logger.error("问题反馈异常:{}", format_exc())
|
||||
logger.info("问题反馈线程执行完成")
|
||||
|
|
@ -0,0 +1,423 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from threading import Thread
|
||||
from time import sleep, time
|
||||
from traceback import format_exc
|
||||
|
||||
from loguru import logger
|
||||
import cv2
|
||||
from entity.FeedBack import message_feedback
|
||||
from enums.ExceptionEnum import ExceptionType
|
||||
from enums.ModelTypeEnum import ModelType
|
||||
from exception.CustomerException import ServiceException
|
||||
from util.AliyunSdk import AliyunOssSdk
|
||||
from util.MinioSdk import MinioSdk
|
||||
from util import TimeUtils
|
||||
from enums.AnalysisStatusEnum import AnalysisStatus
|
||||
from util.PlotsUtils import draw_painting_joint, draw_name_ocr, draw_name_crowd
|
||||
from util.QueUtil import put_queue, get_no_block_queue, clear_queue
|
||||
import io
|
||||
from util.LocationUtils import locate_byMqtt
|
||||
|
||||
|
||||
class FileUpload(Thread):
|
||||
__slots__ = ('_fb_queue', '_context', '_image_queue', '_analyse_type', '_msg', '_mqtt_list')
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
self._fb_queue, self._context, self._msg, self._image_queue, self._analyse_type, self._mqtt_list = args
|
||||
self._storage_source = self._context['service']['storage_source']
|
||||
self._algStatus = False # 默认关闭
|
||||
|
||||
# self._algStatus = True # 默认关闭
|
||||
self._algSwitch = self._context['service']['algSwitch']
|
||||
|
||||
# 0521:
|
||||
default_enabled = str(self._msg.get("defaultEnabled", "True")).lower() == "true"
|
||||
if default_enabled:
|
||||
print("执行默认程序(defaultEnabled=True)")
|
||||
self._algSwitch = True
|
||||
# 这里放默认逻辑的代码
|
||||
else:
|
||||
print("执行替代程序(defaultEnabled=False)")
|
||||
# 这里放非默认逻辑的代码
|
||||
self._algSwitch = False
|
||||
|
||||
print("---line46 :FileUploadThread.py---", self._algSwitch)
|
||||
|
||||
|
||||
# 如果任务是在线、离线处理,则用此类
|
||||
class ImageFileUpload(FileUpload):
|
||||
__slots__ = ()
|
||||
|
||||
# @staticmethod
|
||||
def handle_image(self, frame_msg, frame_step):
|
||||
# (high_score_image["code"], all_frames, draw_config["font_config"])
|
||||
# high_score_image["code"][code][cls] = (frame, frame_index_list[i], cls_list)
|
||||
det_xywh, frame, current_frame, all_frames, font_config = frame_msg
|
||||
'''
|
||||
det_xywh:{
|
||||
'code':{
|
||||
1: [[detect_targets_code, box, score, label_array, color,is_new]]
|
||||
}
|
||||
} #is_new--是否是新的目标。
|
||||
模型编号:modeCode
|
||||
检测目标:detectTargetCode
|
||||
'''
|
||||
print('*' * 100, ' mqtt_list:', len(self._mqtt_list))
|
||||
|
||||
model_info = []
|
||||
# 更加模型编码解析数据
|
||||
for code, det_list in det_xywh.items():
|
||||
if len(det_list) > 0:
|
||||
for cls, target_list in det_list.items():
|
||||
if len(target_list) > 0:
|
||||
aFrame = frame.copy()
|
||||
for target in target_list:
|
||||
# 自研车牌模型判断
|
||||
if ModelType.CITY_CARPLATE_MODEL.value[1] == str(code):
|
||||
draw_name_ocr(target[1], aFrame, target[4])
|
||||
elif ModelType.CITY_DENSECROWDCOUNT_MODEL.value[1] == str(code) or\
|
||||
ModelType.CITY_UNDERBUILDCOUNT_MODEL.value[1] == str(code):
|
||||
draw_name_crowd(target[1], aFrame, target[4])
|
||||
else:
|
||||
draw_painting_joint(target[1], aFrame, target[3], target[2], target[4], font_config,
|
||||
target[5])
|
||||
|
||||
igH, igW = aFrame.shape[0:2]
|
||||
if len(self._mqtt_list) >= 1:
|
||||
# camParas = self._mqtt_list[0]['data']
|
||||
camParas = self._mqtt_list[0]
|
||||
gps = locate_byMqtt(target[1], igW, igH, camParas, outFormat='wgs84')
|
||||
else:
|
||||
gps = [None, None]
|
||||
model_info.append(
|
||||
{"modelCode": str(code), "detectTargetCode": str(cls), "aFrame": aFrame, 'gps': gps})
|
||||
if len(model_info) > 0:
|
||||
image_result = {
|
||||
"or_frame": frame,
|
||||
"model_info": model_info,
|
||||
"current_frame": current_frame,
|
||||
"last_frame": current_frame + frame_step
|
||||
}
|
||||
return image_result
|
||||
return None
|
||||
|
||||
def run(self):
|
||||
msg, context = self._msg, self._context
|
||||
service = context["service"]
|
||||
base_dir, env, request_id = context["base_dir"], context["env"], msg["request_id"]
|
||||
logger.info("启动图片上传线程, requestId: {}", request_id)
|
||||
image_queue, fb_queue, analyse_type = self._image_queue, self._fb_queue, self._analyse_type
|
||||
service_timeout = int(service["timeout"])
|
||||
frame_step = int(service["filter"]["frame_step"]) + 120
|
||||
if msg['taskType'] == 0:
|
||||
self._algStatus = False
|
||||
else:
|
||||
self._algStatus = True
|
||||
try:
|
||||
with ThreadPoolExecutor(max_workers=2) as t:
|
||||
# 初始化oss客户端
|
||||
if self._storage_source == 1:
|
||||
minioSdk = MinioSdk(base_dir, env, request_id)
|
||||
else:
|
||||
aliyunOssSdk = AliyunOssSdk(base_dir, env, request_id)
|
||||
start_time = time()
|
||||
while True:
|
||||
try:
|
||||
if time() - start_time > service_timeout:
|
||||
logger.error("图片上传线程运行超时, requestId: {}", request_id)
|
||||
break
|
||||
raise ServiceException(ExceptionType.TASK_EXCUTE_TIMEOUT.value[0],
|
||||
ExceptionType.TASK_EXCUTE_TIMEOUT.value[1])
|
||||
# 获取队列中的消息
|
||||
image_msg = get_no_block_queue(image_queue)
|
||||
if image_msg is not None:
|
||||
|
||||
if image_msg[0] == 2:
|
||||
logger.info("图片上传线程收到命令:{}, requestId: {}", image_msg[1], request_id)
|
||||
if 'stop' == image_msg[1]:
|
||||
logger.info("开始停止图片上传线程, requestId:{}", request_id)
|
||||
break
|
||||
if 'algStart' == image_msg[1]: self._algStatus = True; logger.info(
|
||||
"图片上传线程,执行算法开启命令, requestId:{}", request_id)
|
||||
if 'algStop' == image_msg[1]: self._algStatus = False; logger.info(
|
||||
"图片上传线程,执行算法关闭命令, requestId:{}", request_id)
|
||||
|
||||
if image_msg[0] == 1:
|
||||
image_result = self.handle_image(image_msg[1], frame_step)
|
||||
if image_result is not None:
|
||||
task = []
|
||||
or_image = cv2.imencode(".jpg", image_result["or_frame"])[1]
|
||||
or_image_name = build_image_name(image_result["current_frame"],
|
||||
image_result["last_frame"],
|
||||
analyse_type,
|
||||
"OR", "0", "0", request_id)
|
||||
if self._storage_source == 1:
|
||||
or_future = t.submit(minioSdk.put_object, or_image, or_image_name)
|
||||
else:
|
||||
or_future = t.submit(aliyunOssSdk.put_object, or_image_name, or_image.tobytes())
|
||||
task.append(or_future)
|
||||
model_info_list = image_result["model_info"]
|
||||
msg_list = []
|
||||
for model_info in model_info_list:
|
||||
ai_image = cv2.imencode(".jpg", model_info["aFrame"])[1]
|
||||
ai_image_name = build_image_name(image_result["current_frame"],
|
||||
image_result["last_frame"],
|
||||
analyse_type,
|
||||
"AI",
|
||||
model_info["modelCode"],
|
||||
model_info["detectTargetCode"],
|
||||
request_id)
|
||||
if self._storage_source == 1:
|
||||
ai_future = t.submit(minioSdk.put_object, ai_image,
|
||||
ai_image_name)
|
||||
else:
|
||||
ai_future = t.submit(aliyunOssSdk.put_object, ai_image_name,
|
||||
ai_image.tobytes())
|
||||
|
||||
task.append(ai_future)
|
||||
# msg_list.append(message_feedback(request_id,
|
||||
# AnalysisStatus.RUNNING.value,
|
||||
# analyse_type, "", "", "",
|
||||
# or_image_name,
|
||||
# ai_image_name,
|
||||
# model_info['modelCode'],
|
||||
# model_info['detectTargetCode']))
|
||||
remote_image_list = []
|
||||
for tk in task:
|
||||
remote_image_list.append(tk.result())
|
||||
|
||||
for ii, model_info in enumerate(model_info_list):
|
||||
msg_list.append(message_feedback(request_id,
|
||||
AnalysisStatus.RUNNING.value,
|
||||
analyse_type, "", "", "",
|
||||
remote_image_list[0],
|
||||
remote_image_list[ii + 1],
|
||||
model_info['modelCode'],
|
||||
model_info['detectTargetCode'],
|
||||
longitude=model_info['gps'][0],
|
||||
latitude=model_info['gps'][1],
|
||||
))
|
||||
|
||||
if (not self._algSwitch) or (self._algStatus and self._algSwitch):
|
||||
for msg in msg_list:
|
||||
put_queue(fb_queue, msg, timeout=2, is_ex=False)
|
||||
del task, msg_list
|
||||
else:
|
||||
sleep(1)
|
||||
del image_msg
|
||||
except Exception:
|
||||
logger.error("图片上传异常:{}, requestId:{}", format_exc(), request_id)
|
||||
finally:
|
||||
logger.info("停止图片上传线程0, requestId:{}", request_id)
|
||||
clear_queue(image_queue)
|
||||
logger.info("停止图片上传线程1, requestId:{}", request_id)
|
||||
|
||||
|
||||
def build_image_name(*args):
|
||||
"""
|
||||
{requestId}/{time_now}_frame-{current_frame}-{last_frame}_type_{random_num}-{mode_type}" \
|
||||
"-{modeCode}-{target}_{image_type}.jpg
|
||||
"""
|
||||
current_frame, last_frame, mode_type, image_type, modeCode, target, request_id = args
|
||||
random_num = TimeUtils.now_date_to_str(TimeUtils.YMDHMSF)
|
||||
time_now = TimeUtils.now_date_to_str("%Y-%m-%d-%H-%M-%S")
|
||||
return "%s/%s_frame-%s-%s_type_%s-%s-%s-%s_%s.jpg" % (request_id, time_now, current_frame, last_frame,
|
||||
random_num, mode_type, modeCode, target, image_type)
|
||||
|
||||
|
||||
# 如果任务是图像处理,则用此类
|
||||
class ImageTypeImageFileUpload(Thread):
|
||||
__slots__ = ('_fb_queue', '_context', '_image_queue', '_analyse_type', '_msg')
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
self._fb_queue, self._context, self._msg, self._image_queue, self._analyse_type = args
|
||||
self._storage_source = self._context['service']['storage_source']
|
||||
|
||||
@staticmethod
|
||||
def handle_image(det_xywh, copy_frame, font_config):
|
||||
"""
|
||||
det_xywh:{
|
||||
'code':{
|
||||
1: [[detect_targets_code, box, score, label_array, color]]
|
||||
}
|
||||
}
|
||||
模型编号:modeCode
|
||||
检测目标:detectTargetCode
|
||||
"""
|
||||
model_info = []
|
||||
# 更加模型编码解析数据
|
||||
for code, det_info in det_xywh.items():
|
||||
if det_info is not None and len(det_info) > 0:
|
||||
for cls, target_list in det_info.items():
|
||||
if target_list is not None and len(target_list) > 0:
|
||||
aiFrame = copy_frame.copy()
|
||||
for target in target_list:
|
||||
# 自研车牌模型判断
|
||||
if ModelType.CITY_CARPLATE_MODEL.value[1] == str(code):
|
||||
draw_name_ocr(target, aiFrame, font_config[cls])
|
||||
elif ModelType.CITY_DENSECROWDCOUNT_MODEL.value[1] == str(code) or \
|
||||
ModelType.CITY_UNDERBUILDCOUNT_MODEL.value[1] == str(code):
|
||||
draw_name_crowd(target, aiFrame, font_config[cls])
|
||||
else:
|
||||
draw_painting_joint(target[1], aiFrame, target[3], target[2], target[4], font_config)
|
||||
|
||||
model_info.append({
|
||||
"modelCode": str(code),
|
||||
"detectTargetCode": str(cls),
|
||||
"frame": aiFrame
|
||||
})
|
||||
|
||||
if len(model_info) > 0:
|
||||
image_result = {
|
||||
"or_frame": copy_frame,
|
||||
"model_info": model_info,
|
||||
"current_frame": 0,
|
||||
"last_frame": 0
|
||||
}
|
||||
return image_result
|
||||
return None
|
||||
|
||||
def run(self):
|
||||
context, msg = self._context, self._msg
|
||||
base_dir, env, request_id = context["base_dir"], context["env"], msg["request_id"]
|
||||
logger.info("启动图片识别图片上传线程, requestId: {}", request_id)
|
||||
image_queue, fb_queue, analyse_type = self._image_queue, self._fb_queue, self._analyse_type
|
||||
service_timeout = int(context["service"]["timeout"])
|
||||
with ThreadPoolExecutor(max_workers=2) as t:
|
||||
try:
|
||||
# 初始化oss客户端
|
||||
if self._storage_source == 1:
|
||||
minioSdk = MinioSdk(base_dir, env, request_id)
|
||||
else:
|
||||
aliyunOssSdk = AliyunOssSdk(base_dir, env, request_id)
|
||||
|
||||
start_time = time()
|
||||
while True:
|
||||
try:
|
||||
if time() - start_time > service_timeout:
|
||||
logger.error("图片上传进程运行超时, requestId: {}", request_id)
|
||||
break
|
||||
# 获取队列中的消息
|
||||
image_msg = image_queue.get()
|
||||
if image_msg is not None:
|
||||
if image_msg[0] == 2:
|
||||
if 'stop' == image_msg[1]:
|
||||
logger.info("开始停止图片上传线程, requestId:{}", request_id)
|
||||
break
|
||||
if image_msg[0] == 1:
|
||||
task, msg_list = [], []
|
||||
det_xywh, image_url, copy_frame, font_config, result = image_msg[1]
|
||||
remote_names = []
|
||||
if det_xywh is None:
|
||||
ai_image_name = build_image_name(0, 0, analyse_type, "AI", result.get("modelCode"),
|
||||
result.get("type"), request_id)
|
||||
|
||||
if self._storage_source == 1:
|
||||
ai_future = t.submit(minioSdk.put_object, copy_frame, ai_image_name)
|
||||
else:
|
||||
ai_future = t.submit(aliyunOssSdk.put_object, ai_image_name, copy_frame)
|
||||
|
||||
task.append(ai_future)
|
||||
remote_names.append(ai_image_name)
|
||||
# msg_list.append(message_feedback(request_id,
|
||||
# AnalysisStatus.RUNNING.value,
|
||||
# analyse_type, "", "", "",
|
||||
# image_url,
|
||||
# ai_image_name,
|
||||
# result.get("modelCode"),
|
||||
# result.get("type"),
|
||||
# analyse_results=result))
|
||||
else:
|
||||
image_result = self.handle_image(det_xywh, copy_frame, font_config)
|
||||
if image_result:
|
||||
|
||||
# 图片帧数编码
|
||||
if image_url is None:
|
||||
or_result, or_image = cv2.imencode(".jpg", image_result.get("or_frame"))
|
||||
image_url_0 = build_image_name(image_result.get("current_frame"),
|
||||
image_result.get("last_frame"),
|
||||
analyse_type,
|
||||
"OR", "0", "O", request_id)
|
||||
|
||||
if self._storage_source == 1:
|
||||
or_future = t.submit(minioSdk.put_object, or_image, image_url_0)
|
||||
else:
|
||||
or_future = t.submit(aliyunOssSdk.put_object, image_url_0,
|
||||
or_image.tobytes())
|
||||
task.append(or_future)
|
||||
remote_names.append(image_url_0)
|
||||
model_info_list = image_result.get("model_info")
|
||||
for model_info in model_info_list:
|
||||
ai_result, ai_image = cv2.imencode(".jpg", model_info.get("frame"))
|
||||
ai_image_name = build_image_name(image_result.get("current_frame"),
|
||||
image_result.get("last_frame"),
|
||||
analyse_type,
|
||||
"AI",
|
||||
model_info.get("modelCode"),
|
||||
model_info.get("detectTargetCode"),
|
||||
request_id)
|
||||
if self._storage_source == 1:
|
||||
ai_future = t.submit(minioSdk.put_object, ai_image, ai_image_name)
|
||||
else:
|
||||
ai_future = t.submit(aliyunOssSdk.put_object, ai_image_name,
|
||||
ai_image.tobytes())
|
||||
task.append(ai_future)
|
||||
remote_names.append(ai_image_name)
|
||||
# msg_list.append(message_feedback(request_id,
|
||||
# AnalysisStatus.RUNNING.value,
|
||||
# analyse_type, "", "", "",
|
||||
# image_url,
|
||||
# ai_image_name,
|
||||
# model_info.get('modelCode'),
|
||||
# model_info.get('detectTargetCode'),
|
||||
# analyse_results=result))
|
||||
remote_url_list = []
|
||||
for thread_result in task:
|
||||
remote_url_list.append(thread_result.result())
|
||||
|
||||
# 以下代码是为了获取图像上传后,返回的全路径地址
|
||||
if det_xywh is None:
|
||||
msg_list.append(message_feedback(request_id,
|
||||
AnalysisStatus.RUNNING.value,
|
||||
analyse_type, "", "", "",
|
||||
image_url,
|
||||
remote_url_list[0],
|
||||
result.get("modelCode"),
|
||||
result.get("type"),
|
||||
analyse_results=result))
|
||||
else:
|
||||
if image_result:
|
||||
if image_url is None:
|
||||
for ii in range(len(remote_names) - 1):
|
||||
msg_list.append(message_feedback(request_id,
|
||||
AnalysisStatus.RUNNING.value,
|
||||
analyse_type, "", "", "",
|
||||
remote_url_list[0],
|
||||
remote_url_list[1 + ii],
|
||||
model_info.get('modelCode'),
|
||||
model_info.get('detectTargetCode'),
|
||||
analyse_results=result))
|
||||
else:
|
||||
for ii in range(len(remote_names)):
|
||||
msg_list.append(message_feedback(request_id,
|
||||
AnalysisStatus.RUNNING.value,
|
||||
analyse_type, "", "", "",
|
||||
image_url,
|
||||
remote_url_list[ii],
|
||||
model_info_list[ii].get('modelCode'),
|
||||
model_info_list[ii].get(
|
||||
'detectTargetCode'),
|
||||
analyse_results=result))
|
||||
|
||||
for msg in msg_list:
|
||||
put_queue(fb_queue, msg, timeout=2, is_ex=False)
|
||||
else:
|
||||
sleep(1)
|
||||
except Exception as e:
|
||||
logger.error("图片上传异常:{}, requestId:{}", format_exc(), request_id)
|
||||
finally:
|
||||
clear_queue(image_queue)
|
||||
logger.info("停止图片识别图片上传线程, requestId:{}", request_id)
|
||||
|
|
@ -0,0 +1,315 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from threading import Thread
|
||||
from time import sleep, time
|
||||
from traceback import format_exc
|
||||
|
||||
from loguru import logger
|
||||
import cv2
|
||||
|
||||
from entity.FeedBack import message_feedback
|
||||
from enums.ExceptionEnum import ExceptionType
|
||||
from exception.CustomerException import ServiceException
|
||||
from util.AliyunSdk import AliyunOssSdk
|
||||
from util.MinioSdk import MinioSdk
|
||||
from util import TimeUtils
|
||||
from enums.AnalysisStatusEnum import AnalysisStatus
|
||||
from util.PlotsUtils import draw_painting_joint
|
||||
from util.QueUtil import put_queue, get_no_block_queue, clear_queue
|
||||
import io
|
||||
|
||||
class FileUpload(Thread):
|
||||
__slots__ = ('_fb_queue', '_context', '_image_queue', '_analyse_type', '_msg')
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
self._fb_queue, self._context, self._msg, self._image_queue, self._analyse_type = args
|
||||
self._storage_source = self._context['service']['storage_source']
|
||||
|
||||
class ImageFileUpload(FileUpload):
|
||||
__slots__ = ()
|
||||
|
||||
@staticmethod
|
||||
def handle_image(frame_msg, frame_step):
|
||||
# (high_score_image["code"], all_frames, draw_config["font_config"])
|
||||
# high_score_image["code"][code][cls] = (frame, frame_index_list[i], cls_list)
|
||||
det_xywh, frame, current_frame, all_frames, font_config = frame_msg
|
||||
'''
|
||||
det_xywh:{
|
||||
'code':{
|
||||
1: [[detect_targets_code, box, score, label_array, color]]
|
||||
}
|
||||
}
|
||||
模型编号:modeCode
|
||||
检测目标:detectTargetCode
|
||||
'''
|
||||
model_info = []
|
||||
# 更加模型编码解析数据
|
||||
for code, det_list in det_xywh.items():
|
||||
if len(det_list) > 0:
|
||||
for cls, target_list in det_list.items():
|
||||
if len(target_list) > 0:
|
||||
aFrame = frame.copy()
|
||||
for target in target_list:
|
||||
draw_painting_joint(target[1], aFrame, target[3], target[2], target[4], font_config, target[5])
|
||||
model_info.append({"modelCode": str(code), "detectTargetCode": str(cls), "aFrame": aFrame})
|
||||
if len(model_info) > 0:
|
||||
image_result = {
|
||||
"or_frame": frame,
|
||||
"model_info": model_info,
|
||||
"current_frame": current_frame,
|
||||
"last_frame": current_frame + frame_step
|
||||
}
|
||||
return image_result
|
||||
return None
|
||||
|
||||
def run(self):
|
||||
msg, context = self._msg, self._context
|
||||
service = context["service"]
|
||||
base_dir, env, request_id = context["base_dir"], context["env"], msg["request_id"]
|
||||
logger.info("启动图片上传线程, requestId: {}", request_id)
|
||||
image_queue, fb_queue, analyse_type = self._image_queue, self._fb_queue, self._analyse_type
|
||||
service_timeout = int(service["timeout"])
|
||||
frame_step = int(service["filter"]["frame_step"]) + 120
|
||||
try:
|
||||
with ThreadPoolExecutor(max_workers=2) as t:
|
||||
# 初始化oss客户端
|
||||
if self._storage_source==1:
|
||||
minioSdk = MinioSdk(base_dir, env, request_id )
|
||||
else:
|
||||
aliyunOssSdk = AliyunOssSdk(base_dir, env, request_id)
|
||||
start_time = time()
|
||||
while True:
|
||||
try:
|
||||
if time() - start_time > service_timeout:
|
||||
logger.error("图片上传线程运行超时, requestId: {}", request_id)
|
||||
break
|
||||
raise ServiceException(ExceptionType.TASK_EXCUTE_TIMEOUT.value[0],
|
||||
ExceptionType.TASK_EXCUTE_TIMEOUT.value[1])
|
||||
# 获取队列中的消息
|
||||
image_msg = get_no_block_queue(image_queue)
|
||||
if image_msg is not None:
|
||||
if image_msg[0] == 2:
|
||||
if 'stop' == image_msg[1]:
|
||||
logger.info("开始停止图片上传线程, requestId:{}", request_id)
|
||||
break
|
||||
if image_msg[0] == 1:
|
||||
image_result = self.handle_image(image_msg[1], frame_step)
|
||||
if image_result is not None:
|
||||
task = []
|
||||
or_image = cv2.imencode(".jpg", image_result["or_frame"])[1]
|
||||
or_image_name = build_image_name(image_result["current_frame"],
|
||||
image_result["last_frame"],
|
||||
analyse_type,
|
||||
"OR", "0", "0", request_id)
|
||||
if self._storage_source==1:
|
||||
or_future = t.submit(minioSdk.put_object, or_image,or_image_name)
|
||||
else:
|
||||
or_future = t.submit(aliyunOssSdk.put_object, or_image_name, or_image.tobytes())
|
||||
task.append(or_future)
|
||||
model_info_list = image_result["model_info"]
|
||||
msg_list = []
|
||||
for model_info in model_info_list:
|
||||
ai_image = cv2.imencode(".jpg", model_info["aFrame"])[1]
|
||||
ai_image_name = build_image_name(image_result["current_frame"],
|
||||
image_result["last_frame"],
|
||||
analyse_type,
|
||||
"AI",
|
||||
model_info["modelCode"],
|
||||
model_info["detectTargetCode"],
|
||||
request_id)
|
||||
if self._storage_source==1:
|
||||
ai_future = t.submit(minioSdk.put_object, ai_image,
|
||||
ai_image_name)
|
||||
else:
|
||||
ai_future = t.submit(aliyunOssSdk.put_object, ai_image_name,
|
||||
ai_image.tobytes())
|
||||
|
||||
task.append(ai_future)
|
||||
#msg_list.append(message_feedback(request_id,
|
||||
# AnalysisStatus.RUNNING.value,
|
||||
# analyse_type, "", "", "",
|
||||
# or_image_name,
|
||||
# ai_image_name,
|
||||
# model_info['modelCode'],
|
||||
# model_info['detectTargetCode']))
|
||||
remote_image_list=[]
|
||||
for tk in task:
|
||||
remote_image_list.append( tk.result())
|
||||
for ii,model_info in enumerate(model_info_list):
|
||||
msg_list.append( message_feedback(request_id,
|
||||
AnalysisStatus.RUNNING.value,
|
||||
analyse_type, "", "", "",
|
||||
remote_image_list[0],
|
||||
remote_image_list[ii+1],
|
||||
model_info['modelCode'],
|
||||
model_info['detectTargetCode']) )
|
||||
|
||||
for msg in msg_list:
|
||||
put_queue(fb_queue, msg, timeout=2, is_ex=False)
|
||||
del task, msg_list
|
||||
else:
|
||||
sleep(1)
|
||||
del image_msg
|
||||
except Exception:
|
||||
logger.error("图片上传异常:{}, requestId:{}", format_exc(), request_id)
|
||||
finally:
|
||||
logger.info("停止图片上传线程0, requestId:{}", request_id)
|
||||
clear_queue(image_queue)
|
||||
logger.info("停止图片上传线程1, requestId:{}", request_id)
|
||||
|
||||
|
||||
def build_image_name(*args):
|
||||
"""
|
||||
{requestId}/{time_now}_frame-{current_frame}-{last_frame}_type_{random_num}-{mode_type}" \
|
||||
"-{modeCode}-{target}_{image_type}.jpg
|
||||
"""
|
||||
current_frame, last_frame, mode_type, image_type, modeCode, target, request_id = args
|
||||
random_num = TimeUtils.now_date_to_str(TimeUtils.YMDHMSF)
|
||||
time_now = TimeUtils.now_date_to_str("%Y-%m-%d-%H-%M-%S")
|
||||
return "%s/%s_frame-%s-%s_type_%s-%s-%s-%s_%s.jpg" % (request_id, time_now, current_frame, last_frame,
|
||||
random_num, mode_type, modeCode, target, image_type)
|
||||
|
||||
|
||||
class ImageTypeImageFileUpload(Thread):
|
||||
__slots__ = ('_fb_queue', '_context', '_image_queue', '_analyse_type', '_msg')
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
self._fb_queue, self._context, self._msg, self._image_queue, self._analyse_type = args
|
||||
self._storage_source = self._context['service']['storage_source']
|
||||
@staticmethod
|
||||
def handle_image(det_xywh, copy_frame, font_config):
|
||||
"""
|
||||
det_xywh:{
|
||||
'code':{
|
||||
1: [[detect_targets_code, box, score, label_array, color]]
|
||||
}
|
||||
}
|
||||
模型编号:modeCode
|
||||
检测目标:detectTargetCode
|
||||
"""
|
||||
model_info = []
|
||||
# 更加模型编码解析数据
|
||||
for code, det_info in det_xywh.items():
|
||||
if det_info is not None and len(det_info) > 0:
|
||||
for cls, target_list in det_info.items():
|
||||
if target_list is not None and len(target_list) > 0:
|
||||
aiFrame = copy_frame.copy()
|
||||
for target in target_list:
|
||||
draw_painting_joint(target[1], aiFrame, target[3], target[2], target[4], font_config)
|
||||
model_info.append({
|
||||
"modelCode": str(code),
|
||||
"detectTargetCode": str(cls),
|
||||
"frame": aiFrame
|
||||
})
|
||||
if len(model_info) > 0:
|
||||
image_result = {
|
||||
"or_frame": copy_frame,
|
||||
"model_info": model_info,
|
||||
"current_frame": 0,
|
||||
"last_frame": 0
|
||||
}
|
||||
return image_result
|
||||
return None
|
||||
|
||||
def run(self):
|
||||
context, msg = self._context, self._msg
|
||||
base_dir, env, request_id = context["base_dir"], context["env"], msg["request_id"]
|
||||
logger.info("启动图片识别图片上传线程, requestId: {}", request_id)
|
||||
image_queue, fb_queue, analyse_type = self._image_queue, self._fb_queue, self._analyse_type
|
||||
service_timeout = int(context["service"]["timeout"])
|
||||
with ThreadPoolExecutor(max_workers=2) as t:
|
||||
try:
|
||||
# 初始化oss客户端
|
||||
if self._storage_source==1:
|
||||
minioSdk = MinioSdk(base_dir, env, request_id )
|
||||
else:
|
||||
aliyunOssSdk = AliyunOssSdk(base_dir, env, request_id)
|
||||
|
||||
start_time = time()
|
||||
while True:
|
||||
try:
|
||||
if time() - start_time > service_timeout:
|
||||
logger.error("图片上传进程运行超时, requestId: {}", request_id)
|
||||
break
|
||||
# 获取队列中的消息
|
||||
image_msg = image_queue.get()
|
||||
if image_msg is not None:
|
||||
if image_msg[0] == 2:
|
||||
if 'stop' == image_msg[1]:
|
||||
logger.info("开始停止图片上传线程, requestId:{}", request_id)
|
||||
break
|
||||
if image_msg[0] == 1:
|
||||
task, msg_list = [], []
|
||||
det_xywh, image_url, copy_frame, font_config, result = image_msg[1]
|
||||
if det_xywh is None:
|
||||
ai_image_name = build_image_name(0, 0, analyse_type, "AI", result.get("modelCode"),
|
||||
result.get("type"), request_id)
|
||||
|
||||
if self._storage_source==1:
|
||||
ai_future = t.submit(minioSdk.put_object, copy_frame,ai_image_name)
|
||||
else:
|
||||
ai_future = t.submit(aliyunOssSdk.put_object, ai_image_name, copy_frame)
|
||||
|
||||
task.append(ai_future)
|
||||
msg_list.append(message_feedback(request_id,
|
||||
AnalysisStatus.RUNNING.value,
|
||||
analyse_type, "", "", "",
|
||||
image_url,
|
||||
ai_image_name,
|
||||
result.get("modelCode"),
|
||||
result.get("type"),
|
||||
analyse_results=result))
|
||||
else:
|
||||
image_result = self.handle_image(det_xywh, copy_frame, font_config)
|
||||
if image_result:
|
||||
# 图片帧数编码
|
||||
if image_url is None:
|
||||
or_result, or_image = cv2.imencode(".jpg", image_result.get("or_frame"))
|
||||
image_url = build_image_name(image_result.get("current_frame"),
|
||||
image_result.get("last_frame"),
|
||||
analyse_type,
|
||||
"OR", "0", "O", request_id)
|
||||
|
||||
if self._storage_source==1:
|
||||
or_future = t.submit(minioSdk.put_object, or_image,image_url)
|
||||
else:
|
||||
or_future = t.submit(aliyunOssSdk.put_object, image_url,
|
||||
or_image.tobytes())
|
||||
task.append(or_future)
|
||||
model_info_list = image_result.get("model_info")
|
||||
for model_info in model_info_list:
|
||||
ai_result, ai_image = cv2.imencode(".jpg", model_info.get("frame"))
|
||||
ai_image_name = build_image_name(image_result.get("current_frame"),
|
||||
image_result.get("last_frame"),
|
||||
analyse_type,
|
||||
"AI",
|
||||
model_info.get("modelCode"),
|
||||
model_info.get("detectTargetCode"),
|
||||
request_id)
|
||||
if self._storage_source==1:
|
||||
ai_future = t.submit(minioSdk.put_object, ai_image, ai_image_name)
|
||||
else:
|
||||
ai_future = t.submit(aliyunOssSdk.put_object, ai_image_name,
|
||||
ai_image.tobytes())
|
||||
task.append(ai_future)
|
||||
msg_list.append(message_feedback(request_id,
|
||||
AnalysisStatus.RUNNING.value,
|
||||
analyse_type, "", "", "",
|
||||
image_url,
|
||||
ai_image_name,
|
||||
model_info.get('modelCode'),
|
||||
model_info.get('detectTargetCode'),
|
||||
analyse_results=result))
|
||||
for thread_result in task:
|
||||
thread_result.result()
|
||||
for msg in msg_list:
|
||||
put_queue(fb_queue, msg, timeout=2, is_ex=False)
|
||||
else:
|
||||
sleep(1)
|
||||
except Exception as e:
|
||||
logger.error("图片上传异常:{}, requestId:{}", format_exc(), request_id)
|
||||
finally:
|
||||
clear_queue(image_queue)
|
||||
logger.info("停止图片识别图片上传线程, requestId:{}", request_id)
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from threading import Thread
|
||||
from time import sleep, time
|
||||
from traceback import format_exc
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from common.Constant import init_progess
|
||||
from enums.AnalysisStatusEnum import AnalysisStatus
|
||||
from entity.FeedBack import message_feedback
|
||||
from enums.ExceptionEnum import ExceptionType
|
||||
from exception.CustomerException import ServiceException
|
||||
from util.QueUtil import get_no_block_queue, put_queue, clear_queue
|
||||
|
||||
|
||||
class Heartbeat(Thread):
|
||||
__slots__ = ('__fb_queue', '__hb_queue', '__request_id', '__analyse_type', "_context")
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
self.__fb_queue, self.__hb_queue, self.__request_id, self.__analyse_type, self._context = args
|
||||
|
||||
def run(self):
|
||||
request_id, hb_queue, progress = self.__request_id, self.__hb_queue, init_progess
|
||||
analyse_type, fb_queue = self.__analyse_type, self.__fb_queue
|
||||
service_timeout = int(self._context["service"]["timeout"]) + 120
|
||||
try:
|
||||
logger.info("开始启动心跳线程!requestId:{}", request_id)
|
||||
start_time = time()
|
||||
hb_init_num = 0
|
||||
while True:
|
||||
if time() - start_time > service_timeout:
|
||||
logger.error("心跳运行超时, requestId: {}", request_id)
|
||||
raise ServiceException(ExceptionType.TASK_EXCUTE_TIMEOUT.value[0],
|
||||
ExceptionType.TASK_EXCUTE_TIMEOUT.value[1])
|
||||
sleep(3)
|
||||
hb_msg = get_no_block_queue(hb_queue)
|
||||
if hb_msg is not None:
|
||||
command = hb_msg.get("command")
|
||||
hb_value = hb_msg.get("hb_value")
|
||||
if 'stop' == command:
|
||||
logger.info("开始终止心跳线程, requestId:{}", request_id)
|
||||
break
|
||||
if hb_value is not None:
|
||||
progress = hb_value
|
||||
if hb_init_num % 30 == 0:
|
||||
hb_init_num = 0
|
||||
put_queue(fb_queue, message_feedback(request_id, AnalysisStatus.RUNNING.value, analyse_type,
|
||||
progress=progress), timeout=3, is_ex=True)
|
||||
|
||||
hb_init_num += 3
|
||||
del hb_msg
|
||||
except Exception:
|
||||
logger.error("心跳线程异常:{}, requestId:{}", format_exc(), request_id)
|
||||
finally:
|
||||
clear_queue(hb_queue)
|
||||
logger.info("心跳线程停止完成!requestId:{}", request_id)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,153 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import time
|
||||
from traceback import format_exc
|
||||
|
||||
from multiprocessing import Process, Queue
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from concurrency.Pull2PushStreamThread import PushSteamThread
|
||||
from enums.StatusEnum import PushStreamStatus, ExecuteStatus
|
||||
from util.LogUtils import init_log
|
||||
|
||||
from enums.ExceptionEnum import ExceptionType
|
||||
from entity.FeedBack import pull_stream_feedback
|
||||
from exception.CustomerException import ServiceException
|
||||
from util.QueUtil import get_no_block_queue, put_queue
|
||||
|
||||
|
||||
class PushStreamProcess(Process):
|
||||
__slots__ = ('_fb_queue', 'event_queue', '_context', '_msg', '_analysisType')
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
self._fb_queue, self._context, self._msg, self._analysisType = args
|
||||
self.event_queue = Queue()
|
||||
|
||||
def sendEvent(self, eBody):
|
||||
try:
|
||||
self.event_queue.put(eBody, timeout=2)
|
||||
except Exception:
|
||||
logger.error("添加事件到队列超时异常:{}, requestId:{}", format_exc(), self._msg["request_id"])
|
||||
raise ServiceException(ExceptionType.SERVICE_INNER_EXCEPTION.value[0],
|
||||
ExceptionType.SERVICE_INNER_EXCEPTION.value[1])
|
||||
|
||||
def run(self):
|
||||
msg, context = self._msg, self._context
|
||||
requestId, videoUrls = msg["request_id"], msg["video_urls"]
|
||||
base_dir, env = context['base_dir'], context['env']
|
||||
fb_queue = self._fb_queue
|
||||
task, videoStatus = {}, {}
|
||||
ex = None
|
||||
try:
|
||||
init_log(base_dir, env)
|
||||
if videoUrls is None or len(videoUrls) == 0:
|
||||
raise ServiceException(ExceptionType.PUSH_STREAM_URL_IS_NULL.value[0],
|
||||
ExceptionType.PUSH_STREAM_URL_IS_NULL.value[1])
|
||||
if len(videoUrls) > 5:
|
||||
logger.error("推流数量超过限制, 当前推流数量: {}, requestId:{}", len(videoUrls), requestId)
|
||||
raise ServiceException(ExceptionType.PULL_STREAM_NUM_LIMIT_EXCEPTION.value[0],
|
||||
ExceptionType.PULL_STREAM_NUM_LIMIT_EXCEPTION.value[1])
|
||||
videoInfo = [{"id": url["id"], "status": PushStreamStatus.WAITING.value[0]} for url in videoUrls if
|
||||
url.get("id")]
|
||||
put_queue(fb_queue, pull_stream_feedback(requestId, ExecuteStatus.WAITING.value[0], "", "", videoInfo))
|
||||
for videoUrl in videoUrls:
|
||||
pushThread = PushSteamThread(videoUrl["pull_url"], videoUrl["push_url"], requestId, videoUrl["id"])
|
||||
pushThread.start()
|
||||
task[videoUrl["id"]] = pushThread
|
||||
enable_time = time.time()
|
||||
for video in videoInfo:
|
||||
videoStatus[video.get("id")] = video.get("status")
|
||||
count = 0
|
||||
while True:
|
||||
# 整个推流任务超时时间
|
||||
if time.time() - enable_time > 43200:
|
||||
logger.error("任务执行超时, requestId:{}", requestId)
|
||||
for t in list(task.keys()):
|
||||
if task[t].is_alive():
|
||||
task[t].status = False
|
||||
task[t].pushStreamUtil.close_push_stream_sp()
|
||||
task[t].join(120)
|
||||
videoStatus[t] = PushStreamStatus.TIMEOUT.value[0]
|
||||
videoInfo_timeout = [{"id": k, "status": v} for k, v in videoStatus.items()]
|
||||
put_queue(fb_queue, pull_stream_feedback(requestId, ExecuteStatus.TIMEOUT.value[0],
|
||||
ExceptionType.TASK_EXCUTE_TIMEOUT.value[0],
|
||||
ExceptionType.TASK_EXCUTE_TIMEOUT.value[1],
|
||||
videoInfo_timeout))
|
||||
break
|
||||
# 接受停止指令
|
||||
event_result = get_no_block_queue(self.event_queue)
|
||||
if event_result is not None:
|
||||
command = event_result.get("command")
|
||||
videoIds = event_result.get("videoIds")
|
||||
if "stop" == command:
|
||||
# 如果videoIds是空停止所有任务
|
||||
if videoIds is None or len(videoIds) == 0:
|
||||
logger.info("停止所有执行的推流任务, requestId:{}", requestId)
|
||||
for t in list(task.keys()):
|
||||
if task[t].is_alive():
|
||||
task[t].status = False
|
||||
task[t].pushStreamUtil.close_push_stream_sp()
|
||||
task[t].join(120)
|
||||
videoStatus[t] = PushStreamStatus.SUCCESS.value[0]
|
||||
videoInfo_sucess = [{"id": k, "status": v} for k, v in videoStatus.items()]
|
||||
put_queue(fb_queue, pull_stream_feedback(requestId, ExecuteStatus.SUCCESS.value[0], "", "",
|
||||
videoInfo_sucess))
|
||||
break
|
||||
else:
|
||||
logger.info("停止指定的推流任务, requestId:{}", requestId)
|
||||
alive_thread = 0
|
||||
for t in list(task.keys()):
|
||||
if task[t].is_alive():
|
||||
if t in videoIds:
|
||||
task[t].status = False
|
||||
task[t].pushStreamUtil.close_push_stream_sp()
|
||||
task[t].join(120)
|
||||
videoStatus[t] = PushStreamStatus.SUCCESS.value[0]
|
||||
else:
|
||||
alive_thread += 1
|
||||
if alive_thread == 0:
|
||||
videoInfo_sucess = [{"id": k, "status": v} for k, v in videoStatus.items()]
|
||||
put_queue(fb_queue, pull_stream_feedback(requestId, ExecuteStatus.SUCCESS.value[0], "",
|
||||
"", videoInfo_sucess))
|
||||
break
|
||||
for t in list(task.keys()):
|
||||
if task[t].status and not task[t].is_alive():
|
||||
videoStatus[t] = PushStreamStatus.FAILED.value[0]
|
||||
logger.error("检测到推流线程异常停止!videoId:{}, requestId:{}", t, requestId)
|
||||
if task[t].ex:
|
||||
raise task[t].ex
|
||||
raise Exception("检测到推流线程异常停止!")
|
||||
if task[t].is_alive():
|
||||
videoStatus[t] = task[t].excute_status
|
||||
if count % 10 == 0:
|
||||
videoInfo_hb = [{"id": k, "status": v} for k, v in videoStatus.items()]
|
||||
put_queue(fb_queue, pull_stream_feedback(requestId, ExecuteStatus.RUNNING.value[0], "", "",
|
||||
videoInfo_hb))
|
||||
count = 0
|
||||
count += 1
|
||||
time.sleep(1)
|
||||
except ServiceException as s:
|
||||
ex = s.code, s.msg
|
||||
logger.error("服务异常,异常编号:{}, 异常描述:{}, requestId: {}", s.code, s.msg, requestId)
|
||||
except Exception:
|
||||
ex = ExceptionType.SERVICE_INNER_EXCEPTION.value[0], ExceptionType.SERVICE_INNER_EXCEPTION.value[1]
|
||||
logger.error("服务异常: {}, requestId: {},", format_exc(), requestId)
|
||||
finally:
|
||||
if ex:
|
||||
errorCode, errorMsg = ex
|
||||
for t in list(task.keys()):
|
||||
if task[t].is_alive():
|
||||
task[t].status = False
|
||||
task[t].pushStreamUtil.close_push_stream_sp()
|
||||
task[t].join(120)
|
||||
videoStatus[t] = PushStreamStatus.FAILED.value[0]
|
||||
videoInfo_ex = [{"id": k, "status": v} for k, v in videoStatus.items()]
|
||||
put_queue(fb_queue, pull_stream_feedback(requestId, ExecuteStatus.FAILED.value[0], errorCode, errorMsg,
|
||||
videoInfo_ex))
|
||||
for t in list(task.keys()):
|
||||
if task[t].is_alive():
|
||||
task[t].status = False
|
||||
task[t].pushStreamUtil.close_push_stream_sp()
|
||||
task[t].join(120)
|
||||
logger.info("推流任务完成, requestId: {}", requestId)
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from threading import Thread
|
||||
import time
|
||||
from traceback import format_exc
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from enums.StatusEnum import PushStreamStatus
|
||||
from exception.CustomerException import ServiceException
|
||||
from util.PushStreamUtils import PushStreamUtil
|
||||
|
||||
|
||||
class PushSteamThread(Thread):
|
||||
__slots__ = ("pushStreamUtil", "requestId", "videoId", "status", "ex")
|
||||
|
||||
def __init__(self, pullUrl, pushUrl, requestId, videoId):
|
||||
super().__init__()
|
||||
self.pushStreamUtil = PushStreamUtil(pullUrl, pushUrl, requestId)
|
||||
self.requestId = requestId
|
||||
self.videoId = videoId
|
||||
self.status = True
|
||||
self.excute_status = PushStreamStatus.WAITING.value[0]
|
||||
self.ex = None
|
||||
|
||||
def run(self):
|
||||
logger.info("开始启动推流线程, 视频id: {}, requestId:{}", self.videoId, self.requestId)
|
||||
while True:
|
||||
try:
|
||||
self.pushStreamUtil.start_push_stream()
|
||||
self.excute_status = PushStreamStatus.RUNNING.value[0]
|
||||
out, err = self.pushStreamUtil.push_stream_sp.communicate()
|
||||
# 异常断流
|
||||
if self.status:
|
||||
logger.warning("推流异常,请检测拉流地址和推流地址是否正常!")
|
||||
if self.pushStreamUtil.push_stream_sp.returncode != 0:
|
||||
logger.error("推流异常:{}, 视频id: {}, requestId:{}", err.decode(), self.videoId,
|
||||
self.requestId)
|
||||
self.excute_status = PushStreamStatus.RETRYING.value[0]
|
||||
self.pushStreamUtil.close_push_stream_sp()
|
||||
time.sleep(5)
|
||||
# 手动断流
|
||||
if not self.status:
|
||||
self.pushStreamUtil.close_push_stream_sp()
|
||||
break
|
||||
except ServiceException as s:
|
||||
logger.error("异常: {}, 视频id: {}, requestId:{}", s.msg, self.videoId, self.requestId)
|
||||
self.pushStreamUtil.close_push_stream_sp()
|
||||
self.ex = s
|
||||
break
|
||||
except Exception as e:
|
||||
logger.error("异常:{}, 视频id: {}, requestId:{}", format_exc(), self.videoId, self.requestId)
|
||||
self.pushStreamUtil.close_push_stream_sp()
|
||||
self.ex = e
|
||||
break
|
||||
logger.info("结束推流线程, 视频id: {}, requestId:{}", self.videoId, self.requestId)
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from threading import Thread
|
||||
from time import sleep, time
|
||||
from traceback import format_exc
|
||||
|
||||
from loguru import logger
|
||||
from common.YmlConstant import mqtt_yml_path
|
||||
from util.RWUtils import getConfigs
|
||||
from common.Constant import init_progess
|
||||
from enums.AnalysisStatusEnum import AnalysisStatus
|
||||
from entity.FeedBack import message_feedback
|
||||
from enums.ExceptionEnum import ExceptionType
|
||||
from exception.CustomerException import ServiceException
|
||||
from util.QueUtil import get_no_block_queue, put_queue, clear_queue
|
||||
from multiprocessing import Process, Queue
|
||||
import paho.mqtt.client as mqtt
|
||||
import json,os
|
||||
class PullMqtt(Thread):
|
||||
__slots__ = ('__fb_queue', '__mqtt_list', '__request_id', '__analyse_type', "_context")
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
self.__fb_queue, self.__mqtt_list, self.__request_id, self.__analyse_type, self._context = args
|
||||
|
||||
base_dir, env = self._context["base_dir"], self._context["env"]
|
||||
self.__config = getConfigs(os.path.join(base_dir, mqtt_yml_path % env))
|
||||
|
||||
self.__broker = self.__config["broker"]
|
||||
self.__port = self.__config["port"]
|
||||
self.__topic = self.__config["topic"]
|
||||
self.__lengthMqttList = self.__config["length"]
|
||||
|
||||
|
||||
def put_queue(self,__queue,data):
|
||||
if __queue.full():
|
||||
a = __queue.get()
|
||||
__queue.put( data,block=True, timeout=2 )
|
||||
def on_connect(self,client,userdata,flags,rc):
|
||||
client.subscribe(self.__topic)
|
||||
|
||||
|
||||
|
||||
# 当接收到MQTT消息时,回调函数
|
||||
def on_message(self,client, userdata, msg):
|
||||
# 将消息解码为JSON格式
|
||||
payload = msg.payload.decode('utf-8')
|
||||
data = json.loads(payload)
|
||||
#logger.info(str(data))
|
||||
|
||||
|
||||
# 解析位姿信息
|
||||
lon = data.get("lon")
|
||||
lat = data.get("lat")
|
||||
alt = data.get("alt")
|
||||
yaw = data.get("yaw")
|
||||
pitch = data.get("pitch")
|
||||
roll = data.get("roll")
|
||||
|
||||
if len(self.__mqtt_list) == self.__lengthMqttList:
|
||||
self.__mqtt_list.pop(0)
|
||||
self.__mqtt_list.append(data)
|
||||
|
||||
|
||||
# 打印无人机的位姿信息
|
||||
#print(f"Longitude: {lon}, Latitude: {lat}, Altitude: {alt}, sat:{data.get('satcount')} , list length:{len(self.__mqtt_list)}")
|
||||
|
||||
def mqtt_connect(self):
|
||||
# 创建客户端
|
||||
self.client = mqtt.Client()
|
||||
self.client.on_connect = self.on_connect
|
||||
# 设置回调函数
|
||||
self.client.on_message = self.on_message
|
||||
|
||||
# 连接到 Broker
|
||||
self.client.connect(self.__broker, self.__port)
|
||||
|
||||
# 订阅主题
|
||||
self.client.subscribe(self.__topic)
|
||||
# 循环等待并处理网络事件
|
||||
self.client.loop_forever()
|
||||
|
||||
def mqtt_disconnect(self):
|
||||
start_time = time()
|
||||
while True:
|
||||
if time() - start_time > service_timeout:
|
||||
logger.error("MQTT读取超时, requestId: %s,限定时间:%.1s , 已运行:%.1fs"%(request_id,service_timeout, time() - start_time))
|
||||
raise ServiceException(ExceptionType.TASK_EXCUTE_TIMEOUT.value[0],
|
||||
ExceptionType.TASK_EXCUTE_TIMEOUT.value[1])
|
||||
client.loop_stop() # 停止循环
|
||||
client.disconnect() # 断开连接
|
||||
|
||||
def run(self):
|
||||
request_id, mqtt_list, progress = self.__request_id, self.__mqtt_list, init_progess
|
||||
analyse_type, fb_queue = self.__analyse_type, self.__fb_queue
|
||||
#service_timeout = int(self.__config["service"]["timeout"]) + 120
|
||||
|
||||
try:
|
||||
logger.info("开始MQTT读取线程!requestId:{}", request_id)
|
||||
mqtt_init_num = 0
|
||||
self.mqtt_connect()
|
||||
|
||||
except Exception:
|
||||
logger.error("MQTT线程异常:{}, requestId:{}", format_exc(), request_id)
|
||||
finally:
|
||||
mqtt_list = []
|
||||
logger.info("MQTT线程停止完成!requestId:{}", request_id)
|
||||
|
||||
|
||||
def start_PullMqtt(fb_queue, mqtt_list, request_id, analyse_type, context):
|
||||
mqtt_thread = PullMqtt(fb_queue, mqtt_list, request_id, analyse_type, context)
|
||||
mqtt_thread.setDaemon(True)
|
||||
mqtt_thread.start()
|
||||
return mqtt_thread
|
||||
def start_PullVideo(mqtt_list):
|
||||
for i in range(1000):
|
||||
sleep(1)
|
||||
if len(mqtt_list)>=10:
|
||||
print( mqtt_list[4])
|
||||
print(i,len(mqtt_list))
|
||||
if __name__=="__main__":
|
||||
#context = {'service':{'timeout':3600},'mqtt':{
|
||||
# 'broker':"101.133.163.127",'port':1883,'topic':"test/topic","length":10}
|
||||
# }
|
||||
context = {
|
||||
'base_dir':'/home/th/WJ/test/tuoheng_algN',
|
||||
'env':'test'
|
||||
|
||||
}
|
||||
analyse_type = '1'
|
||||
request_id = '123456789'
|
||||
event_queue, pull_queue, mqtt_list, image_queue, push_queue, push_ex_queue = Queue(), Queue(10), [], Queue(), Queue(), Queue()
|
||||
fb_queue = Queue()
|
||||
mqtt_thread = start_PullMqtt(fb_queue, mqtt_list, request_id, analyse_type, context)
|
||||
|
||||
|
||||
start_PullVideo(mqtt_list)
|
||||
print('---line117--')
|
||||
|
||||
|
||||
|
||||
#mqtt_thread.join()
|
||||
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from queue import Queue
|
||||
from threading import Thread
|
||||
from time import time, sleep
|
||||
from traceback import format_exc
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from enums.ExceptionEnum import ExceptionType
|
||||
from enums.RecordingStatusEnum import RecordingStatus
|
||||
from exception.CustomerException import ServiceException
|
||||
from util.Cv2Utils import check_video_stream, clear_pull_p, build_video_info2, pull_read_video_stream2
|
||||
from util.QueUtil import put_queue, get_no_block_queue, clear_queue, put_queue_result
|
||||
|
||||
|
||||
class PullStreamThread(Thread):
|
||||
__slots__ = ('_command', '_pull_queue', '_hb_queue', '_fb_queue', '_msg', '_context')
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
self._msg, self._context, self._pull_queue, self._hb_queue, self._fb_queue, self._frame_num = args
|
||||
self._command = Queue()
|
||||
|
||||
def sendEvent(self, result):
|
||||
put_queue(self._command, result, timeout=10, is_ex=False)
|
||||
|
||||
|
||||
class RecordingPullStreamThread(PullStreamThread):
|
||||
|
||||
def run(self):
|
||||
msg, context, frame_num = self._msg, self._context, self._frame_num
|
||||
request_id, pull_url = msg["request_id"], msg['pull_url']
|
||||
service = context["service"]
|
||||
pull_stream_timeout = int(service["recording_pull_stream_timeout"])
|
||||
read_stream_timeout = int(service["cv2_read_stream_timeout"])
|
||||
service_timeout = int(service["timeout"])
|
||||
command_queue, pull_queue, fb_queue, hb_queue = self._command, self._pull_queue, self._fb_queue, self._hb_queue
|
||||
width, height, width_height_3, all_frames, w, h = None, None, None, 0, None, None
|
||||
read_start_time, pull_p, ex = None, None, None
|
||||
frame_list, frame_index_list = [], []
|
||||
stop_ex = True
|
||||
pull_stream_start_time = time()
|
||||
try:
|
||||
logger.info("录屏拉流线程开始启动, requestId: {}", request_id)
|
||||
cv2_init_num, init_pull_num, concurrent_frame = 0, 1, 1
|
||||
start_time = time()
|
||||
while True:
|
||||
# 检查任务是否超时
|
||||
if time() - start_time > service_timeout:
|
||||
logger.error("录屏拉流超时, requestId: {}", request_id)
|
||||
raise ServiceException(ExceptionType.TASK_EXCUTE_TIMEOUT.value[0],
|
||||
ExceptionType.TASK_EXCUTE_TIMEOUT.value[1])
|
||||
# 最终停止拉流
|
||||
event = get_no_block_queue(command_queue)
|
||||
if event is not None:
|
||||
# 当接收到停止指令,说明不会再处理视频帧了, 直接退出
|
||||
if 'stop' == event.get("command"):
|
||||
if len(frame_list) > 0:
|
||||
put_queue(pull_queue, (4, (frame_list, frame_index_list, all_frames)), timeout=1)
|
||||
logger.info("录屏拉流线程开始停止, requestId: {}", request_id)
|
||||
break
|
||||
# 主进程异常,停止子线程
|
||||
if 'stop_ex' == event.get("command"):
|
||||
logger.info("录屏异常拉开始停止拉流线程, requestId: {}", request_id)
|
||||
stop_ex = False
|
||||
break
|
||||
# 如果是离线拉流
|
||||
if pull_url.startswith('http'):
|
||||
if check_video_stream(width, height):
|
||||
logger.info("开始重新获取视频信息: {}次, requestId: {}", cv2_init_num, request_id)
|
||||
# 当是离线地址重试3次还是拉取不到视频流,关闭拉流管道,返回失败信息
|
||||
# 目前改为等待5分钟
|
||||
# if cv2_init_num > 3:
|
||||
if time() - start_time > 300:
|
||||
logger.info("离线拉流重试失败, 重试次数: {}, requestId: {}", cv2_init_num, request_id)
|
||||
raise ServiceException(ExceptionType.OR_VIDEO_ADDRESS_EXCEPTION.value[0],
|
||||
ExceptionType.OR_VIDEO_ADDRESS_EXCEPTION.value[1])
|
||||
cv2_init_num += 1
|
||||
width, height, width_height_3, all_frames, w, h = build_video_info2(pull_url, request_id)
|
||||
if width is not None:
|
||||
put_queue(hb_queue, {"status": RecordingStatus.RECORDING_RUNNING.value[0]}, timeout=2)
|
||||
else:
|
||||
# if cv2_init_num < 2:
|
||||
if time() - start_time < 300:
|
||||
put_queue(hb_queue, {"status": RecordingStatus.RECORDING_RETRYING.value[0]}, timeout=2)
|
||||
continue
|
||||
# 当离线视频时, 队列满了, 等待1秒后再试
|
||||
if pull_queue.full():
|
||||
logger.info("pull拉流队列满了: {}, requestId: {}", pull_queue.qsize(), request_id)
|
||||
sleep(1)
|
||||
continue
|
||||
# 如果是实时拉流
|
||||
else:
|
||||
if check_video_stream(width, height):
|
||||
logger.info("开始重新获取视频信息: {}次, requestId: {}", cv2_init_num, request_id)
|
||||
pull_stream_init_timeout = time() - pull_stream_start_time
|
||||
if len(frame_list) > 0:
|
||||
put_queue(pull_queue, (4, (frame_list, frame_index_list, all_frames)), timeout=1)
|
||||
frame_list, frame_index_list = [], []
|
||||
if pull_stream_init_timeout > pull_stream_timeout:
|
||||
logger.error("开始拉流超时, 超时时间:{}, requestId:{}", pull_stream_init_timeout, request_id)
|
||||
raise ServiceException(ExceptionType.PULLSTREAM_TIMEOUT_EXCEPTION.value[0],
|
||||
ExceptionType.PULLSTREAM_TIMEOUT_EXCEPTION.value[1])
|
||||
cv2_init_num += 1
|
||||
width, height, width_height_3, all_frames, w, h = build_video_info2(pull_url, request_id)
|
||||
if width is not None:
|
||||
put_queue(hb_queue, {"status": RecordingStatus.RECORDING_RUNNING.value[0]}, timeout=1)
|
||||
else:
|
||||
if cv2_init_num < 3:
|
||||
put_queue(hb_queue, {"status": RecordingStatus.RECORDING_RETRYING.value[0]}, timeout=1)
|
||||
sleep(1)
|
||||
continue
|
||||
pull_stream_start_time = time()
|
||||
cv2_init_num = 1
|
||||
frame, pull_p, width, height = pull_read_video_stream2(pull_p, pull_url, width, height,
|
||||
width_height_3, w, h, request_id)
|
||||
if frame is None:
|
||||
if pull_url.startswith('http'):
|
||||
clear_pull_p(pull_p, request_id)
|
||||
logger.info("总帧数: {}, 当前帧数: {}, requestId: {}", all_frames, concurrent_frame, request_id)
|
||||
if len(frame_list) > 0:
|
||||
put_queue(pull_queue, (4, (frame_list, frame_index_list, all_frames)), timeout=1)
|
||||
if concurrent_frame < all_frames - 100:
|
||||
logger.info("离线拉流异常结束:requestId: {}", request_id)
|
||||
raise ServiceException(ExceptionType.READSTREAM_TIMEOUT_EXCEPTION.value[0],
|
||||
ExceptionType.READSTREAM_TIMEOUT_EXCEPTION.value[1])
|
||||
logger.info("离线拉流线程结束, requestId: {}", request_id)
|
||||
break
|
||||
else:
|
||||
logger.info("获取帧为空, 开始重试: {}次, requestId: {}", init_pull_num, request_id)
|
||||
if len(frame_list) > 0:
|
||||
put_queue(pull_queue, (4, (frame_list, frame_index_list, all_frames)), timeout=1)
|
||||
frame_list, frame_index_list = [], []
|
||||
if read_start_time is None:
|
||||
read_start_time = time()
|
||||
pull_stream_read_timeout = time() - read_start_time
|
||||
if pull_stream_read_timeout > read_stream_timeout:
|
||||
logger.info("拉流过程中断了重试超时, 超时时间: {}, requestId: {}", pull_stream_read_timeout,
|
||||
request_id)
|
||||
raise ServiceException(ExceptionType.READSTREAM_TIMEOUT_EXCEPTION.value[0],
|
||||
ExceptionType.READSTREAM_TIMEOUT_EXCEPTION.value[1])
|
||||
init_pull_num += 1
|
||||
continue
|
||||
init_pull_num = 1
|
||||
read_start_time = None
|
||||
if pull_queue.full():
|
||||
sleep(1)
|
||||
logger.info("pull拉流队列满了:{}, requestId: {}", pull_queue.qsize(), request_id)
|
||||
continue
|
||||
frame_list.append(frame)
|
||||
frame_index_list.append(concurrent_frame)
|
||||
if len(frame_list) >= frame_num:
|
||||
put_queue(pull_queue, (4, (frame_list, frame_index_list, all_frames)), timeout=1)
|
||||
frame_list, frame_index_list = [], []
|
||||
concurrent_frame += 1
|
||||
del frame
|
||||
except ServiceException as s:
|
||||
ex = s.code, s.msg
|
||||
except Exception:
|
||||
logger.exception("实时拉流异常: {}, requestId:{}", format_exc(), request_id)
|
||||
ex = ExceptionType.SERVICE_INNER_EXCEPTION.value[0], ExceptionType.SERVICE_INNER_EXCEPTION.value[1]
|
||||
finally:
|
||||
clear_pull_p(pull_p, request_id)
|
||||
if stop_ex:
|
||||
if ex:
|
||||
error_code, error_msg = ex
|
||||
result = put_queue_result(pull_queue, (1, error_code, error_msg), timeout=3)
|
||||
else:
|
||||
result = put_queue_result(pull_queue, (2,), timeout=3)
|
||||
if result:
|
||||
# 3分钟超时时间
|
||||
cr_time = time()
|
||||
while time() - cr_time < 180:
|
||||
event = get_no_block_queue(command_queue)
|
||||
if event is not None:
|
||||
# 当接收到停止指令,说明不会再处理视频帧了, 直接退出
|
||||
if 'stop' == event.get("command"):
|
||||
logger.info("录屏拉流线程开始停止, requestId: {}", request_id)
|
||||
break
|
||||
sleep(1)
|
||||
clear_queue(command_queue)
|
||||
clear_queue(pull_queue)
|
||||
clear_queue(hb_queue)
|
||||
del frame_list, frame_index_list
|
||||
logger.info("录屏拉流线程结束, requestId: {}", request_id)
|
||||
|
|
@ -0,0 +1,352 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
from multiprocessing import Process, Queue
|
||||
from os import getpid
|
||||
from time import time, sleep
|
||||
from traceback import format_exc
|
||||
|
||||
import psutil
|
||||
from loguru import logger
|
||||
from concurrency.PullMqttThread import PullMqtt
|
||||
from util.LogUtils import init_log
|
||||
from concurrency.FileUploadThread import ImageFileUpload
|
||||
from entity.FeedBack import message_feedback
|
||||
from enums.AnalysisStatusEnum import AnalysisStatus
|
||||
from enums.ExceptionEnum import ExceptionType
|
||||
from exception.CustomerException import ServiceException
|
||||
from util.Cv2Utils import check_video_stream, build_video_info, pull_read_video_stream, clear_pull_p
|
||||
from util.QueUtil import get_no_block_queue, put_queue, clear_queue, put_queue_result
|
||||
|
||||
|
||||
class PullVideoStreamProcess(Process):
|
||||
__slots__ = ("_command_queue", "_msg", "_context", "_fb_queue", "_pull_queue", "_image_queue", "_analyse_type",
|
||||
"_frame_num","_mqtt_list")
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
# 自带参数
|
||||
self._command_queue = Queue()
|
||||
|
||||
# 传参
|
||||
self._msg, self._context, self._fb_queue, self._pull_queue, self._image_queue, self._analyse_type, \
|
||||
self._frame_num = args
|
||||
self._mqtt_list = []
|
||||
def sendCommand(self, result):
|
||||
put_queue(self._command_queue, result, timeout=2, is_ex=True)
|
||||
|
||||
@staticmethod
|
||||
def start_File_upload(fb_queue, context, msg, image_queue, analyse_type,mqtt_list):
|
||||
image_thread = ImageFileUpload(fb_queue, context, msg, image_queue, analyse_type,mqtt_list)
|
||||
image_thread.setDaemon(True)
|
||||
image_thread.start()
|
||||
return image_thread
|
||||
|
||||
@staticmethod
|
||||
def start_PullMqtt(fb_queue, mqtt_list, request_id, analyse_type, context):
|
||||
mqtt_thread = PullMqtt(fb_queue, mqtt_list, request_id, analyse_type, context)
|
||||
mqtt_thread.setDaemon(True)
|
||||
mqtt_thread.start()
|
||||
return mqtt_thread
|
||||
|
||||
|
||||
@staticmethod
|
||||
def check(start_time, service_timeout, request_id, image_thread):
|
||||
if time() - start_time > service_timeout:
|
||||
logger.error("拉流进程运行超时, requestId: {}", request_id)
|
||||
raise ServiceException(ExceptionType.TASK_EXCUTE_TIMEOUT.value[0],
|
||||
ExceptionType.TASK_EXCUTE_TIMEOUT.value[1])
|
||||
# 检测图片上传线程是否正常运行
|
||||
if image_thread and not image_thread.is_alive():
|
||||
logger.error("未检测到图片上传线程活动,图片上传线程可能出现异常, requestId:{}", request_id)
|
||||
raise Exception("未检测到图片上传线程活动,图片上传线程可能出现异常!")
|
||||
|
||||
|
||||
class OnlinePullVideoStreamProcess(PullVideoStreamProcess):
|
||||
__slots__ = ()
|
||||
|
||||
def run(self):
|
||||
# 避免循环调用性能影响, 优先赋值
|
||||
context, msg, analyse_type, frame_num = self._context, self._msg, self._analyse_type, self._frame_num
|
||||
base_dir, env, service = context['base_dir'], context['env'], context["service"]
|
||||
request_id, pull_url = msg["request_id"], msg["pull_url"]
|
||||
pull_stream_timeout, read_stream_timeout, service_timeout = int(service["cv2_pull_stream_timeout"]), \
|
||||
int(service["cv2_read_stream_timeout"]), int(service["timeout"]) + 120
|
||||
command_queue, pull_queue, image_queue, fb_queue ,mqtt_list= self._command_queue, self._pull_queue, self._image_queue, \
|
||||
self._fb_queue,self._mqtt_list
|
||||
image_thread, ex = None, None
|
||||
width, height, width_height_3, all_frames, w_2, h_2, pull_p = None, None, None, 0, None, None, None
|
||||
frame_list, frame_index_list = [], []
|
||||
ex_status = True
|
||||
try:
|
||||
# 初始化日志
|
||||
init_log(base_dir, env)
|
||||
logger.info("开启启动实时视频拉流进程, requestId:{},pid:{},ppid:{}", request_id,os.getpid(),os.getppid())
|
||||
|
||||
#开启mqtt
|
||||
if service["mqtt_flag"]==1:
|
||||
mqtt_thread = self.start_PullMqtt(fb_queue, mqtt_list, request_id, analyse_type, context)
|
||||
|
||||
# 开启图片上传线程
|
||||
image_thread = self.start_File_upload(fb_queue, context, msg, image_queue, analyse_type,mqtt_list)
|
||||
cv2_init_num, init_pull_num, concurrent_frame = 0, 1, 1
|
||||
start_time, pull_stream_start_time, read_start_time, full_timeout = time(), None, None, None
|
||||
while True:
|
||||
# 检测任务执行是否超时、图片上传线程是否正常
|
||||
self.check(start_time, service_timeout, request_id, image_thread)
|
||||
command_msg = get_no_block_queue(command_queue)
|
||||
if command_msg is not None:
|
||||
if 'stop' == command_msg.get("command"):
|
||||
logger.info("开始停止实时拉流进程, requestId:{}", request_id)
|
||||
break
|
||||
if 'stop_ex' == command_msg.get("command"):
|
||||
logger.info("开始停止实时拉流进程, requestId:{}", request_id)
|
||||
ex_status = False
|
||||
break
|
||||
if command_msg.get("command") in ['algStart' , 'algStop' ]:
|
||||
logger.info("拉流进程中,requestId:{},向图片上传进程发送命令:{}", request_id,command_msg.get("command"))
|
||||
put_queue(image_queue, (2, command_msg.get("command") ), timeout=1)
|
||||
|
||||
# 检测视频信息是否存在或拉流对象是否存在
|
||||
if check_video_stream(width, height):
|
||||
if len(frame_list) > 0:
|
||||
put_queue(pull_queue, (4, (frame_list, frame_index_list, all_frames)), timeout=1)
|
||||
frame_list, frame_index_list = [], []
|
||||
logger.info("开始重新获取视频信息: {}次, requestId: {}", cv2_init_num, request_id)
|
||||
if pull_stream_start_time is None:
|
||||
pull_stream_start_time = time()
|
||||
pull_stream_init_timeout = time() - pull_stream_start_time
|
||||
if pull_stream_init_timeout > pull_stream_timeout:
|
||||
logger.info("开始拉流超时, 超时时间:{}, requestId:{}", pull_stream_init_timeout, request_id)
|
||||
# 如果超时了, 将异常信息发送给主进程,如果队列满了,抛出异常
|
||||
raise ServiceException(ExceptionType.PULLSTREAM_TIMEOUT_EXCEPTION.value[0],
|
||||
ExceptionType.PULLSTREAM_TIMEOUT_EXCEPTION.value[1])
|
||||
cv2_init_num += 1
|
||||
width, height, width_height_3, all_frames, w_2, h_2 = build_video_info(pull_url, request_id)
|
||||
if width is None:
|
||||
sleep(1)
|
||||
continue
|
||||
pull_stream_start_time, cv2_init_num = None, 1
|
||||
frame, pull_p, width, height = pull_read_video_stream(pull_p, pull_url, width, height, width_height_3,
|
||||
w_2, h_2, request_id)
|
||||
if pull_queue.full():
|
||||
logger.info("pull拉流队列满了:{}, requestId: {}", os.getppid(), request_id)
|
||||
if full_timeout is None:
|
||||
full_timeout = time()
|
||||
if time() - full_timeout > 180:
|
||||
logger.error("拉流队列阻塞超时, 请检查父进程是否正常!requestId: {}", request_id)
|
||||
raise ServiceException(ExceptionType.SERVICE_INNER_EXCEPTION.value[0],
|
||||
ExceptionType.SERVICE_INNER_EXCEPTION.value[1])
|
||||
if psutil.Process(getpid()).ppid() == 1:
|
||||
clear_pull_p(pull_p, request_id)
|
||||
ex_status = False
|
||||
for q in [command_queue, pull_queue, image_queue]:
|
||||
clear_queue(q)
|
||||
if image_thread and image_thread.is_alive():
|
||||
put_queue(image_queue, (2, "stop"), timeout=1)
|
||||
image_thread.join(120)
|
||||
logger.info("检测到父进程异常停止, 请检测服务器资源是否负载过高, requestId: {}", request_id)
|
||||
put_queue(self._fb_queue, message_feedback(request_id, AnalysisStatus.FAILED.value,
|
||||
self._analyse_type,
|
||||
ExceptionType.NO_RESOURCES.value[0],
|
||||
ExceptionType.NO_RESOURCES.value[1]), timeout=2)
|
||||
break
|
||||
del frame
|
||||
continue
|
||||
full_timeout = None
|
||||
if frame is None:
|
||||
clear_pull_p(pull_p, request_id)
|
||||
if len(frame_list) > 0:
|
||||
put_queue(pull_queue, (4, (frame_list, frame_index_list, all_frames)), timeout=1)
|
||||
frame_list, frame_index_list = [], []
|
||||
logger.info("获取帧为空, 开始重试: {}次, requestId: {}", init_pull_num, request_id)
|
||||
if read_start_time is None:
|
||||
read_start_time = time()
|
||||
pull_stream_read_timeout = time() - read_start_time
|
||||
if pull_stream_read_timeout > read_stream_timeout:
|
||||
logger.info("拉流过程中断了重试超时, 超时时间: {}, requestId: {}", pull_stream_read_timeout,
|
||||
request_id)
|
||||
raise ServiceException(ExceptionType.READSTREAM_TIMEOUT_EXCEPTION.value[0],
|
||||
ExceptionType.READSTREAM_TIMEOUT_EXCEPTION.value[1])
|
||||
init_pull_num += 1
|
||||
sleep(1)
|
||||
continue
|
||||
init_pull_num, read_start_time = 1, None
|
||||
frame_list.append(frame)
|
||||
frame_index_list.append(concurrent_frame)
|
||||
if len(frame_list) >= frame_num:
|
||||
put_queue(pull_queue, (4, (frame_list, frame_index_list, all_frames)), timeout=1, is_ex=True)
|
||||
frame_list, frame_index_list = [], []
|
||||
concurrent_frame += 1
|
||||
del frame
|
||||
except ServiceException as s:
|
||||
logger.error("实时拉流异常: {}, 队列大小:{}, requestId:{}", s.msg, pull_queue.qsize(), request_id)
|
||||
ex = s.code, s.msg
|
||||
except Exception:
|
||||
logger.error("实时拉流异常: {}, 队列大小:{}, requestId:{}", format_exc(), pull_queue.qsize(), request_id)
|
||||
ex = ExceptionType.SERVICE_INNER_EXCEPTION.value[0], ExceptionType.SERVICE_INNER_EXCEPTION.value[1]
|
||||
finally:
|
||||
clear_pull_p(pull_p, request_id)
|
||||
del frame_list, frame_index_list
|
||||
if ex_status:
|
||||
if ex:
|
||||
code, msg = ex
|
||||
r = put_queue_result(pull_queue, (1, code, msg), timeout=10)
|
||||
else:
|
||||
r = put_queue_result(pull_queue, (2,), timeout=10)
|
||||
if r:
|
||||
c_time = time()
|
||||
while time() - c_time < 60:
|
||||
command_msg = get_no_block_queue(command_queue)
|
||||
if command_msg is not None:
|
||||
if 'stop' == command_msg.get("command"):
|
||||
logger.info("开始停止实时拉流进程, requestId:{}", request_id)
|
||||
if image_thread and image_thread.is_alive():
|
||||
put_queue(image_queue, (2, "stop"), timeout=1)
|
||||
logger.info("停止图片上传线程, requestId:{}", request_id)
|
||||
image_thread.join(120)
|
||||
logger.info("停止图片上传线程结束, requestId:{}", request_id)
|
||||
break
|
||||
for q in [command_queue, pull_queue, image_queue]:
|
||||
clear_queue(q)
|
||||
if image_thread and image_thread.is_alive():
|
||||
put_queue(image_queue, (2, "stop"), timeout=1)
|
||||
logger.info("停止图片上传线程, requestId:{}", request_id)
|
||||
image_thread.join(120)
|
||||
logger.info("停止图片上传线程结束, requestId:{}", request_id)
|
||||
logger.info("实时拉流线程结束, 图片队列: {}, 拉流队列: {}, 图片进程的状态: {} requestId: {}",
|
||||
image_queue.qsize(), pull_queue.qsize(), image_thread.is_alive(), request_id)
|
||||
|
||||
|
||||
class OfflinePullVideoStreamProcess(PullVideoStreamProcess):
|
||||
__slots__ = ()
|
||||
|
||||
def run(self):
|
||||
msg, context, frame_num, analyse_type = self._msg, self._context, self._frame_num, self._analyse_type
|
||||
request_id, base_dir, env, pull_url = msg["request_id"], context['base_dir'], context['env'], msg["pull_url"]
|
||||
ex, service_timeout, full_timeout = None, int(context["service"]["timeout"]) + 120, None
|
||||
command_queue, pull_queue, image_queue, fb_queue = self._command_queue, self._pull_queue, self._image_queue, \
|
||||
self._fb_queue
|
||||
image_thread, pull_p = None, None
|
||||
width, height, width_height_3, all_frames, w_2, h_2 = None, None, None, 0, None, None
|
||||
frame_list, frame_index_list = [], []
|
||||
ex_status = True
|
||||
try:
|
||||
# 初始化日志
|
||||
init_log(base_dir, env)
|
||||
logger.info("开启离线视频拉流进程, requestId:{}", request_id)
|
||||
|
||||
# 开启图片上传线程
|
||||
image_thread = self.start_File_upload(fb_queue, context, msg, image_queue, analyse_type,[])
|
||||
|
||||
# 初始化拉流工具类
|
||||
cv2_init_num, concurrent_frame = 0, 1
|
||||
start_time = time()
|
||||
while True:
|
||||
# 检测任务执行是否超时、图片上传线程是否正常
|
||||
self.check(start_time, service_timeout, request_id, image_thread)
|
||||
command_msg = get_no_block_queue(command_queue)
|
||||
if command_msg is not None:
|
||||
if 'stop' == command_msg.get("command"):
|
||||
logger.info("开始停止离线拉流进程, requestId:{}", request_id)
|
||||
break
|
||||
if 'stop_ex' == command_msg.get("command"):
|
||||
logger.info("开始停止离线拉流进程, requestId:{}", request_id)
|
||||
ex_status = False
|
||||
break
|
||||
if command_msg.get("command") in ['algStart' , 'algStop' ]:
|
||||
logger.info("拉流进程中,requestId:{},向图片上传进程发送命令:{}", request_id,command_msg.get("command"))
|
||||
put_queue(image_queue, (2, command_msg.get("command") ), timeout=1)
|
||||
|
||||
# 检测视频信息是否存在或拉流对象是否存在
|
||||
if check_video_stream(width, height):
|
||||
logger.info("开始重新获取视频信息: {}次, requestId: {}", cv2_init_num, request_id)
|
||||
if cv2_init_num > 3:
|
||||
logger.info("离线拉流重试失败, 重试次数: {}, requestId: {}", cv2_init_num, request_id)
|
||||
raise ServiceException(ExceptionType.OR_VIDEO_ADDRESS_EXCEPTION.value[0],
|
||||
ExceptionType.OR_VIDEO_ADDRESS_EXCEPTION.value[1])
|
||||
cv2_init_num += 1
|
||||
sleep(1)
|
||||
width, height, width_height_3, all_frames, w_2, h_2 = build_video_info(pull_url, request_id)
|
||||
continue
|
||||
if pull_queue.full():
|
||||
logger.info("pull拉流队列满了:{}, requestId: {}", os.getppid(), request_id)
|
||||
if full_timeout is None:
|
||||
full_timeout = time()
|
||||
if time() - full_timeout > 180:
|
||||
logger.error("pull队列阻塞超时,请检测父进程是否正常!requestId: {}", request_id)
|
||||
raise ServiceException(ExceptionType.SERVICE_INNER_EXCEPTION.value[0],
|
||||
ExceptionType.SERVICE_INNER_EXCEPTION.value[1])
|
||||
if psutil.Process(getpid()).ppid() == 1:
|
||||
clear_pull_p(pull_p, request_id)
|
||||
ex_status = False
|
||||
for q in [command_queue, pull_queue, image_queue]:
|
||||
clear_queue(q)
|
||||
put_queue(image_queue, (2, "stop"), timeout=1)
|
||||
image_thread.join(120)
|
||||
logger.info("检测到父进程异常停止, 请检测服务器资源是否负载过高, requestId: {}", request_id)
|
||||
put_queue(self._fb_queue, message_feedback(request_id,
|
||||
AnalysisStatus.FAILED.value,
|
||||
self._analyse_type,
|
||||
ExceptionType.NO_RESOURCES.value[0],
|
||||
ExceptionType.NO_RESOURCES.value[1]), timeout=2)
|
||||
break
|
||||
continue
|
||||
full_timeout = None
|
||||
frame, pull_p, width, height = pull_read_video_stream(pull_p, pull_url, width, height,
|
||||
width_height_3, w_2, h_2, request_id)
|
||||
if frame is None:
|
||||
logger.info("总帧数: {}, 当前帧数: {}, requestId: {}", all_frames, concurrent_frame, request_id)
|
||||
clear_pull_p(pull_p, request_id)
|
||||
if len(frame_list) > 0:
|
||||
put_queue(pull_queue, (4, (frame_list, frame_index_list, all_frames)), timeout=1)
|
||||
# 允许100帧的误差
|
||||
if concurrent_frame < all_frames - 100:
|
||||
logger.info("离线拉流异常结束:requestId: {}", request_id)
|
||||
raise ServiceException(ExceptionType.READSTREAM_TIMEOUT_EXCEPTION.value[0],
|
||||
ExceptionType.READSTREAM_TIMEOUT_EXCEPTION.value[1])
|
||||
logger.info("离线拉流线程结束, requestId: {}", request_id)
|
||||
break
|
||||
frame_list.append(frame)
|
||||
frame_index_list.append(concurrent_frame)
|
||||
if len(frame_list) >= frame_num:
|
||||
put_queue(pull_queue, (4, (frame_list, frame_index_list, all_frames)), timeout=1, is_ex=True)
|
||||
frame_list, frame_index_list = [], []
|
||||
concurrent_frame += 1
|
||||
del frame
|
||||
except ServiceException as s:
|
||||
logger.error("离线拉流异常: {}, 队列大小:{}, requestId:{}", s.msg, pull_queue.qsize(), request_id)
|
||||
ex = s.code, s.msg
|
||||
except Exception:
|
||||
logger.error("离线拉流异常: {}, requestId:{}", format_exc(), request_id)
|
||||
ex = ExceptionType.SERVICE_INNER_EXCEPTION.value[0], ExceptionType.SERVICE_INNER_EXCEPTION.value[1]
|
||||
finally:
|
||||
clear_pull_p(pull_p, request_id)
|
||||
del frame_list, frame_index_list
|
||||
if ex_status:
|
||||
if ex:
|
||||
code, msg = ex
|
||||
r = put_queue_result(pull_queue, (1, code, msg), timeout=10)
|
||||
else:
|
||||
r = put_queue_result(pull_queue, (2,), timeout=10)
|
||||
if r:
|
||||
c_time = time()
|
||||
while time() - c_time < 180:
|
||||
command_msg = get_no_block_queue(command_queue)
|
||||
if command_msg is not None:
|
||||
if 'stop' == command_msg.get("command"):
|
||||
logger.info("开始停止实时拉流进程, requestId:{}", request_id)
|
||||
if image_thread and image_thread.is_alive():
|
||||
put_queue(image_queue, (2, "stop"), timeout=1)
|
||||
logger.info("停止图片上传线程, requestId:{}", request_id)
|
||||
image_thread.join(120)
|
||||
logger.info("停止图片上传线程结束, requestId:{}", request_id)
|
||||
break
|
||||
for q in [command_queue, pull_queue, image_queue]:
|
||||
clear_queue(q)
|
||||
if image_thread and image_thread.is_alive():
|
||||
put_queue(image_queue, (2, "stop"), timeout=1)
|
||||
logger.info("停止图片上传线程, requestId:{}", request_id)
|
||||
image_thread.join(120)
|
||||
logger.info("停止图片上传线程结束, requestId:{}", request_id)
|
||||
logger.info("离线拉流线程结束, 图片队列: {}, 拉流队列: {}, 图片进程的状态: {} requestId: {}",
|
||||
image_queue.qsize(), pull_queue.qsize(), image_thread.is_alive(), request_id)
|
||||
|
|
@ -0,0 +1,349 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
from multiprocessing import Process, Queue
|
||||
from os import getpid
|
||||
from time import time, sleep
|
||||
from traceback import format_exc
|
||||
|
||||
import psutil
|
||||
from loguru import logger
|
||||
|
||||
from util.LogUtils import init_log
|
||||
from concurrency.FileUploadThread import ImageFileUpload
|
||||
from entity.FeedBack import message_feedback
|
||||
from enums.AnalysisStatusEnum import AnalysisStatus
|
||||
from enums.ExceptionEnum import ExceptionType
|
||||
from exception.CustomerException import ServiceException
|
||||
from util.Cv2Utils import check_video_stream, build_video_info, pull_read_video_stream, clear_pull_p
|
||||
from util.QueUtil import get_no_block_queue, put_queue, clear_queue, put_queue_result
|
||||
|
||||
|
||||
class PullVideoStreamProcess2(Process):
|
||||
__slots__ = ("_command_queue", "_msg", "_context", "_fb_queue", "_pull_queue", "_image_queue", "_analyse_type",
|
||||
"_frame_num")
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
# 自带参数
|
||||
self._command_queue = Queue()
|
||||
|
||||
# 传参
|
||||
self._msg, self._context, self._fb_queue, self._pull_queue, self._image_queue, self._analyse_type, \
|
||||
self._frame_num = args
|
||||
|
||||
def sendCommand(self, result):
|
||||
try:
|
||||
self._command_queue.put(result, timeout=10)
|
||||
except Exception:
|
||||
logger.error("添加队列超时异常:{}, requestId:{}", format_exc(), self._msg.get("request_id"))
|
||||
raise ServiceException(ExceptionType.SERVICE_INNER_EXCEPTION.value[0],
|
||||
ExceptionType.SERVICE_INNER_EXCEPTION.value[1])
|
||||
|
||||
@staticmethod
|
||||
def start_File_upload(*args):
|
||||
fb_queue, context, msg, image_queue, analyse_type = args
|
||||
image_thread = ImageFileUpload(fb_queue, context, msg, image_queue, analyse_type)
|
||||
image_thread.setDaemon(True)
|
||||
image_thread.start()
|
||||
return image_thread
|
||||
|
||||
@staticmethod
|
||||
def check(start_time, service_timeout, request_id, image_thread):
|
||||
if time() - start_time > service_timeout:
|
||||
logger.error("分析超时, requestId: {}", request_id)
|
||||
raise ServiceException(ExceptionType.ANALYSE_TIMEOUT_EXCEPTION.value[0],
|
||||
ExceptionType.ANALYSE_TIMEOUT_EXCEPTION.value[1])
|
||||
# 检测图片上传线程是否正常运行
|
||||
if image_thread is not None and not image_thread.is_alive():
|
||||
logger.error("未检测到图片上传线程活动,图片上传线程可能出现异常, requestId:{}", request_id)
|
||||
raise Exception("未检测到图片上传线程活动,图片上传线程可能出现异常!")
|
||||
|
||||
|
||||
class OnlinePullVideoStreamProcess2(PullVideoStreamProcess2):
|
||||
__slots__ = ()
|
||||
|
||||
def run(self):
|
||||
# 避免循环调用性能影响, 优先赋值
|
||||
context, msg, analyse_type = self._context, self._msg, self._analyse_type
|
||||
request_id, base_dir, env = msg["request_id"], context['base_dir'], context['env']
|
||||
pull_url, frame_num = msg["pull_url"], self._frame_num
|
||||
pull_stream_timeout = int(context["service"]["cv2_pull_stream_timeout"])
|
||||
read_stream_timeout = int(context["service"]["cv2_read_stream_timeout"])
|
||||
service_timeout = int(context["service"]["timeout"])
|
||||
command_queue, pull_queue, image_queue = self._command_queue, self._pull_queue, self._image_queue
|
||||
fb_queue = self._fb_queue
|
||||
image_thread, pull_p = None, None
|
||||
width, height, width_height_3, all_frames, w_2, h_2 = None, None, None, 0, None, None
|
||||
frame_list, frame_index_list = [], []
|
||||
ex = None
|
||||
ex_status = True
|
||||
full_timeout = None
|
||||
try:
|
||||
# 初始化日志
|
||||
init_log(base_dir, env)
|
||||
logger.info("开启实时视频拉流进程, requestId:{}", request_id)
|
||||
|
||||
# 开启图片上传线程
|
||||
image_thread = self.start_File_upload(fb_queue, context, msg, image_queue, analyse_type)
|
||||
|
||||
# 初始化拉流工具类
|
||||
cv2_init_num, init_pull_num, concurrent_frame = 0, 1, 1
|
||||
start_time, pull_start_time, read_start_time = time(), None, None
|
||||
while True:
|
||||
# 检测任务执行是否超时、图片上传线程是否正常
|
||||
self.check(start_time, service_timeout, request_id, image_thread)
|
||||
command_msg = get_no_block_queue(command_queue)
|
||||
if command_msg is not None:
|
||||
if 'stop' == command_msg.get("command"):
|
||||
logger.info("开始停止实时拉流进程, requestId:{}", request_id)
|
||||
break
|
||||
if 'stop_ex' == command_msg.get("command"):
|
||||
logger.info("开始停止实时拉流进程, requestId:{}", request_id)
|
||||
ex_status = False
|
||||
break
|
||||
# 检测视频信息是否存在或拉流对象是否存在
|
||||
if check_video_stream(width, height):
|
||||
if len(frame_list) > 0:
|
||||
put_queue(pull_queue, (4, (frame_list, frame_index_list, all_frames)), timeout=1)
|
||||
frame_list, frame_index_list = [], []
|
||||
logger.info("开始重新获取视频信息: {}次, requestId: {}", cv2_init_num, request_id)
|
||||
if pull_start_time is None:
|
||||
pull_start_time = time()
|
||||
pull_stream_init_timeout = time() - pull_start_time
|
||||
if pull_stream_init_timeout > pull_stream_timeout:
|
||||
logger.info("开始拉流超时, 超时时间:{}, requestId:{}", pull_stream_init_timeout, request_id)
|
||||
raise ServiceException(ExceptionType.PULLSTREAM_TIMEOUT_EXCEPTION.value[0],
|
||||
ExceptionType.PULLSTREAM_TIMEOUT_EXCEPTION.value[1])
|
||||
cv2_init_num += 1
|
||||
width, height, width_height_3, all_frames, w_2, h_2 = build_video_info(pull_url, request_id)
|
||||
if width is None:
|
||||
sleep(1)
|
||||
continue
|
||||
pull_start_time, cv2_init_num = None, 1
|
||||
frame, pull_p, width, height = pull_read_video_stream(pull_p, pull_url, width, height, width_height_3,
|
||||
w_2, h_2, request_id)
|
||||
if frame is None:
|
||||
if len(frame_list) > 0:
|
||||
put_queue(pull_queue, (4, (frame_list, frame_index_list, all_frames)), timeout=1)
|
||||
frame_list, frame_index_list = [], []
|
||||
logger.info("获取帧为空, 开始重试: {}次, requestId: {}", init_pull_num, request_id)
|
||||
if read_start_time is None:
|
||||
read_start_time = time()
|
||||
pull_stream_read_timeout = time() - read_start_time
|
||||
if pull_stream_read_timeout > read_stream_timeout:
|
||||
logger.info("拉流过程中断了重试超时, 超时时间: {}, requestId: {}", pull_stream_read_timeout,
|
||||
request_id)
|
||||
raise ServiceException(ExceptionType.READSTREAM_TIMEOUT_EXCEPTION.value[0],
|
||||
ExceptionType.READSTREAM_TIMEOUT_EXCEPTION.value[1])
|
||||
init_pull_num += 1
|
||||
continue
|
||||
init_pull_num, read_start_time = 1, None
|
||||
if pull_queue.full():
|
||||
logger.info("pull拉流队列满了:{}, requestId: {}", os.getppid(), request_id)
|
||||
if full_timeout is None:
|
||||
full_timeout = time()
|
||||
if time() - full_timeout > 180:
|
||||
logger.error("拉流队列阻塞异常, requestId: {}", request_id)
|
||||
raise ServiceException(ExceptionType.SERVICE_INNER_EXCEPTION.value[0],
|
||||
ExceptionType.SERVICE_INNER_EXCEPTION.value[1])
|
||||
if psutil.Process(getpid()).ppid() == 1:
|
||||
clear_pull_p(pull_p, request_id)
|
||||
ex_status = False
|
||||
for q in [command_queue, pull_queue, image_queue]:
|
||||
clear_queue(q)
|
||||
if image_thread and image_thread.is_alive():
|
||||
put_queue(image_queue, (2, "stop"), timeout=1)
|
||||
image_thread.join(120)
|
||||
logger.info("检测到父进程异常停止, 请检测服务器资源是否负载过高, requestId: {}", request_id)
|
||||
put_queue(self._fb_queue, message_feedback(request_id,
|
||||
AnalysisStatus.FAILED.value,
|
||||
self._analyse_type,
|
||||
ExceptionType.NO_RESOURCES.value[0],
|
||||
ExceptionType.NO_RESOURCES.value[1]))
|
||||
break
|
||||
del frame
|
||||
continue
|
||||
full_timeout = None
|
||||
frame_list.append(frame)
|
||||
frame_index_list.append(concurrent_frame)
|
||||
if len(frame_list) >= frame_num:
|
||||
put_queue(pull_queue, (4, (frame_list, frame_index_list, all_frames)), timeout=1, is_ex=True)
|
||||
frame_list, frame_index_list = [], []
|
||||
concurrent_frame += 1
|
||||
del frame
|
||||
except ServiceException as s:
|
||||
logger.error("实时拉流异常: {}, 队列大小:{}, requestId:{}", s.msg, pull_queue.qsize(), request_id)
|
||||
ex = s.code, s.msg
|
||||
except Exception:
|
||||
logger.error("实时拉流异常: {}, 队列大小:{}, requestId:{}", format_exc(), pull_queue.qsize(), request_id)
|
||||
ex = ExceptionType.SERVICE_INNER_EXCEPTION.value[0], ExceptionType.SERVICE_INNER_EXCEPTION.value[1]
|
||||
finally:
|
||||
clear_pull_p(pull_p, request_id)
|
||||
del frame_list, frame_index_list
|
||||
if ex_status:
|
||||
if ex:
|
||||
code, msg = ex
|
||||
r = put_queue_result(pull_queue, (1, code, msg), timeout=10)
|
||||
else:
|
||||
r = put_queue_result(pull_queue, (2,), timeout=10)
|
||||
if r:
|
||||
c_time = time()
|
||||
while time() - c_time < 180:
|
||||
command_msg = get_no_block_queue(command_queue)
|
||||
if command_msg is not None:
|
||||
if 'stop' == command_msg.get("command"):
|
||||
logger.info("开始停止实时拉流进程, requestId:{}", request_id)
|
||||
if image_thread and image_thread.is_alive():
|
||||
put_queue(image_queue, (2, "stop"), timeout=1)
|
||||
logger.info("停止图片上传线程, requestId:{}", request_id)
|
||||
image_thread.join(120)
|
||||
logger.info("停止图片上传线程结束, requestId:{}", request_id)
|
||||
break
|
||||
for q in [command_queue, pull_queue, image_queue]:
|
||||
clear_queue(q)
|
||||
if image_thread and image_thread.is_alive():
|
||||
put_queue(image_queue, (2, "stop"), timeout=1)
|
||||
logger.info("停止图片上传线程, requestId:{}", request_id)
|
||||
image_thread.join(120)
|
||||
logger.info("停止图片上传线程结束, requestId:{}", request_id)
|
||||
logger.info("实时拉流线程结束, 图片队列: {}, 拉流队列: {}, 图片进程的状态: {} requestId: {}",
|
||||
image_queue.qsize(), pull_queue.qsize(), image_thread.is_alive(), request_id)
|
||||
|
||||
|
||||
class OfflinePullVideoStreamProcess2(PullVideoStreamProcess2):
|
||||
__slots__ = ()
|
||||
|
||||
def run(self):
|
||||
msg, context, frame_num, analyse_type = self._msg, self._context, self._frame_num, self._analyse_type
|
||||
request_id, base_dir, env, pull_url = msg["request_id"], context['base_dir'], context['env'], msg["pull_url"]
|
||||
ex, service_timeout = None, int(context["service"]["timeout"])
|
||||
command_queue, pull_queue, image_queue, fb_queue = self._command_queue, self._pull_queue, self._image_queue, \
|
||||
self._fb_queue
|
||||
image_thread, pull_p = None, None
|
||||
width, height, width_height_3, all_frames, w_2, h_2 = None, None, None, 0, None, None
|
||||
frame_list, frame_index_list = [], []
|
||||
ex_status = True
|
||||
full_timeout = None
|
||||
try:
|
||||
# 初始化日志
|
||||
init_log(base_dir, env)
|
||||
logger.info("开启离线视频拉流进程, requestId:{}", request_id)
|
||||
|
||||
# 开启图片上传线程
|
||||
image_thread = self.start_File_upload(fb_queue, context, msg, image_queue, analyse_type)
|
||||
|
||||
# 初始化拉流工具类
|
||||
cv2_init_num = 0
|
||||
concurrent_frame = 1
|
||||
start_time = time()
|
||||
while True:
|
||||
# 检测任务执行是否超时、图片上传线程是否正常
|
||||
self.check(start_time, service_timeout, request_id, image_thread)
|
||||
command_msg = get_no_block_queue(command_queue)
|
||||
if command_msg is not None:
|
||||
if 'stop' == command_msg.get("command"):
|
||||
logger.info("开始停止离线拉流进程, requestId:{}", request_id)
|
||||
break
|
||||
if 'stop_ex' == command_msg.get("command"):
|
||||
logger.info("开始停止离线拉流进程, requestId:{}", request_id)
|
||||
ex_status = False
|
||||
break
|
||||
# 检测视频信息是否存在或拉流对象是否存在
|
||||
if check_video_stream(width, height):
|
||||
if len(frame_list) > 0:
|
||||
put_queue(pull_queue, (4, (frame_list, frame_index_list, all_frames)), timeout=1)
|
||||
frame_list, frame_index_list = [], []
|
||||
logger.info("开始重新获取视频信息: {}次, requestId: {}", cv2_init_num, request_id)
|
||||
if cv2_init_num > 3:
|
||||
clear_pull_p(pull_p, request_id)
|
||||
logger.info("离线拉流重试失败, 重试次数: {}, requestId: {}", cv2_init_num, request_id)
|
||||
raise ServiceException(ExceptionType.OR_VIDEO_ADDRESS_EXCEPTION.value[0],
|
||||
ExceptionType.OR_VIDEO_ADDRESS_EXCEPTION.value[1])
|
||||
cv2_init_num += 1
|
||||
sleep(1)
|
||||
width, height, width_height_3, all_frames, w_2, h_2 = build_video_info(pull_url, request_id)
|
||||
continue
|
||||
if pull_queue.full():
|
||||
logger.info("pull拉流队列满了:{}, requestId: {}", os.getppid(), request_id)
|
||||
if full_timeout is None:
|
||||
full_timeout = time()
|
||||
if time() - full_timeout > 300:
|
||||
logger.error("拉流队列阻塞超时, 请检查父进程是否正常!requestId: {}", request_id)
|
||||
raise ServiceException(ExceptionType.SERVICE_INNER_EXCEPTION.value[0],
|
||||
ExceptionType.SERVICE_INNER_EXCEPTION.value[1])
|
||||
if psutil.Process(getpid()).ppid() == 1:
|
||||
clear_pull_p(pull_p, request_id)
|
||||
ex_status = False
|
||||
for q in [command_queue, pull_queue, image_queue]:
|
||||
clear_queue(q)
|
||||
if image_thread and image_thread.is_alive():
|
||||
put_queue(image_queue, (2, "stop"), timeout=1)
|
||||
image_thread.join(120)
|
||||
logger.info("检测到父进程异常停止, 请检测服务器资源是否负载过高, requestId: {}", request_id)
|
||||
put_queue(self._fb_queue, message_feedback(request_id,
|
||||
AnalysisStatus.FAILED.value,
|
||||
self._analyse_type,
|
||||
ExceptionType.NO_RESOURCES.value[0],
|
||||
ExceptionType.NO_RESOURCES.value[1]))
|
||||
break
|
||||
continue
|
||||
full_timeout = None
|
||||
frame, pull_p, width, height = pull_read_video_stream(pull_p, pull_url, width, height, width_height_3,
|
||||
w_2, h_2, request_id)
|
||||
if frame is None:
|
||||
logger.info("总帧数: {}, 当前帧数: {}, requestId: {}", all_frames, concurrent_frame, request_id)
|
||||
clear_pull_p(pull_p, request_id)
|
||||
if len(frame_list) > 0:
|
||||
put_queue(pull_queue, (4, (frame_list, frame_index_list, all_frames)), timeout=2, is_ex=False)
|
||||
frame_list, frame_index_list = [], []
|
||||
# 允许100帧的误差
|
||||
if concurrent_frame < all_frames - 100:
|
||||
logger.info("离线拉流异常结束:requestId: {}", request_id)
|
||||
raise ServiceException(ExceptionType.READSTREAM_TIMEOUT_EXCEPTION.value[0],
|
||||
ExceptionType.READSTREAM_TIMEOUT_EXCEPTION.value[1])
|
||||
logger.info("离线拉流线程结束, requestId: {}", request_id)
|
||||
break
|
||||
frame_list.append(frame)
|
||||
frame_index_list.append(concurrent_frame)
|
||||
if len(frame_list) >= frame_num:
|
||||
put_queue(pull_queue, (4, (frame_list, frame_index_list, all_frames)), timeout=1, is_ex=True)
|
||||
frame_list, frame_index_list = [], []
|
||||
concurrent_frame += 1
|
||||
del frame
|
||||
except ServiceException as s:
|
||||
logger.error("实时拉流异常: {}, 队列大小:{}, requestId:{}", s.msg, pull_queue.qsize(), request_id)
|
||||
ex = s.code, s.msg
|
||||
except Exception:
|
||||
logger.error("实时拉流异常: {}, requestId:{}", format_exc(), request_id)
|
||||
ex = ExceptionType.SERVICE_INNER_EXCEPTION.value[0], ExceptionType.SERVICE_INNER_EXCEPTION.value[1]
|
||||
finally:
|
||||
clear_pull_p(pull_p, request_id)
|
||||
del frame_list, frame_index_list
|
||||
if ex_status:
|
||||
if ex:
|
||||
code, msg = ex
|
||||
r = put_queue_result(pull_queue, (1, code, msg), timeout=10)
|
||||
else:
|
||||
r = put_queue_result(pull_queue, (2,), timeout=10)
|
||||
if r:
|
||||
c_time = time()
|
||||
while time() - c_time < 180:
|
||||
command_msg = get_no_block_queue(command_queue)
|
||||
if command_msg is not None:
|
||||
if 'stop' == command_msg.get("command"):
|
||||
logger.info("开始停止离线拉流进程, requestId:{}", request_id)
|
||||
if image_thread and image_thread.is_alive():
|
||||
put_queue(image_queue, (2, "stop"), timeout=1)
|
||||
logger.info("停止图片上传线程, requestId:{}", request_id)
|
||||
image_thread.join(120)
|
||||
logger.info("停止图片上传线程结束, requestId:{}", request_id)
|
||||
break
|
||||
for q in [command_queue, pull_queue, image_queue]:
|
||||
clear_queue(q)
|
||||
if image_thread and image_thread.is_alive():
|
||||
put_queue(image_queue, (2, "stop"), timeout=1)
|
||||
logger.info("停止图片上传线程, requestId:{}", request_id)
|
||||
image_thread.join(120)
|
||||
logger.info("停止图片上传线程结束, requestId:{}", request_id)
|
||||
logger.info("离线拉流线程结束, 图片队列: {}, 拉流队列: {}, 图片进程的状态: {} requestId: {}",
|
||||
image_queue.qsize(), pull_queue.qsize(), image_thread.is_alive(), request_id)
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from os.path import join
|
||||
from threading import Thread
|
||||
from traceback import format_exc
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
from loguru import logger
|
||||
from util.Cv2Utils import write_or_video, write_ai_video, push_video_stream, close_all_p, video_conjuncing
|
||||
from util.ImageUtils import url2Array, add_water_pic
|
||||
from util.PlotsUtils import draw_painting_joint
|
||||
from util.QueUtil import put_queue
|
||||
|
||||
|
||||
class OnPushStreamThread(Thread):
|
||||
__slots__ = ('_msg', '_push_queue', '_context', 'ex', '_logo', '_image_queue')
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
# 传参
|
||||
self._msg, self._push_queue, self._image_queue, self._context = args
|
||||
# 自带参数
|
||||
self.ex = None
|
||||
self._logo = None
|
||||
if self._context["video"]["video_add_water"]:
|
||||
self._logo = self._msg.get("logo_url")
|
||||
if self._logo:
|
||||
self._logo = url2Array(self._logo, enable_ex=False)
|
||||
if not self._logo:
|
||||
self._logo = cv2.imread(join(self._context['base_dir'], "image/logo.png"), -1)
|
||||
|
||||
def run(self):
|
||||
request_id, push_queue, image_queue = self._msg.get("request_id"), self._push_queue, self._image_queue
|
||||
orFilePath, aiFilePath, logo = self._context.get("orFilePath"), self._context.get("aiFilePath"), self._logo
|
||||
or_video_file, ai_video_file, push_p = None, None, None
|
||||
push_url = self._msg.get("push_url")
|
||||
try:
|
||||
logger.info("开始启动推流线程!requestId:{}", request_id)
|
||||
with ThreadPoolExecutor(max_workers=2) as t:
|
||||
p_push_status, or_write_status, ai_write_status = [0, 0], [0, 0], [0, 0]
|
||||
while True:
|
||||
push_parm = push_queue.get()
|
||||
if push_parm is not None:
|
||||
# [(1, 原视频帧, 分析视频帧)]
|
||||
# # [视频帧、当前帧数、 总帧数、 [(问题数组、code、allowedList、label_arraylist、rainbows)]]
|
||||
# res = (1, (pull_frame[1], pull_frame[2], pull_frame[3], []))
|
||||
# [(2, 操作指令)]
|
||||
if push_parm[0] == 1: # 视频帧操作
|
||||
frame, current_frame, all_frames, ques_list = push_parm[1]
|
||||
copy_frame = frame.copy()
|
||||
det_xywh = {}
|
||||
if len(ques_list) > 0:
|
||||
for qs in ques_list:
|
||||
det_xywh[qs[1]] = {}
|
||||
detect_targets_code = int(qs[0][0])
|
||||
score = qs[0][-1]
|
||||
label_array = qs[3][detect_targets_code]
|
||||
color = qs[4][detect_targets_code]
|
||||
if not isinstance(qs[0][1], (list, tuple, np.ndarray)):
|
||||
xc, yc, x2, y2 = int(qs[0][1]), int(qs[0][2]), int(qs[0][3]), int(qs[0][4])
|
||||
box = [(xc, yc), (x2, yc), (x2, y2), (xc, y2)]
|
||||
else:
|
||||
box = qs[0][1]
|
||||
draw_painting_joint(box, copy_frame, label_array, score, color, "leftTop")
|
||||
cd = det_xywh[qs[1]].get(detect_targets_code)
|
||||
if cd is None:
|
||||
det_xywh[qs[1]][detect_targets_code] = [
|
||||
[detect_targets_code, box, score, label_array, color]]
|
||||
else:
|
||||
det_xywh[qs[1]][detect_targets_code].append(
|
||||
[detect_targets_code, box, score, label_array, color])
|
||||
if logo:
|
||||
frame = add_water_pic(frame, logo, request_id)
|
||||
copy_frame = add_water_pic(copy_frame, logo, request_id)
|
||||
frame_merge = video_conjuncing(frame, copy_frame)
|
||||
# 写原视频到本地
|
||||
write_or_video_result = t.submit(write_or_video, frame, orFilePath, or_video_file,
|
||||
or_write_status, request_id)
|
||||
# 写识别视频到本地
|
||||
write_ai_video_result = t.submit(write_ai_video, frame_merge, aiFilePath, ai_video_file,
|
||||
ai_write_status, request_id)
|
||||
if len(det_xywh) > 0:
|
||||
put_queue(image_queue, (1, (det_xywh, frame, current_frame, all_frames)))
|
||||
push_p = push_video_stream(frame_merge, push_p, push_url, p_push_status, request_id)
|
||||
ai_video_file = write_ai_video_result.result()
|
||||
or_video_file = write_or_video_result.result()
|
||||
if push_parm[0] == 2:
|
||||
if 'stop' == push_parm[1]:
|
||||
logger.info("停止推流线程, requestId: {}", request_id)
|
||||
close_all_p(push_p, or_video_file, ai_video_file, request_id)
|
||||
or_video_file, ai_video_file, push_p = None, None, None
|
||||
break
|
||||
except Exception as e:
|
||||
logger.error("推流线程异常:{}, requestId:{}", format_exc(), request_id)
|
||||
self.ex = e
|
||||
finally:
|
||||
close_all_p(push_p, or_video_file, ai_video_file, request_id)
|
||||
logger.info("推流线程停止完成!requestId:{}", request_id)
|
||||
|
||||
|
||||
class OffPushStreamThread(Thread):
|
||||
__slots__ = ('_msg', '_push_queue', '_context', 'ex', '_logo', '_image_queue')
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
# 传参
|
||||
self._msg, self._push_queue, self._image_queue, self._context = args
|
||||
# 自带参数
|
||||
self.ex = None
|
||||
self._logo = None
|
||||
if self._context["video"]["video_add_water"]:
|
||||
self._logo = self._msg.get("logo_url")
|
||||
if self._logo:
|
||||
self._logo = url2Array(self._logo, enable_ex=False)
|
||||
if not self._logo:
|
||||
self._logo = cv2.imread(join(self._context['base_dir'], "image/logo.png"), -1)
|
||||
|
||||
def run(self):
|
||||
request_id, push_queue, image_queue = self._msg.get("request_id"), self._push_queue, self._image_queue
|
||||
aiFilePath, logo = self._context.get("aiFilePath"), self._logo
|
||||
ai_video_file, push_p = None, None
|
||||
push_url = self._msg.get("push_url")
|
||||
try:
|
||||
logger.info("开始启动推流线程!requestId:{}", request_id)
|
||||
with ThreadPoolExecutor(max_workers=1) as t:
|
||||
p_push_status, or_write_status, ai_write_status = [0, 0], [0, 0], [0, 0]
|
||||
while True:
|
||||
push_parm = push_queue.get()
|
||||
if push_parm is not None:
|
||||
# [(1, 原视频帧, 分析视频帧)]
|
||||
# # [视频帧、当前帧数、 总帧数、 [(问题数组、code、allowedList、label_arraylist、rainbows)]]
|
||||
# res = (1, (pull_frame[1], pull_frame[2], pull_frame[3], []))
|
||||
# [(2, 操作指令)]
|
||||
if push_parm[0] == 1: # 视频帧操作
|
||||
frame, current_frame, all_frames, ques_list = push_parm[1]
|
||||
copy_frame = frame.copy()
|
||||
det_xywh = {}
|
||||
if len(ques_list) > 0:
|
||||
for qs in ques_list:
|
||||
det_xywh[qs[1]] = {}
|
||||
detect_targets_code = int(qs[0][0])
|
||||
score = qs[0][-1]
|
||||
label_array = qs[3][detect_targets_code]
|
||||
color = qs[4][detect_targets_code]
|
||||
if not isinstance(qs[0][1], (list, tuple, np.ndarray)):
|
||||
xc, yc, x2, y2 = int(qs[0][1]), int(qs[0][2]), int(qs[0][3]), int(qs[0][4])
|
||||
box = [(xc, yc), (x2, yc), (x2, y2), (xc, y2)]
|
||||
else:
|
||||
box = qs[0][1]
|
||||
draw_painting_joint(box, copy_frame, label_array, score, color, "leftTop")
|
||||
cd = det_xywh[qs[1]].get(detect_targets_code)
|
||||
if cd is None:
|
||||
det_xywh[qs[1]][detect_targets_code] = [
|
||||
[detect_targets_code, box, score, label_array, color]]
|
||||
else:
|
||||
det_xywh[qs[1]][detect_targets_code].append(
|
||||
[detect_targets_code, box, score, label_array, color])
|
||||
if logo:
|
||||
frame = add_water_pic(frame, logo, request_id)
|
||||
copy_frame = add_water_pic(copy_frame, logo, request_id)
|
||||
frame_merge = video_conjuncing(frame, copy_frame)
|
||||
# 写识别视频到本地
|
||||
write_ai_video_result = t.submit(write_ai_video, frame_merge, aiFilePath, ai_video_file,
|
||||
ai_write_status, request_id)
|
||||
if len(det_xywh) > 0:
|
||||
put_queue(image_queue, (1, (det_xywh, frame, current_frame, all_frames)))
|
||||
push_p = push_video_stream(frame_merge, push_p, push_url, p_push_status, request_id)
|
||||
ai_video_file = write_ai_video_result.result()
|
||||
if push_parm[0] == 2:
|
||||
if 'stop' == push_parm[1]:
|
||||
logger.info("停止推流线程, requestId: {}", request_id)
|
||||
close_all_p(push_p, None, ai_video_file, request_id)
|
||||
ai_video_file, push_p = None, None
|
||||
break
|
||||
except Exception as e:
|
||||
logger.error("推流线程异常:{}, requestId:{}", format_exc(), request_id)
|
||||
self.ex = e
|
||||
finally:
|
||||
close_all_p(push_p, None, ai_video_file, request_id)
|
||||
logger.info("推流线程停止完成!requestId:{}", request_id)
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETED
|
||||
from os.path import join
|
||||
from threading import Thread
|
||||
from traceback import format_exc
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
from loguru import logger
|
||||
from util.Cv2Utils import write_or_video, write_ai_video, push_video_stream, close_all_p, video_conjuncing
|
||||
from util.ImageUtils import url2Array, add_water_pic
|
||||
from util.PlotsUtils import draw_painting_joint
|
||||
from util.QueUtil import put_queue
|
||||
|
||||
|
||||
class OnPushStreamThread2(Thread):
|
||||
__slots__ = ('_msg', '_push_queue', '_context', 'ex', '_logo', '_image_queue')
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
# 传参
|
||||
self._msg, self._push_queue, self._image_queue, self._context = args
|
||||
# 自带参数
|
||||
self.ex = None
|
||||
self._logo = None
|
||||
if self._context["video"]["video_add_water"]:
|
||||
self._logo = self._msg.get("logo_url")
|
||||
if self._logo:
|
||||
self._logo = url2Array(self._logo, enable_ex=False)
|
||||
if not self._logo:
|
||||
self._logo = cv2.imread(join(self._context['base_dir'], "image/logo.png"), -1)
|
||||
|
||||
def run(self):
|
||||
request_id, push_queue, image_queue = self._msg.get("request_id"), self._push_queue, self._image_queue
|
||||
orFilePath, aiFilePath, logo = self._context.get("orFilePath"), self._context.get("aiFilePath"), self._logo
|
||||
or_video_file, ai_video_file, push_p = None, None, None
|
||||
push_url = self._msg.get("push_url")
|
||||
try:
|
||||
logger.info("开始启动推流线程!requestId:{}", request_id)
|
||||
with ThreadPoolExecutor(max_workers=2) as t:
|
||||
with ThreadPoolExecutor(max_workers=5) as tt:
|
||||
p_push_status, or_write_status, ai_write_status = [0, 0], [0, 0], [0, 0]
|
||||
while True:
|
||||
push_r = push_queue.get()
|
||||
if push_r is not None:
|
||||
# [(1, 原视频帧, 分析视频帧)]
|
||||
# [(code, retResults[2])]
|
||||
# [(2, 操作指令)]
|
||||
if push_r[0] == 1: # 视频帧操作
|
||||
frame_list, frame_index_list, all_frames = push_r[1]
|
||||
allowedList, rainbows, label_arrays, font_config = push_r[2]
|
||||
for i, frame in enumerate(frame_list):
|
||||
copy_frame = frame.copy()
|
||||
det_xywh = {}
|
||||
# 每帧可能存在多模型,多模型问题处理
|
||||
thread_p = []
|
||||
for det in push_r[3]:
|
||||
code, retResults = det
|
||||
det_xywh[code] = {}
|
||||
# 如果识别到了检测目标
|
||||
if len(retResults[i]) > 0:
|
||||
for qs in retResults[i]:
|
||||
detect_targets_code = int(qs[6])
|
||||
if detect_targets_code not in allowedList:
|
||||
logger.warning("当前检测目标不在检测目标中: {}, requestId: {}", detect_targets_code, request_id)
|
||||
continue
|
||||
score = qs[5]
|
||||
label_array = label_arrays[detect_targets_code]
|
||||
color = rainbows[detect_targets_code]
|
||||
if not isinstance(qs[1], (list, tuple, np.ndarray)):
|
||||
xc, yc, x2, y2 = int(qs[1]), int(qs[2]), int(qs[3]), int(qs[4])
|
||||
box = [(xc, yc), (x2, yc), (x2, y2), (xc, y2)]
|
||||
else:
|
||||
box = qs[1]
|
||||
# box, img, label_array, score=0.5, color=None, config=None
|
||||
dp = tt.submit(draw_painting_joint, box, copy_frame, label_array, score,
|
||||
color, font_config)
|
||||
thread_p.append(dp)
|
||||
cd = det_xywh[code].get(detect_targets_code)
|
||||
if cd is None:
|
||||
det_xywh[code][detect_targets_code] = [
|
||||
[detect_targets_code, box, score, label_array, color]]
|
||||
else:
|
||||
det_xywh[code][detect_targets_code].append(
|
||||
[detect_targets_code, box, score, label_array, color])
|
||||
if logo:
|
||||
frame = add_water_pic(frame, logo, request_id)
|
||||
copy_frame = add_water_pic(copy_frame, logo, request_id)
|
||||
if len(thread_p) > 0:
|
||||
completed_results = wait(thread_p, timeout=60, return_when=ALL_COMPLETED)
|
||||
completed_futures = completed_results.done
|
||||
for r in completed_futures:
|
||||
if r.exception():
|
||||
raise r.exception()
|
||||
frame_merge = video_conjuncing(frame, copy_frame)
|
||||
# 写原视频到本地
|
||||
write_or_video_result = t.submit(write_or_video, frame, orFilePath, or_video_file,
|
||||
or_write_status, request_id)
|
||||
# 写识别视频到本地
|
||||
write_ai_video_result = t.submit(write_ai_video, frame_merge, aiFilePath, ai_video_file,
|
||||
ai_write_status, request_id)
|
||||
if len(det_xywh) > 0:
|
||||
put_queue(image_queue, (1, (det_xywh, frame, frame_index_list[i], all_frames,
|
||||
font_config)))
|
||||
push_p = push_video_stream(frame_merge, push_p, push_url, p_push_status, request_id)
|
||||
ai_video_file = write_ai_video_result.result()
|
||||
or_video_file = write_or_video_result.result()
|
||||
if push_r[0] == 2:
|
||||
if 'stop' == push_r[1]:
|
||||
logger.info("停止推流线程, requestId: {}", request_id)
|
||||
close_all_p(push_p, or_video_file, ai_video_file, request_id)
|
||||
or_video_file, ai_video_file, push_p = None, None, None
|
||||
break
|
||||
except Exception as e:
|
||||
logger.error("推流线程异常:{}, requestId:{}", format_exc(), request_id)
|
||||
self.ex = e
|
||||
finally:
|
||||
close_all_p(push_p, or_video_file, ai_video_file, request_id)
|
||||
logger.info("推流线程停止完成!requestId:{}", request_id)
|
||||
|
||||
|
||||
# class OffPushStreamThread(Thread):
|
||||
# __slots__ = ('_msg', '_push_queue', '_context', 'ex', '_logo', '_image_queue')
|
||||
#
|
||||
# def __init__(self, *args):
|
||||
# super().__init__()
|
||||
# # 传参
|
||||
# self._msg, self._push_queue, self._image_queue, self._context = args
|
||||
# # 自带参数
|
||||
# self.ex = None
|
||||
# self._logo = None
|
||||
# if self._context["video"]["video_add_water"]:
|
||||
# self._logo = self._msg.get("logo_url")
|
||||
# if self._logo:
|
||||
# self._logo = url2Array(self._logo, enable_ex=False)
|
||||
# if not self._logo:
|
||||
# self._logo = cv2.imread(join(self._context['base_dir'], "image/logo.png"), -1)
|
||||
#
|
||||
# def run(self):
|
||||
# request_id, push_queue, image_queue = self._msg.get("request_id"), self._push_queue, self._image_queue
|
||||
# aiFilePath, logo = self._context.get("aiFilePath"), self._logo
|
||||
# ai_video_file, push_p = None, None
|
||||
# push_url = self._msg.get("push_url")
|
||||
# try:
|
||||
# logger.info("开始启动推流线程!requestId:{}", request_id)
|
||||
# with ThreadPoolExecutor(max_workers=1) as t:
|
||||
# p_push_status, or_write_status, ai_write_status = [0, 0], [0, 0], [0, 0]
|
||||
# while True:
|
||||
# push_parm = push_queue.get()
|
||||
# if push_parm is not None:
|
||||
# # [(1, 原视频帧, 分析视频帧)]
|
||||
# # # [视频帧、当前帧数、 总帧数、 [(问题数组、code、allowedList、label_arraylist、rainbows)]]
|
||||
# # res = (1, (pull_frame[1], pull_frame[2], pull_frame[3], []))
|
||||
# # [(2, 操作指令)]
|
||||
# if push_parm[0] == 1: # 视频帧操作
|
||||
# frame, current_frame, all_frames, ques_list = push_parm[1]
|
||||
# copy_frame = frame.copy()
|
||||
# det_xywh = {}
|
||||
# if len(ques_list) > 0:
|
||||
# for qs in ques_list:
|
||||
# det_xywh[qs[1]] = {}
|
||||
# detect_targets_code = int(qs[0][0])
|
||||
# score = qs[0][-1]
|
||||
# label_array = qs[3][detect_targets_code]
|
||||
# color = qs[4][detect_targets_code]
|
||||
# if not isinstance(qs[0][1], (list, tuple, np.ndarray)):
|
||||
# xc, yc, x2, y2 = int(qs[0][1]), int(qs[0][2]), int(qs[0][3]), int(qs[0][4])
|
||||
# box = [(xc, yc), (x2, yc), (x2, y2), (xc, y2)]
|
||||
# else:
|
||||
# box = qs[0][1]
|
||||
# draw_painting_joint(box, copy_frame, label_array, score, color, "leftTop")
|
||||
# cd = det_xywh[qs[1]].get(detect_targets_code)
|
||||
# if cd is None:
|
||||
# det_xywh[qs[1]][detect_targets_code] = [
|
||||
# [detect_targets_code, box, score, label_array, color]]
|
||||
# else:
|
||||
# det_xywh[qs[1]][detect_targets_code].append(
|
||||
# [detect_targets_code, box, score, label_array, color])
|
||||
# if logo:
|
||||
# frame = add_water_pic(frame, logo, request_id)
|
||||
# copy_frame = add_water_pic(copy_frame, logo, request_id)
|
||||
# frame_merge = video_conjuncing(frame, copy_frame)
|
||||
# # 写识别视频到本地
|
||||
# write_ai_video_result = t.submit(write_ai_video, frame_merge, aiFilePath, ai_video_file,
|
||||
# ai_write_status, request_id)
|
||||
# if len(det_xywh) > 0:
|
||||
# put_queue(image_queue, (1, (det_xywh, frame, current_frame, all_frames)))
|
||||
# push_p = push_video_stream(frame_merge, push_p, push_url, p_push_status, request_id)
|
||||
# ai_video_file = write_ai_video_result.result()
|
||||
# if push_parm[0] == 2:
|
||||
# if 'stop' == push_parm[1]:
|
||||
# logger.info("停止推流线程, requestId: {}", request_id)
|
||||
# close_all_p(push_p, None, ai_video_file, request_id)
|
||||
# ai_video_file, push_p = None, None
|
||||
# break
|
||||
# except Exception as e:
|
||||
# logger.error("推流线程异常:{}, requestId:{}", format_exc(), request_id)
|
||||
# self.ex = e
|
||||
# finally:
|
||||
# close_all_p(push_p, None, ai_video_file, request_id)
|
||||
# logger.info("推流线程停止完成!requestId:{}", request_id)
|
||||
|
|
@ -0,0 +1,553 @@
|
|||
#ne -*- coding: utf-8 -*-
|
||||
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from multiprocessing import Process
|
||||
from os import getpid
|
||||
import os
|
||||
|
||||
from os.path import join
|
||||
from time import time, sleep
|
||||
from traceback import format_exc
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
import psutil
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from enums.ExceptionEnum import ExceptionType
|
||||
from enums.ModelTypeEnum import ModelType
|
||||
from exception.CustomerException import ServiceException
|
||||
from util import ImageUtils
|
||||
from util.Cv2Utils import video_conjuncing, write_or_video, write_ai_video, push_video_stream, close_all_p
|
||||
from util.ImageUtils import url2Array, add_water_pic
|
||||
from util.LogUtils import init_log
|
||||
|
||||
from util.PlotsUtils import draw_painting_joint, filterBox, xywh2xyxy2, xy2xyxy, draw_name_joint, plot_one_box_auto, draw_name_ocr,draw_name_crowd
|
||||
|
||||
from util.QueUtil import get_no_block_queue, put_queue, clear_queue
|
||||
|
||||
|
||||
class PushStreamProcess(Process):
|
||||
__slots__ = ("_msg", "_push_queue", "_image_queue", '_push_ex_queue', '_hb_queue', "_context")
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
# 传参
|
||||
self._msg, self._push_queue, self._image_queue, self._push_ex_queue, self._hb_queue, self._context = args
|
||||
self._algStatus = False # 默认关闭
|
||||
self._algSwitch = self._context['service']['algSwitch']
|
||||
|
||||
|
||||
#0521:
|
||||
default_enabled = str(self._msg.get("defaultEnabled", "True")).lower() == "true"
|
||||
if default_enabled:
|
||||
print("执行默认程序(defaultEnabled=True)")
|
||||
self._algSwitch = True
|
||||
# 这里放默认逻辑的代码
|
||||
else:
|
||||
print("执行替代程序(defaultEnabled=False)")
|
||||
# 这里放非默认逻辑的代码
|
||||
self._algSwitch = False
|
||||
|
||||
print("---line53 :PushVideoStreamProcess.py---",self._algSwitch)
|
||||
|
||||
def build_logo_url(self):
|
||||
logo = None
|
||||
if self._context["video"]["video_add_water"]:
|
||||
logo = self._msg.get("logo_url")
|
||||
if logo:
|
||||
logo = url2Array(logo, enable_ex=False)
|
||||
if logo is None:
|
||||
logo = cv2.imread(join(self._context['base_dir'], "image/logo.png"), -1)
|
||||
self._context["logo"] = logo
|
||||
|
||||
@staticmethod
|
||||
def handle_image(det_xywh, det, frame_score, copy_frame, draw_config, code_list):
|
||||
code, det_result = det
|
||||
# 每个单独模型处理
|
||||
# 模型编号、100帧的所有问题, 检测目标、颜色、文字图片
|
||||
if len(det_result) > 0:
|
||||
font_config, allowedList = draw_config["font_config"], draw_config[code]["allowedList"]
|
||||
rainbows, label_arrays = draw_config[code]["rainbows"], draw_config[code]["label_arrays"]
|
||||
for qs in det_result:
|
||||
box, score, cls = xywh2xyxy2(qs)
|
||||
if cls not in allowedList or score < frame_score:
|
||||
continue
|
||||
label_array, color = label_arrays[cls], rainbows[cls]
|
||||
draw_painting_joint(box, copy_frame, label_array, score, color, font_config)
|
||||
if det_xywh.get(code) is None:
|
||||
det_xywh[code], code_list[code] = {}, {}
|
||||
cd = det_xywh[code].get(cls)
|
||||
if cd is None:
|
||||
code_list[code][cls] = 1
|
||||
det_xywh[code][cls] = [[cls, box, score, label_array, color]]
|
||||
else:
|
||||
code_list[code][cls] += 1
|
||||
det_xywh[code][cls].append([cls, box, score, label_array, color])
|
||||
|
||||
|
||||
class OnPushStreamProcess(PushStreamProcess):
|
||||
__slots__ = ()
|
||||
|
||||
def run(self):
|
||||
self.build_logo_url()
|
||||
msg, context = self._msg, self._context
|
||||
base_dir, env, orFilePath, aiFilePath, logo, service_timeout, frame_score = context["base_dir"], \
|
||||
context['env'], context["orFilePath"], context["aiFilePath"], context["logo"], \
|
||||
int(context["service"]["timeout"]) + 120, context["service"]["filter"]["frame_score"]
|
||||
request_id, push_url = msg["request_id"], msg["push_url"]
|
||||
push_queue, image_queue, push_ex_queue, hb_queue = self._push_queue, self._image_queue, self._push_ex_queue, \
|
||||
self._hb_queue
|
||||
or_video_file, ai_video_file, push_p, ex = None, None, None, None
|
||||
ex_status = True
|
||||
# 图片相似度开关
|
||||
picture_similarity = bool(context["service"]["filter"]["picture_similarity"])
|
||||
qs_np_tmp = None
|
||||
pix_dis = 60
|
||||
try:
|
||||
init_log(base_dir, env)
|
||||
logger.info("开始实时启动推流进程!requestId:{},pid:{}, ppid:{}", request_id,os.getpid(),os.getppid())
|
||||
with ThreadPoolExecutor(max_workers=2) as t:
|
||||
# 定义三种推流、写原视频流、写ai视频流策略
|
||||
# 第一个参数时间, 第二个参数重试次数
|
||||
p_push_status, or_write_status, ai_write_status = [0, 0], [0, 0], [0, 0]
|
||||
start_time = time()
|
||||
while True:
|
||||
# 检测推流执行超时时间, 1.防止任务运行超时 2.主进程挂了,子进程运行超时
|
||||
if time() - start_time > service_timeout:
|
||||
logger.error("推流超时, requestId: {}", request_id)
|
||||
raise ServiceException(ExceptionType.TASK_EXCUTE_TIMEOUT.value[0],
|
||||
ExceptionType.TASK_EXCUTE_TIMEOUT.value[1])
|
||||
# 系统由于各种问题可能会杀死内存使用多的进程, 自己杀掉自己
|
||||
if psutil.Process(getpid()).ppid() == 1:
|
||||
logger.info("推流进程检测到父进程异常停止, 自动停止推流进程, requestId: {}", request_id)
|
||||
ex_status = False
|
||||
for q in [push_queue, image_queue, push_ex_queue, hb_queue]:
|
||||
clear_queue(q)
|
||||
break
|
||||
# 获取推流的视频帧
|
||||
push_r = get_no_block_queue(push_queue)
|
||||
if push_r is not None:
|
||||
if push_r[0] == 1:
|
||||
frame_list, frame_index_list, all_frames, draw_config, push_objs = push_r[1]
|
||||
for i, frame in enumerate(frame_list):
|
||||
pix_dis = int((frame.shape[0]//10)*1.2)
|
||||
# 复制帧用来画图
|
||||
copy_frame = frame.copy()
|
||||
det_xywh, thread_p = {}, []
|
||||
det_xywh2 = {}
|
||||
# 所有问题的矩阵集合
|
||||
qs_np = None
|
||||
qs_reurn = []
|
||||
for det in push_objs[i]:
|
||||
code, det_result = det
|
||||
# 每个单独模型处理
|
||||
# 模型编号、100帧的所有问题, 检测目标、颜色、文字图片
|
||||
if len(det_result) > 0:
|
||||
font_config, allowedList = draw_config["font_config"], draw_config[code]["allowedList"]
|
||||
rainbows, label_arrays = draw_config[code]["rainbows"], draw_config[code]["label_arrays"]
|
||||
for qs in det_result:
|
||||
# 自研车牌模型处理
|
||||
if ModelType.CITY_CARPLATE_MODEL.value[1] == str(code):
|
||||
cls = 0
|
||||
box = xy2xyxy(qs[1])
|
||||
score = None
|
||||
color = rainbows[cls]
|
||||
label_array = None
|
||||
rr = t.submit(draw_name_ocr, qs, copy_frame, color)
|
||||
elif ModelType.CITY_DENSECROWDCOUNT_MODEL.value[1] == str(code) or\
|
||||
ModelType.CITY_UNDERBUILDCOUNT_MODEL.value[1] == str(code):
|
||||
cls = 0
|
||||
# crowdlabel, points = qs
|
||||
box = [(0, 0), (0, 0), (0, 0), (0, 0)]
|
||||
score = None
|
||||
color = rainbows[cls]
|
||||
label_array = None
|
||||
rr = t.submit(draw_name_crowd, qs, copy_frame, color)
|
||||
else:
|
||||
try: # 应对NaN情况
|
||||
box, score, cls = xywh2xyxy2(qs)
|
||||
except:
|
||||
continue
|
||||
if cls not in allowedList or score < frame_score:
|
||||
continue
|
||||
label_array, color = label_arrays[cls], rainbows[cls]
|
||||
if ModelType.CHANNEL2_MODEL.value[1] == str(code) and cls == 2:
|
||||
rr = t.submit(draw_name_joint, box, copy_frame,
|
||||
draw_config[code]["label_dict"], score, color,
|
||||
font_config, qs[6])
|
||||
else:
|
||||
rr = t.submit(draw_painting_joint, box, copy_frame, label_array,
|
||||
score, color, font_config)
|
||||
|
||||
thread_p.append(rr)
|
||||
if det_xywh.get(code) is None:
|
||||
det_xywh[code] = {}
|
||||
cd = det_xywh[code].get(cls)
|
||||
if not (ModelType.CHANNEL2_MODEL.value[1] == str(code) and cls == 2):
|
||||
if cd is None:
|
||||
det_xywh[code][cls] = [[cls, box, score, label_array, color]]
|
||||
else:
|
||||
det_xywh[code][cls].append([cls, box, score, label_array, color])
|
||||
if qs_np is None:
|
||||
qs_np = np.array([box[0][0], box[0][1], box[1][0], box[1][1],
|
||||
box[2][0], box[2][1], box[3][0], box[3][1],
|
||||
score, cls, code],dtype=np.float32)
|
||||
else:
|
||||
result_li = np.array([box[0][0], box[0][1], box[1][0], box[1][1],
|
||||
box[2][0], box[2][1], box[3][0], box[3][1],
|
||||
score, cls, code],dtype=np.float32)
|
||||
qs_np = np.row_stack((qs_np, result_li))
|
||||
|
||||
if logo:
|
||||
frame = add_water_pic(frame, logo, request_id)
|
||||
copy_frame = add_water_pic(copy_frame, logo, request_id)
|
||||
if len(thread_p) > 0:
|
||||
for r in thread_p:
|
||||
r.result()
|
||||
#print('----line173:',self._algSwitch,self._algStatus)
|
||||
if self._algSwitch and (not self._algStatus):
|
||||
frame_merge = video_conjuncing(frame, frame.copy())
|
||||
else:
|
||||
frame_merge = video_conjuncing(frame, copy_frame)
|
||||
# 写原视频到本地
|
||||
write_or_video_result = t.submit(write_or_video, frame, orFilePath, or_video_file,
|
||||
or_write_status, request_id)
|
||||
# 写识别视频到本地
|
||||
write_ai_video_result = t.submit(write_ai_video, frame_merge, aiFilePath,
|
||||
ai_video_file, ai_write_status, request_id)
|
||||
push_stream_result = t.submit(push_video_stream, frame_merge, push_p, push_url,
|
||||
p_push_status, request_id)
|
||||
# 如果有问题, 走下面的逻辑
|
||||
if qs_np is not None:
|
||||
if len(qs_np.shape) == 1:
|
||||
qs_np = qs_np[np.newaxis,...]
|
||||
qs_np_id = qs_np.copy()
|
||||
b = np.ones(qs_np_id.shape[0])
|
||||
qs_np_id = np.column_stack((qs_np_id,b))
|
||||
if qs_np_tmp is None:
|
||||
if picture_similarity:
|
||||
qs_np_tmp = qs_np_id.copy()
|
||||
b = np.zeros(qs_np.shape[0])
|
||||
qs_reurn = np.column_stack((qs_np,b))
|
||||
else:
|
||||
qs_reurn = filterBox(qs_np, qs_np_tmp, pix_dis)
|
||||
if picture_similarity:
|
||||
qs_np_tmp = np.append(qs_np_tmp,qs_np_id,axis=0)
|
||||
qs_np_tmp[:, 11] += 1
|
||||
qs_np_tmp = np.delete(qs_np_tmp, np.where((qs_np_tmp[:, 11] >= 75))[0], axis=0)
|
||||
has = False
|
||||
new_lab = []
|
||||
for j in qs_reurn:
|
||||
if j[11] == 1:
|
||||
has = True
|
||||
new_lab.append(j[9])
|
||||
if has:
|
||||
for q in qs_reurn:
|
||||
if q[11] >= 1:
|
||||
cls = int(q[9])
|
||||
if not (cls in new_lab):
|
||||
continue # 为了防止其他类别被带出
|
||||
code = str(int(q[10])).zfill(3)
|
||||
if det_xywh2.get(code) is None:
|
||||
det_xywh2[code] = {}
|
||||
cd = det_xywh2[code].get(cls)
|
||||
score = q[8]
|
||||
rainbows, label_arrays = draw_config[code]["rainbows"], draw_config[code]["label_arrays"]
|
||||
label_array, color = label_arrays[cls], rainbows[cls]
|
||||
box = [(int(q[0]), int(q[1])), (int(q[2]), int(q[3])),
|
||||
(int(q[4]), int(q[5])), (int(q[6]), int(q[7]))]
|
||||
is_new = False
|
||||
if q[11] == 1:
|
||||
is_new = True
|
||||
if ModelType.CITY_CARPLATE_MODEL.value[1] == str(code) or \
|
||||
ModelType.CITY_DENSECROWDCOUNT_MODEL.value[1] == str(code) or\
|
||||
ModelType.CITY_UNDERBUILDCOUNT_MODEL.value[1] == str(code):
|
||||
box = qs
|
||||
if cd is None:
|
||||
det_xywh2[code][cls] = [[cls, box, score, label_array, color, is_new]]
|
||||
else:
|
||||
det_xywh2[code][cls].append(
|
||||
[cls, box, score, label_array, color, is_new])
|
||||
if len(det_xywh2) > 0:
|
||||
put_queue(image_queue, (1, [det_xywh2, frame, frame_index_list[i], all_frames,
|
||||
draw_config["font_config"]]))
|
||||
|
||||
push_p = push_stream_result.result(timeout=60)
|
||||
ai_video_file = write_ai_video_result.result(timeout=60)
|
||||
or_video_file = write_or_video_result.result(timeout=60)
|
||||
# 接收停止指令
|
||||
if push_r[0] == 2:
|
||||
logger.info("拉流进程收到控制命令为:{}, requestId: {}",push_r[1] ,request_id)
|
||||
if 'algStart' == push_r[1]: self._algStatus = True;logger.info("算法识别开启, requestId: {}", request_id)
|
||||
if 'algStop' == push_r[1]: self._algStatus = False;logger.info("算法识别关闭, requestId: {}", request_id)
|
||||
if 'stop' == push_r[1]:
|
||||
logger.info("停止推流进程, requestId: {}", request_id)
|
||||
break
|
||||
if 'stop_ex' == push_r[1]:
|
||||
ex_status = False
|
||||
logger.info("停止推流进程, requestId: {}", request_id)
|
||||
break
|
||||
|
||||
del push_r
|
||||
else:
|
||||
sleep(1)
|
||||
except ServiceException as s:
|
||||
logger.error("推流进程异常:{}, requestId:{}", s.msg, request_id)
|
||||
ex = s.code, s.msg
|
||||
except Exception:
|
||||
logger.error("推流进程异常:{}, requestId:{}", format_exc(), request_id)
|
||||
ex = ExceptionType.SERVICE_INNER_EXCEPTION.value[0], ExceptionType.SERVICE_INNER_EXCEPTION.value[1]
|
||||
finally:
|
||||
# 关闭推流管, 原视频写对象, 分析视频写对象
|
||||
close_all_p(push_p, or_video_file, ai_video_file, request_id)
|
||||
if ex:
|
||||
code, msg = ex
|
||||
put_queue(push_ex_queue, (1, code, msg), timeout=2)
|
||||
else:
|
||||
if ex_status:
|
||||
# 关闭推流的时候, 等待1分钟图片队列处理完,如果1分钟内没有处理完, 清空图片队列, 丢弃没有上传的图片
|
||||
c_time = time()
|
||||
while time() - c_time < 60:
|
||||
if image_queue.qsize() == 0 or image_queue.empty():
|
||||
break
|
||||
sleep(2)
|
||||
for q in [push_queue, image_queue, hb_queue]:
|
||||
clear_queue(q)
|
||||
logger.info("推流进程停止完成!图片队列大小: {}, requestId:{}", image_queue.qsize(), request_id)
|
||||
|
||||
|
||||
class OffPushStreamProcess(PushStreamProcess):
|
||||
__slots__ = ()
|
||||
|
||||
def run(self):
|
||||
self.build_logo_url()
|
||||
msg, context = self._msg, self._context
|
||||
request_id = msg["request_id"]
|
||||
base_dir, env = context["base_dir"], context['env']
|
||||
push_queue, image_queue, push_ex_queue, hb_queue = self._push_queue, self._image_queue, self._push_ex_queue, \
|
||||
self._hb_queue
|
||||
aiFilePath, logo = context["aiFilePath"], context["logo"]
|
||||
ai_video_file, push_p, push_url = None, None, msg["push_url"]
|
||||
service_timeout = int(context["service"]["timeout"]) + 120
|
||||
frame_score = context["service"]["filter"]["frame_score"]
|
||||
ex = None
|
||||
ex_status = True
|
||||
# 图片相似度开关
|
||||
picture_similarity = bool(context["service"]["filter"]["picture_similarity"])
|
||||
qs_np_tmp = None
|
||||
pix_dis = 60
|
||||
if msg['taskType']==0: self._algStatus = False
|
||||
else: self._algStatus = True
|
||||
try:
|
||||
init_log(base_dir, env)
|
||||
logger.info("开始启动离线推流进程!requestId:{}", request_id)
|
||||
with ThreadPoolExecutor(max_workers=2) as t:
|
||||
# 定义三种推流、写原视频流、写ai视频流策略
|
||||
# 第一个参数时间, 第二个参数重试次数
|
||||
p_push_status, ai_write_status = [0, 0], [0, 0]
|
||||
start_time = time()
|
||||
while True:
|
||||
# 检测推流执行超时时间
|
||||
if time() - start_time > service_timeout:
|
||||
logger.error("离线推流超时, requestId: {}", request_id)
|
||||
raise ServiceException(ExceptionType.TASK_EXCUTE_TIMEOUT.value[0],
|
||||
ExceptionType.TASK_EXCUTE_TIMEOUT.value[1])
|
||||
# 系统由于各种问题可能会杀死内存使用多的进程, 自己杀掉自己
|
||||
if psutil.Process(getpid()).ppid() == 1:
|
||||
logger.info("离线推流进程检测到父进程异常停止, 自动停止推流进程, requestId: {}", request_id)
|
||||
ex_status = False
|
||||
for q in [push_queue, image_queue, push_ex_queue, hb_queue]:
|
||||
clear_queue(q)
|
||||
break
|
||||
# 获取推流的视频帧
|
||||
push_r = get_no_block_queue(push_queue)
|
||||
if push_r is not None:
|
||||
# [(1, ...] 视频帧操作
|
||||
# [(2, 操作指令)] 指令操作
|
||||
if push_r[0] == 1:
|
||||
frame_list, frame_index_list, all_frames, draw_config, push_objs = push_r[1]
|
||||
# 处理每一帧图片
|
||||
for i, frame in enumerate(frame_list):
|
||||
pix_dis = int((frame.shape[0]//10)*1.2)
|
||||
if frame_index_list[i] % 300 == 0 and frame_index_list[i] <= all_frames:
|
||||
task_process = "%.2f" % (float(frame_index_list[i]) / float(all_frames))
|
||||
put_queue(hb_queue, {"hb_value": task_process}, timeout=2)
|
||||
# 复制帧用来画图
|
||||
copy_frame = frame.copy()
|
||||
# 所有问题记录字典
|
||||
det_xywh, thread_p = {}, []
|
||||
det_xywh2 = {}
|
||||
# 所有问题的矩阵集合
|
||||
qs_np = None
|
||||
qs_reurn = []
|
||||
for det in push_objs[i]:
|
||||
code, det_result = det
|
||||
|
||||
# 每个单独模型处理
|
||||
# 模型编号、100帧的所有问题, 检测目标、颜色、文字图片
|
||||
if len(det_result) > 0:
|
||||
font_config, allowedList = draw_config["font_config"], draw_config[code]["allowedList"]
|
||||
rainbows, label_arrays = draw_config[code]["rainbows"], draw_config[code]["label_arrays"]
|
||||
for qs in det_result:
|
||||
# 自研车牌模型处理
|
||||
if ModelType.CITY_CARPLATE_MODEL.value[1] == str(code):
|
||||
cls = 0
|
||||
box = xy2xyxy(qs[1])
|
||||
score = None
|
||||
color = rainbows[cls]
|
||||
label_array = None
|
||||
label_arrays = [None]
|
||||
rr = t.submit(draw_name_ocr, qs, copy_frame, color)
|
||||
|
||||
elif ModelType.CITY_DENSECROWDCOUNT_MODEL.value[1] == str(code) or\
|
||||
ModelType.CITY_UNDERBUILDCOUNT_MODEL.value[1] == str(code):
|
||||
cls = 0
|
||||
box = [(0,0),(0,0),(0,0),(0,0)]
|
||||
score = None
|
||||
color = rainbows[cls]
|
||||
label_array = None
|
||||
rr = t.submit(draw_name_crowd, qs, copy_frame, color)
|
||||
|
||||
else:
|
||||
box, score, cls = xywh2xyxy2(qs)
|
||||
if cls not in allowedList or score < frame_score:
|
||||
continue
|
||||
label_array, color = label_arrays[cls], rainbows[cls]
|
||||
if ModelType.CHANNEL2_MODEL.value[1] == str(code) and cls == 2:
|
||||
rr = t.submit(draw_name_joint, box, copy_frame, draw_config[code]["label_dict"], score, color, font_config, qs[6])
|
||||
else:
|
||||
rr = t.submit(draw_painting_joint, box, copy_frame, label_array, score, color, font_config)
|
||||
|
||||
thread_p.append(rr)
|
||||
|
||||
if det_xywh.get(code) is None:
|
||||
det_xywh[code] = {}
|
||||
cd = det_xywh[code].get(cls)
|
||||
if not (ModelType.CHANNEL2_MODEL.value[1] == str(code) and cls == 2):
|
||||
if cd is None:
|
||||
det_xywh[code][cls] = [[cls, box, score, label_array, color]]
|
||||
else:
|
||||
det_xywh[code][cls].append([cls, box, score, label_array, color])
|
||||
if qs_np is None:
|
||||
qs_np = np.array([box[0][0], box[0][1], box[1][0], box[1][1],
|
||||
box[2][0], box[2][1], box[3][0], box[3][1],
|
||||
score, cls, code],dtype=np.float32)
|
||||
else:
|
||||
result_li = np.array([box[0][0], box[0][1], box[1][0], box[1][1],
|
||||
box[2][0], box[2][1], box[3][0], box[3][1],
|
||||
score, cls, code],dtype=np.float32)
|
||||
qs_np = np.row_stack((qs_np, result_li))
|
||||
|
||||
if logo:
|
||||
frame = add_water_pic(frame, logo, request_id)
|
||||
copy_frame = add_water_pic(copy_frame, logo, request_id)
|
||||
if len(thread_p) > 0:
|
||||
for r in thread_p:
|
||||
r.result()
|
||||
if self._algSwitch and (not self._algStatus):
|
||||
frame_merge = video_conjuncing(frame, frame.copy())
|
||||
else:
|
||||
frame_merge = video_conjuncing(frame, copy_frame)
|
||||
# 写识别视频到本地
|
||||
write_ai_video_result = t.submit(write_ai_video, frame_merge, aiFilePath,
|
||||
ai_video_file,
|
||||
ai_write_status, request_id)
|
||||
push_stream_result = t.submit(push_video_stream, frame_merge, push_p, push_url,
|
||||
p_push_status, request_id)
|
||||
|
||||
if qs_np is not None:
|
||||
if len(qs_np.shape) == 1:
|
||||
qs_np = qs_np[np.newaxis,...]
|
||||
qs_np_id = qs_np.copy()
|
||||
b = np.ones(qs_np_id.shape[0])
|
||||
qs_np_id = np.column_stack((qs_np_id,b))
|
||||
if qs_np_tmp is None:
|
||||
if picture_similarity:
|
||||
qs_np_tmp = qs_np_id.copy()
|
||||
b = np.zeros(qs_np.shape[0])
|
||||
qs_reurn = np.column_stack((qs_np,b))
|
||||
else:
|
||||
qs_reurn = filterBox(qs_np, qs_np_tmp, pix_dis)
|
||||
if picture_similarity:
|
||||
qs_np_tmp = np.append(qs_np_tmp,qs_np_id,axis=0)
|
||||
qs_np_tmp[:, 11] += 1
|
||||
qs_np_tmp = np.delete(qs_np_tmp, np.where((qs_np_tmp[:, 11] >= 75))[0], axis=0)
|
||||
has = False
|
||||
new_lab = []
|
||||
|
||||
for j in qs_reurn:
|
||||
if j[11] == 1:
|
||||
has = True
|
||||
new_lab.append(j[9])
|
||||
if has:
|
||||
for q in qs_reurn:
|
||||
if q[11] >= 1:
|
||||
cls = int(q[9])
|
||||
if not (cls in new_lab):
|
||||
continue # 为了防止其他类别被带出
|
||||
code = str(int(q[10])).zfill(3)
|
||||
if det_xywh2.get(code) is None:
|
||||
det_xywh2[code] = {}
|
||||
cd = det_xywh2[code].get(cls)
|
||||
score = q[8]
|
||||
rainbows, label_arrays = draw_config[code]["rainbows"], draw_config[code]["label_arrays"]
|
||||
label_array, color = label_arrays[cls], rainbows[cls]
|
||||
box = [(int(q[0]), int(q[1])), (int(q[2]), int(q[3])),
|
||||
(int(q[4]), int(q[5])), (int(q[6]), int(q[7]))]
|
||||
is_new = False
|
||||
if q[11] == 1:
|
||||
is_new = True
|
||||
|
||||
if ModelType.CITY_CARPLATE_MODEL.value[1] == str(code) or \
|
||||
ModelType.CITY_DENSECROWDCOUNT_MODEL.value[1] == str(code) or\
|
||||
ModelType.CITY_UNDERBUILDCOUNT_MODEL.value[1] == str(code):
|
||||
box = qs
|
||||
if cd is None:
|
||||
det_xywh2[code][cls] = [[cls, box, score, label_array, color, is_new]]
|
||||
else:
|
||||
det_xywh2[code][cls].append(
|
||||
[cls, box, score, label_array, color, is_new])
|
||||
if len(det_xywh2) > 0:
|
||||
put_queue(image_queue, (1, [det_xywh2, frame, frame_index_list[i], all_frames, draw_config["font_config"]]))
|
||||
push_p = push_stream_result.result(timeout=60)
|
||||
ai_video_file = write_ai_video_result.result(timeout=60)
|
||||
# 接收停止指令
|
||||
if push_r[0] == 2:
|
||||
logger.info("拉流进程收到控制命令为:{}, requestId: {}",push_r[1] ,request_id)
|
||||
if 'algStart' == push_r[1]: self._algStatus = True;logger.info("算法识别开启, requestId: {}", request_id)
|
||||
if 'algStop' == push_r[1]: self._algStatus = False;logger.info("算法识别关闭, requestId: {}", request_id)
|
||||
if 'stop' == push_r[1]:
|
||||
logger.info("停止推流进程, requestId: {}", request_id)
|
||||
break
|
||||
if 'stop_ex' == push_r[1]:
|
||||
logger.info("停止推流进程, requestId: {}", request_id)
|
||||
ex_status = False
|
||||
break
|
||||
del push_r
|
||||
else:
|
||||
sleep(1)
|
||||
except ServiceException as s:
|
||||
logger.error("推流进程异常:{}, requestId:{}", s.msg, request_id)
|
||||
ex = s.code, s.msg
|
||||
except Exception:
|
||||
logger.error("推流进程异常:{}, requestId:{}", format_exc(), request_id)
|
||||
ex = ExceptionType.SERVICE_INNER_EXCEPTION.value[0], ExceptionType.SERVICE_INNER_EXCEPTION.value[1]
|
||||
finally:
|
||||
# 关闭推流管, 分析视频写对象
|
||||
close_all_p(push_p, None, ai_video_file, request_id)
|
||||
if ex:
|
||||
code, msg = ex
|
||||
put_queue(push_ex_queue, (1, code, msg), timeout=2)
|
||||
else:
|
||||
if ex_status:
|
||||
# 关闭推流的时候, 等待1分钟图片队列处理完,如果1分钟内没有处理完, 清空图片队列, 丢弃没有上传的图片
|
||||
c_time = time()
|
||||
while time() - c_time < 60:
|
||||
if image_queue.qsize() == 0 or image_queue.empty():
|
||||
break
|
||||
sleep(2)
|
||||
for q in [push_queue, image_queue, hb_queue]:
|
||||
clear_queue(q)
|
||||
logger.info("推流进程停止完成!requestId:{}", request_id)
|
||||
|
|
@ -0,0 +1,356 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from multiprocessing import Process
|
||||
from os import getpid
|
||||
|
||||
from os.path import join
|
||||
from time import time, sleep
|
||||
from traceback import format_exc
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
import psutil
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from enums.ExceptionEnum import ExceptionType
|
||||
from exception.CustomerException import ServiceException
|
||||
from util import ImageUtils
|
||||
from util.Cv2Utils import video_conjuncing, write_or_video, write_ai_video, push_video_stream, close_all_p
|
||||
from util.ImageUtils import url2Array, add_water_pic
|
||||
from util.LogUtils import init_log
|
||||
|
||||
from util.PlotsUtils import draw_painting_joint, filterBox, xywh2xyxy2
|
||||
|
||||
from util.QueUtil import get_no_block_queue, put_queue, clear_queue
|
||||
|
||||
|
||||
class PushStreamProcess2(Process):
|
||||
__slots__ = ("_msg", "_push_queue", "_image_queue", '_push_ex_queue', '_hb_queue', "_context")
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
# 传参
|
||||
self._msg, self._push_queue, self._image_queue, self._push_ex_queue, self._hb_queue, self._context = args
|
||||
|
||||
def build_logo_url(self):
|
||||
logo = None
|
||||
if self._context["video"]["video_add_water"]:
|
||||
logo = self._msg.get("logo_url")
|
||||
if logo:
|
||||
logo = url2Array(logo, enable_ex=False)
|
||||
if logo is None:
|
||||
logo = cv2.imread(join(self._context['base_dir'], "image/logo.png"), -1)
|
||||
self._context["logo"] = logo
|
||||
|
||||
|
||||
class OnPushStreamProcess2(PushStreamProcess2):
|
||||
__slots__ = ()
|
||||
|
||||
def run(self):
|
||||
msg, context = self._msg, self._context
|
||||
self.build_logo_url()
|
||||
request_id = msg["request_id"]
|
||||
base_dir, env = context["base_dir"], context['env']
|
||||
push_queue, image_queue, push_ex_queue, hb_queue = self._push_queue, self._image_queue, self._push_ex_queue, \
|
||||
self._hb_queue
|
||||
orFilePath, aiFilePath, logo = context["orFilePath"], context["aiFilePath"], context["logo"]
|
||||
or_video_file, ai_video_file, push_p, push_url = None, None, None, msg["push_url"]
|
||||
service_timeout = int(context["service"]["timeout"]) + 120
|
||||
frame_score = context["service"]["filter"]["frame_score"]
|
||||
ex = None
|
||||
ex_status = True
|
||||
try:
|
||||
init_log(base_dir, env)
|
||||
logger.info("开始启动推流进程!requestId:{}", request_id)
|
||||
with ThreadPoolExecutor(max_workers=3) as t:
|
||||
# 定义三种推流、写原视频流、写ai视频流策略
|
||||
# 第一个参数时间, 第二个参数重试次数
|
||||
p_push_status, or_write_status, ai_write_status = [0, 0], [0, 0], [0, 0]
|
||||
start_time = time()
|
||||
minID = 0
|
||||
maxID = 0
|
||||
while True:
|
||||
# 检测推流执行超时时间
|
||||
if time() - start_time > service_timeout:
|
||||
logger.error("推流超时, requestId: {}", request_id)
|
||||
raise ServiceException(ExceptionType.PUSH_STREAM_TIMEOUT_EXCEPTION.value[0],
|
||||
ExceptionType.PUSH_STREAM_TIMEOUT_EXCEPTION.value[1])
|
||||
# 系统由于各种问题可能会杀死内存使用多的进程, 自己杀掉自己
|
||||
if psutil.Process(getpid()).ppid() == 1:
|
||||
ex_status = False
|
||||
logger.info("推流进程检测到父进程异常停止, 自动停止推流进程, requestId: {}", request_id)
|
||||
for q in [push_queue, image_queue, push_ex_queue, hb_queue]:
|
||||
clear_queue(q)
|
||||
break
|
||||
# 获取推流的视频帧
|
||||
push_r = get_no_block_queue(push_queue)
|
||||
if push_r is not None:
|
||||
# [(1, ...] 视频帧操作
|
||||
# [(2, 操作指令)] 指令操作
|
||||
if push_r[0] == 1:
|
||||
# 如果是多模型push_objs数组可能包含[模型1识别数组, 模型2识别数组, 模型3识别数组]
|
||||
frame_list, frame_index_list, all_frames, draw_config, push_objs = push_r[1]
|
||||
# 处理每一帧图片
|
||||
for i, frame in enumerate(frame_list):
|
||||
# 复制帧用来画图
|
||||
copy_frame = frame.copy()
|
||||
# 所有问题记录字典
|
||||
det_xywh, thread_p = {}, []
|
||||
det_tmp = {}
|
||||
det_xywh2 = {}
|
||||
|
||||
# [模型1识别数组, 模型2识别数组, 模型3识别数组]
|
||||
for s_det_list in push_objs:
|
||||
code, det_result = s_det_list[0], s_det_list[1][i]
|
||||
if len(det_result) > 0:
|
||||
font_config, allowedList = draw_config["font_config"], draw_config[code]["allowedList"]
|
||||
rainbows, label_arrays = draw_config[code]["rainbows"], draw_config[code]["label_arrays"]
|
||||
for qs in det_result:
|
||||
box, score, cls = xywh2xyxy2(qs)
|
||||
if cls not in allowedList or score < frame_score:
|
||||
continue
|
||||
label_array, color = label_arrays[cls], rainbows[cls]
|
||||
rr = t.submit(draw_painting_joint, box, copy_frame, label_array, score, color, font_config)
|
||||
thread_p.append(rr)
|
||||
if det_xywh.get(code) is None:
|
||||
det_xywh[code] = {}
|
||||
cd = det_xywh[code].get(cls)
|
||||
is_new = False
|
||||
if len(qs) == 8:
|
||||
trackId = qs[7]
|
||||
elif len(qs) == 5:
|
||||
trackId = qs[4]
|
||||
if trackId > minID:
|
||||
is_new = True
|
||||
if det_tmp.get(code) is None:
|
||||
det_tmp[code] = [cls]
|
||||
else:
|
||||
if not (cls in det_tmp[code]):
|
||||
det_tmp[code].append(cls)
|
||||
qs_tmp = [cls, box, score, label_array, color, is_new]
|
||||
if trackId > maxID:
|
||||
maxID = trackId
|
||||
if cd is None:
|
||||
det_xywh[code][cls] = [qs_tmp]
|
||||
else:
|
||||
det_xywh[code][cls].append(qs_tmp)
|
||||
minID = maxID
|
||||
if logo:
|
||||
frame = add_water_pic(frame, logo, request_id)
|
||||
copy_frame = add_water_pic(copy_frame, logo, request_id)
|
||||
if len(thread_p) > 0:
|
||||
for r in thread_p:
|
||||
r.result()
|
||||
frame_merge = video_conjuncing(frame, copy_frame)
|
||||
# 写原视频到本地
|
||||
write_or_video_result = t.submit(write_or_video, frame, orFilePath, or_video_file,
|
||||
or_write_status, request_id)
|
||||
# 写识别视频到本地
|
||||
write_ai_video_result = t.submit(write_ai_video, frame_merge, aiFilePath,
|
||||
ai_video_file, ai_write_status, request_id)
|
||||
push_p_result = t.submit(push_video_stream, frame_merge, push_p, push_url,
|
||||
p_push_status,
|
||||
request_id)
|
||||
if det_xywh:
|
||||
for index, (key, value) in enumerate(det_xywh.items()):
|
||||
for k in value.keys():
|
||||
if (key in det_tmp.keys()) and (k in det_tmp[key]):
|
||||
det_xywh2[key] = {}
|
||||
det_xywh2[key][k] = det_xywh[key][k]
|
||||
if len(det_xywh2) > 0:
|
||||
put_queue(image_queue, (1, [det_xywh2, frame, frame_index_list[i], all_frames, draw_config["font_config"]]))
|
||||
|
||||
push_p = push_p_result.result(timeout=60)
|
||||
ai_video_file = write_ai_video_result.result(timeout=60)
|
||||
or_video_file = write_or_video_result.result(timeout=60)
|
||||
# 接收停止指令
|
||||
if push_r[0] == 2:
|
||||
if 'stop' == push_r[1]:
|
||||
logger.info("停止推流线程, requestId: {}", request_id)
|
||||
break
|
||||
if 'stop_ex' == push_r[1]:
|
||||
logger.info("停止推流线程, requestId: {}", request_id)
|
||||
ex_status = False
|
||||
break
|
||||
del push_r
|
||||
else:
|
||||
sleep(1)
|
||||
except ServiceException as s:
|
||||
logger.error("推流进程异常:{}, requestId:{}", s.msg, request_id)
|
||||
ex = s.code, s.msg
|
||||
except Exception:
|
||||
logger.error("推流进程异常:{}, requestId:{}", format_exc(), request_id)
|
||||
ex = ExceptionType.SERVICE_INNER_EXCEPTION.value[0], ExceptionType.SERVICE_INNER_EXCEPTION.value[1]
|
||||
finally:
|
||||
# 关闭推流管, 原视频写对象, 分析视频写对象
|
||||
close_all_p(push_p, or_video_file, ai_video_file, request_id)
|
||||
if ex:
|
||||
code, msg = ex
|
||||
put_queue(push_ex_queue, (1, code, msg), timeout=2)
|
||||
else:
|
||||
if ex_status:
|
||||
# 关闭推流的时候, 等待1分钟图片队列处理完,如果1分钟内没有处理完, 清空图片队列, 丢弃没有上传的图片
|
||||
c_time = time()
|
||||
while time() - c_time < 60:
|
||||
if image_queue.qsize() == 0 or image_queue.empty():
|
||||
break
|
||||
sleep(2)
|
||||
for q in [push_queue, image_queue, hb_queue]:
|
||||
clear_queue(q)
|
||||
logger.info("推流进程停止完成!requestId:{}", request_id)
|
||||
|
||||
|
||||
class OffPushStreamProcess2(PushStreamProcess2):
|
||||
__slots__ = ()
|
||||
|
||||
def run(self):
|
||||
self.build_logo_url()
|
||||
msg, context = self._msg, self._context
|
||||
request_id = msg["request_id"]
|
||||
base_dir, env = context["base_dir"], context['env']
|
||||
push_queue, image_queue, push_ex_queue, hb_queue = self._push_queue, self._image_queue, self._push_ex_queue, \
|
||||
self._hb_queue
|
||||
aiFilePath, logo = context["aiFilePath"], context["logo"]
|
||||
ai_video_file, push_p, push_url = None, None, msg["push_url"]
|
||||
service_timeout = int(context["service"]["timeout"]) + 120
|
||||
frame_score = context["service"]["filter"]["frame_score"]
|
||||
ex = None
|
||||
ex_status = True
|
||||
try:
|
||||
init_log(base_dir, env)
|
||||
logger.info("开始启动离线推流进程!requestId:{}", request_id)
|
||||
with ThreadPoolExecutor(max_workers=2) as t:
|
||||
# 定义三种推流、写原视频流、写ai视频流策略
|
||||
# 第一个参数时间, 第二个参数重试次数
|
||||
p_push_status, ai_write_status = [0, 0], [0, 0]
|
||||
start_time = time()
|
||||
minID = 0
|
||||
maxID = 0
|
||||
while True:
|
||||
# 检测推流执行超时时间
|
||||
if time() - start_time > service_timeout:
|
||||
logger.error("离线推流超时, requestId: {}", request_id)
|
||||
raise ServiceException(ExceptionType.PUSH_STREAM_TIMEOUT_EXCEPTION.value[0],
|
||||
ExceptionType.PUSH_STREAM_TIMEOUT_EXCEPTION.value[1])
|
||||
# 系统由于各种问题可能会杀死内存使用多的进程, 自己杀掉自己
|
||||
if psutil.Process(getpid()).ppid() == 1:
|
||||
ex_status = False
|
||||
logger.info("离线推流进程检测到父进程异常停止, 自动停止推流进程, requestId: {}", request_id)
|
||||
for q in [push_queue, image_queue, push_ex_queue, hb_queue]:
|
||||
clear_queue(q)
|
||||
break
|
||||
# 获取推流的视频帧
|
||||
push_r = get_no_block_queue(push_queue)
|
||||
if push_r is not None:
|
||||
# [(1, ...] 视频帧操作
|
||||
# [(2, 操作指令)] 指令操作
|
||||
if push_r[0] == 1:
|
||||
frame_list, frame_index_list, all_frames, draw_config, push_objs = push_r[1]
|
||||
# 处理每一帧图片
|
||||
for i, frame in enumerate(frame_list):
|
||||
if frame_index_list[i] % 300 == 0 and frame_index_list[i] <= all_frames:
|
||||
task_process = "%.2f" % (float(frame_index_list[i]) / float(all_frames))
|
||||
put_queue(hb_queue, {"hb_value": task_process}, timeout=2)
|
||||
# 复制帧用来画图
|
||||
copy_frame = frame.copy()
|
||||
# 所有问题记录字典
|
||||
det_xywh, thread_p = {}, []
|
||||
det_xywh2 = {}
|
||||
det_tmp = {}
|
||||
for s_det_list in push_objs:
|
||||
code, det_result = s_det_list[0], s_det_list[1][i]
|
||||
if len(det_result) > 0:
|
||||
font_config, allowedList = draw_config["font_config"], draw_config[code]["allowedList"]
|
||||
rainbows, label_arrays = draw_config[code]["rainbows"], draw_config[code]["label_arrays"]
|
||||
for qs in det_result:
|
||||
box, score, cls = xywh2xyxy2(qs)
|
||||
if cls not in allowedList or score < frame_score:
|
||||
continue
|
||||
label_array, color = label_arrays[cls], rainbows[cls]
|
||||
rr = t.submit(draw_painting_joint, box, copy_frame, label_array, score, color, font_config)
|
||||
thread_p.append(rr)
|
||||
if det_xywh.get(code) is None:
|
||||
det_xywh[code] = {}
|
||||
cd = det_xywh[code].get(cls)
|
||||
is_new = False
|
||||
if len(qs) == 8:
|
||||
trackId = qs[7]
|
||||
elif len(qs) == 5:
|
||||
trackId = qs[4]
|
||||
if trackId > minID:
|
||||
is_new = True
|
||||
if det_tmp.get(code) is None:
|
||||
det_tmp[code] = [cls]
|
||||
else:
|
||||
if not (cls in det_tmp[code]):
|
||||
det_tmp[code].append(cls)
|
||||
qs_tmp = [cls, box, score, label_array, color, is_new]
|
||||
if trackId > maxID:
|
||||
maxID = trackId
|
||||
if cd is None:
|
||||
det_xywh[code][cls] = [qs_tmp]
|
||||
else:
|
||||
det_xywh[code][cls].append(qs_tmp)
|
||||
minID = maxID
|
||||
|
||||
if logo:
|
||||
frame = add_water_pic(frame, logo, request_id)
|
||||
copy_frame = add_water_pic(copy_frame, logo, request_id)
|
||||
if len(thread_p) > 0:
|
||||
for r in thread_p:
|
||||
r.result()
|
||||
frame_merge = video_conjuncing(frame, copy_frame)
|
||||
# 写识别视频到本地
|
||||
write_ai_video_result = t.submit(write_ai_video, frame_merge, aiFilePath,
|
||||
ai_video_file,
|
||||
ai_write_status, request_id)
|
||||
push_p_result = t.submit(push_video_stream, frame_merge, push_p, push_url,
|
||||
p_push_status,
|
||||
request_id)
|
||||
if det_xywh:
|
||||
for index, (key, value) in enumerate(det_xywh.items()):
|
||||
for k in value.keys():
|
||||
if (key in det_tmp.keys()) and (k in det_tmp[key]):
|
||||
det_xywh2[key] = {}
|
||||
det_xywh2[key][k] = det_xywh[key][k]
|
||||
if len(det_xywh2) > 0:
|
||||
put_queue(image_queue, (1, [det_xywh2, frame, frame_index_list[i], all_frames, draw_config["font_config"]]))
|
||||
push_p = push_p_result.result(timeout=60)
|
||||
ai_video_file = write_ai_video_result.result(timeout=60)
|
||||
# 接收停止指令
|
||||
if push_r[0] == 2:
|
||||
if 'stop' == push_r[1]:
|
||||
logger.info("停止推流线程, requestId: {}", request_id)
|
||||
break
|
||||
if 'stop_ex' == push_r[1]:
|
||||
logger.info("停止推流线程, requestId: {}", request_id)
|
||||
ex_status = False
|
||||
break
|
||||
del push_r
|
||||
else:
|
||||
sleep(1)
|
||||
except ServiceException as s:
|
||||
logger.error("推流进程异常:{}, requestId:{}", s.msg, request_id)
|
||||
ex = s.code, s.msg
|
||||
except Exception:
|
||||
logger.error("推流进程异常:{}, requestId:{}", format_exc(), request_id)
|
||||
ex = ExceptionType.SERVICE_INNER_EXCEPTION.value[0], ExceptionType.SERVICE_INNER_EXCEPTION.value[1]
|
||||
finally:
|
||||
# 关闭推流管, 分析视频写对象
|
||||
close_all_p(push_p, None, ai_video_file, request_id)
|
||||
if ex:
|
||||
code, msg = ex
|
||||
put_queue(push_ex_queue, (1, code, msg), timeout=2)
|
||||
else:
|
||||
if ex_status:
|
||||
# 关闭推流的时候, 等待1分钟图片队列处理完,如果1分钟内没有处理完, 清空图片队列, 丢弃没有上传的图片
|
||||
c_time = time()
|
||||
while time() - c_time < 60:
|
||||
if image_queue.qsize() == 0 or image_queue.empty():
|
||||
break
|
||||
sleep(2)
|
||||
for q in [push_queue, image_queue, hb_queue]:
|
||||
clear_queue(q)
|
||||
logger.info("推流进程停止完成!requestId:{}", request_id)
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from threading import Thread
|
||||
import time
|
||||
from traceback import format_exc
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from entity.FeedBack import recording_feedback
|
||||
from enums.RecordingStatusEnum import RecordingStatus
|
||||
from util.QueUtil import get_no_block_queue, put_queue, clear_queue
|
||||
|
||||
|
||||
class RecordingHeartbeat(Thread):
|
||||
__slots__ = ('_fb_queue', '_hb_queue', '_request_id')
|
||||
|
||||
def __init__(self, fb_queue, hb_queue, request_id):
|
||||
super().__init__()
|
||||
self._fb_queue = fb_queue
|
||||
self._hb_queue = hb_queue
|
||||
self._request_id = request_id
|
||||
|
||||
def run(self):
|
||||
request_id = self._request_id
|
||||
hb_queue, fb_queue = self._hb_queue, self._fb_queue
|
||||
logger.info("开始启动录屏心跳线程!requestId:{}", request_id)
|
||||
hb_init_num, progress = 0, '0.0000'
|
||||
status = RecordingStatus.RECORDING_WAITING.value[0]
|
||||
try:
|
||||
while True:
|
||||
time.sleep(3)
|
||||
hb_msg = get_no_block_queue(hb_queue)
|
||||
if hb_msg is not None and len(hb_msg) > 0:
|
||||
command_que = hb_msg.get("command")
|
||||
progress_que = hb_msg.get("progress")
|
||||
status_que = hb_msg.get("status")
|
||||
if progress_que is not None:
|
||||
progress = progress_que
|
||||
if status_que is not None:
|
||||
status = status_que
|
||||
if 'stop' == command_que:
|
||||
logger.info("开始终止心跳线程, requestId:{}", request_id)
|
||||
break
|
||||
if hb_init_num % 30 == 0:
|
||||
put_queue(fb_queue, recording_feedback(request_id, status, progress=progress), timeout=5, is_ex=True)
|
||||
hb_init_num += 3
|
||||
except Exception:
|
||||
logger.error("心跳线程异常:{}, requestId:{}", format_exc(), request_id)
|
||||
finally:
|
||||
clear_queue(hb_queue)
|
||||
logger.info("心跳线程停止完成!requestId:{}", request_id)
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from threading import Thread
|
||||
from time import sleep, time
|
||||
from traceback import format_exc
|
||||
|
||||
#from common.Constant import init_progess
|
||||
import json,os,psutil,GPUtil,platform,socket
|
||||
from kafka import KafkaProducer, KafkaConsumer
|
||||
#from util.KafkaUtils import CustomerKafkaProducer
|
||||
from common.YmlConstant import service_yml_path, kafka_yml_path
|
||||
class uploadGPUinfos(Thread):
|
||||
__slots__ = ('__kafka_config', "_context")
|
||||
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
self.__context,self.__kafka_config = args
|
||||
self.__uploadInterval = self.__context['GPUpollInterval']
|
||||
#kafkaProducer = CustomerKafkaProducer(self.__kafka_config)
|
||||
self.__producer = KafkaProducer(
|
||||
bootstrap_servers=self.__kafka_config['bootstrap_servers'],#tencent yun
|
||||
value_serializer=lambda v: v.encode('utf-8'))
|
||||
|
||||
self.__topic = self.__kafka_config["topicGPU"]
|
||||
def run(self):
|
||||
while True:
|
||||
|
||||
try:
|
||||
#获取当前的gpu状态信息
|
||||
msg_dict = get_system_info()
|
||||
#发送GPU状态到指定的topic
|
||||
msg = json.dumps(msg_dict)
|
||||
|
||||
# 假设生产的消息为键值对(不是一定要键值对),且序列化方式为json
|
||||
|
||||
#future = kafkaProducer.sender(topic_on,msg)
|
||||
future = self.__producer .send(self.__topic,msg)
|
||||
try:
|
||||
future.get(timeout=10)
|
||||
except kafka_errors:
|
||||
traceback.format_exc()
|
||||
|
||||
sleep(self.__uploadInterval)
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
continue
|
||||
#logger.error("上传GPU服务器线程状态异常:{}, requestId:{}", format_exc(), request_id)
|
||||
|
||||
|
||||
|
||||
|
||||
def get_system_info():
|
||||
# 初始化一个字典来存储系统信息
|
||||
system_info = {}
|
||||
|
||||
# 获取CPU信息
|
||||
system_info['CPU'] = {
|
||||
'Physical Cores': psutil.cpu_count(logical=False), # 物理核心数
|
||||
'Logical Cores': psutil.cpu_count(logical=True), # 逻辑核心数
|
||||
'Current Frequency': psutil.cpu_freq().current, # 当前频率
|
||||
'Usage Per Core': psutil.cpu_percent(interval=1, percpu=True), # 每个核心的使用率
|
||||
'Total Usage': psutil.cpu_percent(interval=1) # 总体CPU使用率
|
||||
}
|
||||
|
||||
# 获取内存信息
|
||||
memory = psutil.virtual_memory()
|
||||
system_info['Memory'] = {
|
||||
'Total': memory.total / (1024 ** 3), # 总内存,单位为GB
|
||||
'Available': memory.available / (1024 ** 3), # 可用内存
|
||||
'Used': memory.used / (1024 ** 3), # 已用内存
|
||||
'Usage Percentage': memory.percent # 内存使用率
|
||||
}
|
||||
|
||||
# 获取GPU信息
|
||||
gpus = GPUtil.getGPUs()
|
||||
system_info['GPU'] = []
|
||||
for gpu in gpus:
|
||||
gpu_info = {
|
||||
'ID': gpu.id,
|
||||
'Name': gpu.name,
|
||||
'Load': gpu.load * 100, # GPU负载,百分比
|
||||
'Memory Total': gpu.memoryTotal, # 总显存,单位为MB
|
||||
'Memory Used': gpu.memoryUsed, # 已用显存
|
||||
'Memory Free': gpu.memoryFree, # 可用显存
|
||||
'Temperature': gpu.temperature # GPU温度
|
||||
}
|
||||
system_info['GPU'].append(gpu_info)
|
||||
|
||||
# 获取系统信息
|
||||
system_info['System'] = {
|
||||
'Platform': platform.system(), # 操作系统类型
|
||||
'Platform Version': platform.version(), # 操作系统版本
|
||||
'Platform Release': platform.release(), # 操作系统发行版本
|
||||
'Platform Node': platform.node(), # 网络名称
|
||||
'Machine': platform.machine(), # 硬件架构
|
||||
'Processor': platform.processor() # CPU架构
|
||||
}
|
||||
|
||||
# 获取本机局域网IP地址(非回环地址)
|
||||
try:
|
||||
# 获取所有网络接口信息
|
||||
net_if_addrs = psutil.net_if_addrs()
|
||||
for interface, addrs in net_if_addrs.items():
|
||||
for addr in addrs:
|
||||
# 筛选IPv4地址且非回环地址
|
||||
if addr.family == socket.AF_INET and not addr.address.startswith("127."):
|
||||
system_info['System']['Local IP Address'] = addr.address
|
||||
break
|
||||
if 'Local IP Address' in system_info['System']:
|
||||
break
|
||||
else:
|
||||
system_info['System']['Local IP Address'] = "No local IP found"
|
||||
except Exception as e:
|
||||
system_info['System']['Local IP Address'] = "Unable to retrieve local IP address"
|
||||
|
||||
return system_info
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
|
||||
|
||||
context = {
|
||||
'GPUpollInterval':1,
|
||||
'topic':'server-status',
|
||||
}
|
||||
kafka_config = {
|
||||
'bootstrap_servers':['192.168.10.66:9092']
|
||||
}
|
||||
|
||||
base_dir, env = '/home/thsw2/WJ/test/tuoheng_algN','test'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
upload_thread = uploadGPUinfos(context,kafka_config)
|
||||
upload_thread.setDaemon(False)
|
||||
|
||||
upload_thread.start()
|
||||
|
||||
|
||||
# 主线程等待守护线程运行
|
||||
try:
|
||||
while True:
|
||||
sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
print("主线程退出")
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
access_key: "LTAI5tSJ62TLMUb4SZuf285A"
|
||||
access_secret: "MWYynm30filZ7x0HqSHlU3pdLVNeI7"
|
||||
oss:
|
||||
endpoint: "http://oss-cn-shanghai.aliyuncs.com"
|
||||
bucket: "ta-tech-image"
|
||||
connect_timeout: 30
|
||||
vod:
|
||||
host_address: "https://vod.play.t-aaron.com/"
|
||||
ecsRegionId: "cn-shanghai"
|
||||
cateId: 1000468341
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
access_key: "LTAI5tSJ62TLMUb4SZuf285A"
|
||||
access_secret: "MWYynm30filZ7x0HqSHlU3pdLVNeI7"
|
||||
oss:
|
||||
endpoint: "http://oss-cn-shanghai.aliyuncs.com"
|
||||
bucket: "ta-tech-image"
|
||||
connect_timeout: 30
|
||||
vod:
|
||||
host_address: "https://vod.play.t-aaron.com/"
|
||||
ecsRegionId: "cn-shanghai"
|
||||
cateId: 1000468340
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
access_key: "LTAI5tFmaJHU7ywvBH2j12Gp"
|
||||
access_secret: "mX6rS1xYTgZgFAgpOrQHyc6jLXv0AV"
|
||||
oss:
|
||||
endpoint: "http://oss-cn-shanghai.aliyuncs.com"
|
||||
bucket: "ta-tech-image"
|
||||
connect_timeout: 30
|
||||
vod:
|
||||
host_address: "https://vod.play.t-aaron.com/"
|
||||
ecsRegionId: "cn-shanghai"
|
||||
cateId: 1000468338
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
access_key: "LTAI5tFmaJHU7ywvBH2j12Gp"
|
||||
access_secret: "mX6rS1xYTgZgFAgpOrQHyc6jLXv0AV"
|
||||
oss:
|
||||
endpoint: "http://oss-cn-shanghai.aliyuncs.com"
|
||||
bucket: "ta-tech-image"
|
||||
connect_timeout: 30
|
||||
vod:
|
||||
host_address: "https://vod.play.t-aaron.com/"
|
||||
ecsRegionId: "cn-shanghai"
|
||||
cateId: 1000468338
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
orc:
|
||||
APP_ID: 28173504
|
||||
API_KEY: "kqrFE7VuygIaFer7z6cRxzoi"
|
||||
SECRET_KEY: "yp7xBokyl4TItyGhay7skAN1cMwfvEXf"
|
||||
vehicle:
|
||||
APP_ID: 31096670
|
||||
API_KEY: "Dam3O4tgPRN3qh4OYE82dbg7"
|
||||
SECRET_KEY: "1PGZ9LAXRR5zcT5MN9rHcW8kLBIS5DAa"
|
||||
person:
|
||||
APP_ID: 31096755
|
||||
API_KEY: "CiWrt4iyxOly36n3kR7utiAG"
|
||||
SECRET_KEY: "K7y6V3XTGdyXvgtCNCwTGUEooxxDuX9v"
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
orc:
|
||||
APP_ID: 28173504
|
||||
API_KEY: "kqrFE7VuygIaFer7z6cRxzoi"
|
||||
SECRET_KEY: "yp7xBokyl4TItyGhay7skAN1cMwfvEXf"
|
||||
vehicle:
|
||||
APP_ID: 31096670
|
||||
API_KEY: "Dam3O4tgPRN3qh4OYE82dbg7"
|
||||
SECRET_KEY: "1PGZ9LAXRR5zcT5MN9rHcW8kLBIS5DAa"
|
||||
person:
|
||||
APP_ID: 31096755
|
||||
API_KEY: "CiWrt4iyxOly36n3kR7utiAG"
|
||||
SECRET_KEY: "K7y6V3XTGdyXvgtCNCwTGUEooxxDuX9v"
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
orc:
|
||||
APP_ID: 28173504
|
||||
API_KEY: "kqrFE7VuygIaFer7z6cRxzoi"
|
||||
SECRET_KEY: "yp7xBokyl4TItyGhay7skAN1cMwfvEXf"
|
||||
vehicle:
|
||||
APP_ID: 31096670
|
||||
API_KEY: "Dam3O4tgPRN3qh4OYE82dbg7"
|
||||
SECRET_KEY: "1PGZ9LAXRR5zcT5MN9rHcW8kLBIS5DAa"
|
||||
person:
|
||||
APP_ID: 31096755
|
||||
API_KEY: "CiWrt4iyxOly36n3kR7utiAG"
|
||||
SECRET_KEY: "K7y6V3XTGdyXvgtCNCwTGUEooxxDuX9v"
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
bootstrap_servers: ["192.168.11.13:9092"]
|
||||
topic:
|
||||
dsp-alg-online-tasks-topic: "dsp-alg-online-tasks"
|
||||
dsp-alg-offline-tasks-topic: "dsp-alg-offline-tasks"
|
||||
dsp-alg-image-tasks-topic: "dsp-alg-image-tasks"
|
||||
dsp-alg-results-topic: "dsp-alg-task-results"
|
||||
dsp-recording-task-topic: "dsp-recording-task"
|
||||
dsp-recording-result-topic: "dsp-recording-result"
|
||||
dsp-push-stream-task-topic: "dsp-push-stream-task"
|
||||
dsp-push-stream-result-topic: "dsp-push-stream-result"
|
||||
producer:
|
||||
acks: -1
|
||||
retries: 3
|
||||
linger_ms: 50
|
||||
retry_backoff_ms: 1000
|
||||
max_in_flight_requests_per_connection: 5
|
||||
consumer:
|
||||
client_id: "dsp_ai_server"
|
||||
group_id: "dsp-ai-dev"
|
||||
auto_offset_reset: "latest"
|
||||
enable_auto_commit: false
|
||||
max_poll_records: 1
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
bootstrap_servers: ["101.132.127.1:19094"]
|
||||
topic:
|
||||
dsp-alg-online-tasks-topic: "dsp-alg-online-tasks"
|
||||
dsp-alg-offline-tasks-topic: "dsp-alg-offline-tasks"
|
||||
dsp-alg-image-tasks-topic: "dsp-alg-image-tasks"
|
||||
dsp-alg-results-topic: "dsp-alg-task-results"
|
||||
dsp-recording-task-topic: "dsp-recording-task"
|
||||
dsp-recording-result-topic: "dsp-recording-result"
|
||||
dsp-push-stream-task-topic: "dsp-push-stream-task"
|
||||
dsp-push-stream-result-topic: "dsp-push-stream-result"
|
||||
producer:
|
||||
acks: -1
|
||||
retries: 3
|
||||
linger_ms: 50
|
||||
retry_backoff_ms: 1000
|
||||
max_in_flight_requests_per_connection: 5
|
||||
consumer:
|
||||
client_id: "dsp_ai_server"
|
||||
group_id: "dsp-ai-prod"
|
||||
auto_offset_reset: "latest"
|
||||
enable_auto_commit: false
|
||||
max_poll_records: 1
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
bootstrap_servers: ["106.14.96.218:19092"]
|
||||
topicGPU: "server-status"
|
||||
topicPort:
|
||||
dsp-alg-online-tasks-topic: "dsp-alg-online-tasks"
|
||||
dsp-alg-offline-tasks-topic: "dsp-alg-offline-tasks"
|
||||
dsp-alg-image-tasks-topic: "dsp-alg-image-tasks"
|
||||
dsp-alg-results-topic: "dsp-alg-task-results"
|
||||
dsp-recording-task-topic: "dsp-recording-task"
|
||||
dsp-recording-result-topic: "dsp-recording-result"
|
||||
dsp-push-stream-task-topic: "dsp-push-stream-task"
|
||||
dsp-push-stream-result-topic: "dsp-push-stream-result"
|
||||
topic:
|
||||
dsp-alg-online-tasks-topic: "dsp-alg-online-tasks-192.168.11.7"
|
||||
dsp-alg-offline-tasks-topic: "dsp-alg-offline-tasks-192.168.11.7"
|
||||
dsp-alg-image-tasks-topic: "dsp-alg-image-tasks-192.168.11.7"
|
||||
dsp-alg-results-topic: "dsp-alg-task-results"
|
||||
dsp-recording-task-topic: "dsp-recording-task-192.168.11.7"
|
||||
dsp-recording-result-topic: "dsp-recording-result"
|
||||
dsp-push-stream-task-topic: "dsp-push-stream-task-192.168.11.7"
|
||||
dsp-push-stream-result-topic: "dsp-push-stream-result"
|
||||
producer:
|
||||
acks: -1
|
||||
retries: 3
|
||||
linger_ms: 50
|
||||
retry_backoff_ms: 1000
|
||||
max_in_flight_requests_per_connection: 5
|
||||
consumer:
|
||||
client_id: "dsp_ai_server"
|
||||
group_id: "dsp-ai-test"
|
||||
auto_offset_reset: "latest"
|
||||
enable_auto_commit: false
|
||||
max_poll_records: 1
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
enable_file_log: true
|
||||
enable_stderr: true
|
||||
base_path: "../dsp/logs"
|
||||
log_name: "dsp.log"
|
||||
log_fmt: "{time:YYYY-MM-DD HH:mm:ss.SSS} [{level}][{process.name}-{process.id}-{thread.name}-{thread.id}][{line}] {module}-{function} - {message}"
|
||||
level: "INFO"
|
||||
rotation: "00:00"
|
||||
retention: "1 days"
|
||||
encoding: "utf8"
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
enable_file_log: true
|
||||
enable_stderr: false
|
||||
base_path: "../dsp/logs"
|
||||
log_name: "dsp.log"
|
||||
log_fmt: "{time:YYYY-MM-DD HH:mm:ss.SSS} [{level}][{process.name}-{process.id}-{thread.name}-{thread.id}][{line}] {module}-{function} - {message}"
|
||||
level: "INFO"
|
||||
rotation: "00:00"
|
||||
retention: "15 days"
|
||||
encoding: "utf8"
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
enable_file_log: true
|
||||
enable_stderr: false
|
||||
base_path: "../dsp/logs"
|
||||
log_name: "dsp.log"
|
||||
log_fmt: "{time:YYYY-MM-DD HH:mm:ss.SSS} [{level}][{process.name}-{process.id}-{thread.name}-{thread.id}][{line}] {module}-{function} - {message}"
|
||||
level: "INFO"
|
||||
rotation: "00:00"
|
||||
retention: "7 days"
|
||||
encoding: "utf8"
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
endpoint: 'minio.t-aaron.com:9000'
|
||||
domain: 'https://minio.t-aaron.com'
|
||||
access_key: 'IKf3A0ZSXsR1m0oalMjV'
|
||||
secret_key: 'yoC6qRo2hlyZu8Pdbt6eh9TVaTV4gD7KRudromrk'
|
||||
secure: false
|
||||
image_bucket: 'image'
|
||||
video_bucket: 'video'
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
endpoint: 'minio-jndsj.t-aaron.com:2443'
|
||||
domain: 'https://minio-jndsj.t-aaron.com:2443'
|
||||
access_key: 'PJM0c2qlauoXv5TMEHm2'
|
||||
secret_key: 'Wr69Dm3ZH39M3GCSeyB3eFLynLPuGCKYfphixZuI'
|
||||
secure: true
|
||||
image_bucket: 'image'
|
||||
video_bucket: 'video'
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
mqtt_flag: true
|
||||
broker : "58.213.148.44"
|
||||
port : 1883
|
||||
username: "admin"
|
||||
password: "admin##123"
|
||||
#topic: "/topic/v1/airportFly/%s/aiDroneData"
|
||||
topic: "/topic/v1/airportDrone/THJSQ03B2309TPCTD5QV/realTime/data"
|
||||
# 存储多少条消息到list里
|
||||
length: 10
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
video:
|
||||
# 视频本地保存地址
|
||||
file_path: "../dsp/video/"
|
||||
# 是否添加水印
|
||||
video_add_water: false
|
||||
service:
|
||||
filter:
|
||||
# 图片得分多少分以上返回图片
|
||||
frame_score: 0.4
|
||||
# 图片相似度过滤
|
||||
picture_similarity: true
|
||||
similarity: 0.65
|
||||
frame_step: 160
|
||||
timeout: 21600
|
||||
cv2_pull_stream_timeout: 1000
|
||||
cv2_read_stream_timeout: 1000
|
||||
recording_pull_stream_timeout: 600
|
||||
model:
|
||||
# 使用哪种识别方式
|
||||
# 1 普通方式
|
||||
# 2 模型追踪
|
||||
model_type: 1
|
||||
limit: 3
|
||||
task:
|
||||
# 任务限制5个
|
||||
limit: 5
|
||||
image:
|
||||
limit: 20
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
video:
|
||||
# 视频本地保存地址
|
||||
file_path: "../dsp/video/"
|
||||
# 是否添加水印
|
||||
video_add_water: false
|
||||
service:
|
||||
filter:
|
||||
# 图片得分多少分以上返回图片
|
||||
frame_score: 0.4
|
||||
# 图片相似度过滤
|
||||
picture_similarity: true
|
||||
similarity: 0.65
|
||||
frame_step: 160
|
||||
timeout: 21600
|
||||
cv2_pull_stream_timeout: 1000
|
||||
cv2_read_stream_timeout: 1000
|
||||
recording_pull_stream_timeout: 600
|
||||
model:
|
||||
# 使用哪种识别方式
|
||||
# 1 普通方式
|
||||
# 2 模型追踪
|
||||
model_type: 1
|
||||
limit: 3
|
||||
task:
|
||||
# 任务限制5个
|
||||
limit: 5
|
||||
image:
|
||||
limit: 20
|
||||
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
video:
|
||||
# 视频本地保存地址
|
||||
file_path: "../dsp/video/"
|
||||
# 是否添加水印
|
||||
video_add_water: false
|
||||
#0-slave,1--master
|
||||
role : 1
|
||||
#gpu信息上报间隔
|
||||
GPUpollInterval: 2
|
||||
service:
|
||||
filter:
|
||||
# 图片得分多少分以上返回图片
|
||||
frame_score: 0.4
|
||||
# 图片相似度过滤
|
||||
picture_similarity: true
|
||||
similarity: 0.65
|
||||
frame_step: 160
|
||||
timeout: 21600
|
||||
cv2_pull_stream_timeout: 1000
|
||||
cv2_read_stream_timeout: 1000
|
||||
recording_pull_stream_timeout: 600
|
||||
model:
|
||||
# 使用哪种识别方式
|
||||
# 1 普通方式
|
||||
# 2 模型追踪
|
||||
model_type: 1
|
||||
limit: 3
|
||||
task:
|
||||
# 任务限制5个
|
||||
limit: 5
|
||||
image:
|
||||
limit: 20
|
||||
#storage source,0--aliyun,1--minio
|
||||
storage_source: 0
|
||||
#是否启用mqtt,0--不用,1--启用
|
||||
mqtt_flag: 0
|
||||
#是否启用alg控制功能
|
||||
algSwitch: False
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from os.path import dirname, realpath
|
||||
from sys import argv
|
||||
|
||||
from loguru import logger
|
||||
from torch import multiprocessing
|
||||
|
||||
from service.Dispatcher import DispatcherService
|
||||
from util.LogUtils import init_log
|
||||
|
||||
'''
|
||||
dsp主程序入口
|
||||
'''
|
||||
if __name__ == '__main__':
|
||||
multiprocessing.set_start_method('spawn')
|
||||
base_dir = dirname(realpath(__file__))
|
||||
arg = argv
|
||||
print("脚本启动参数: ", arg)
|
||||
envs = ('dev', 'test', 'prod')
|
||||
env = envs[0]
|
||||
active = [env for env in envs if env in arg]
|
||||
if len(active) != 0:
|
||||
env = active[0]
|
||||
init_log(base_dir, env)
|
||||
logger.info("(♥◠‿◠)ノ゙ DSP【算法调度服务】开始启动 ლ(´ڡ`ლ)゙")
|
||||
DispatcherService(base_dir, env)
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
from json import dumps
|
||||
|
||||
from util.TimeUtils import now_date_to_str
|
||||
|
||||
|
||||
def message_feedback(requestId, status, analyse_type, error_code="", error_msg="", progress="", original_url="",
|
||||
sign_url="", modelCode="", detectTargetCode="", analyse_results="", video_url="", ai_video_url="",longitude="",latitude=""):
|
||||
if len(analyse_results) > 0:
|
||||
analyse_results = dumps(analyse_results)
|
||||
taskbar = {
|
||||
"request_id": requestId,
|
||||
"status": status,
|
||||
"type": analyse_type,
|
||||
"video_url": video_url,
|
||||
"ai_video_url": ai_video_url,
|
||||
"error_code": error_code,
|
||||
"error_msg": error_msg,
|
||||
"progress": progress,
|
||||
"results": [
|
||||
{
|
||||
"original_url": original_url,
|
||||
"sign_url": sign_url,
|
||||
"analyse_results": analyse_results,
|
||||
"model_code": modelCode,
|
||||
"detect_targets_code": detectTargetCode,
|
||||
"analyse_time": now_date_to_str(),
|
||||
"longitude":str(longitude),
|
||||
"latitude":str(latitude),
|
||||
}
|
||||
]
|
||||
}
|
||||
return {"feedback": taskbar}
|
||||
|
||||
|
||||
def recording_feedback(requestId, status, error_code="", error_msg="", progress="", video_url=""):
|
||||
rdf = {
|
||||
"request_id": requestId,
|
||||
"status": status,
|
||||
"error_code": error_code,
|
||||
"error_msg": error_msg,
|
||||
"progress": progress,
|
||||
"video_url": video_url
|
||||
}
|
||||
return {"recording": rdf}
|
||||
|
||||
|
||||
def pull_stream_feedback(requestId, status, error_code="", error_msg="", videoInfo=[]):
|
||||
return {"pull_stream": {
|
||||
"request_id": requestId,
|
||||
"video_info_list": videoInfo,
|
||||
"push_stream_status": status,
|
||||
"error_code": error_code,
|
||||
"error_msg": error_msg,
|
||||
"current_time": now_date_to_str()
|
||||
}}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
class PullStreamDto:
|
||||
|
||||
__slots__ = ('msg', 'context', 'pullQueue', 'fbQueue', 'hbQueue', 'imageQueue', 'analyse_type')
|
||||
|
||||
def __init__(self, msg, context, pullQueue, fbQueue, hbQueue, imageQueue, analyse_type):
|
||||
self.msg = msg
|
||||
self.context = context
|
||||
self.pullQueue = pullQueue
|
||||
self.fbQueue = fbQueue
|
||||
self.hbQueue = hbQueue
|
||||
self.imageQueue = imageQueue
|
||||
self.analyse_type = analyse_type
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
from enum import Enum, unique
|
||||
|
||||
|
||||
# 分析状态枚举
|
||||
@unique
|
||||
class AnalysisStatus(Enum):
|
||||
|
||||
# 等待
|
||||
WAITING = "waiting"
|
||||
|
||||
# 分析中
|
||||
RUNNING = "running"
|
||||
|
||||
# 分析完成
|
||||
SUCCESS = "success"
|
||||
|
||||
# 超时
|
||||
TIMEOUT = "timeout"
|
||||
|
||||
# 失败
|
||||
FAILED = "failed"
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
from enum import Enum, unique
|
||||
|
||||
|
||||
# 分析类型枚举
|
||||
@unique
|
||||
class AnalysisType(Enum):
|
||||
# 在线
|
||||
ONLINE = "1"
|
||||
|
||||
# 离线
|
||||
OFFLINE = "2"
|
||||
|
||||
# 图片
|
||||
IMAGE = "3"
|
||||
|
||||
# 录屏
|
||||
RECORDING = "9999"
|
||||
|
||||
# 转推流
|
||||
PULLTOPUSH = "10000"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
from enum import Enum, unique
|
||||
|
||||
'''
|
||||
ocr官方文档: https://ai.baidu.com/ai-doc/OCR/zkibizyhz
|
||||
官方文档: https://ai.baidu.com/ai-doc/VEHICLE/rk3inf9tj
|
||||
参数1: 异常编号
|
||||
参数2: 异常英文描述
|
||||
参数3: 异常中文描述
|
||||
参数4: 0-异常信息统一输出为内部异常
|
||||
1-异常信息可以输出
|
||||
2-输出空的异常信息
|
||||
参数5: 指定异常重试的次数
|
||||
'''
|
||||
|
||||
|
||||
# 异常枚举
|
||||
@unique
|
||||
class BaiduSdkErrorEnum(Enum):
|
||||
|
||||
UNKNOWN_ERROR = (1, "Unknown error", "未知错误", 0, 0)
|
||||
|
||||
SERVICE_TEMPORARILY_UNAVAILABLE = (2, "Service temporarily unavailable", "服务暂不可用,请再次请求", 0, 3)
|
||||
|
||||
UNSUPPORTED_OPENAPI_METHOD = (3, "Unsupported openapi method", "调用的API不存在", 0, 0)
|
||||
|
||||
API_REQUEST_LIMIT_REACHED = (4, "Open api request limit reached", "请求量限制, 请稍后再试!", 1, 5)
|
||||
|
||||
NO_PERMISSION_TO_ACCESS_DATA = (6, "No permission to access data", "无权限访问该用户数据", 1, 0)
|
||||
|
||||
GET_SERVICE_TOKEN_FAILED = (13, "Get service token failed", "获取token失败", 0, 2)
|
||||
|
||||
IAM_CERTIFICATION_FAILED = (14, "IAM Certification failed", "IAM 鉴权失败", 0, 1)
|
||||
|
||||
APP_NOT_EXSITS_OR_CREATE_FAILED = (15, "app not exsits or create failed", "应用不存在或者创建失败", 0, 0)
|
||||
|
||||
API_DAILY_REQUEST_LIMIT_REACHED = (17, "Open api daily request limit reached", "每天请求量超限额!", 1, 2)
|
||||
|
||||
API_QPS_REQUEST_LIMIT_REACHED = (18, "Open api qps request limit reached", "QPS超限额!", 1, 10)
|
||||
|
||||
API_TOTAL_REQUEST_LIMIT_REACHED = (19, "Open api total request limit reached", "请求总量超限额!", 1, 2)
|
||||
|
||||
INVALID_TOKEN = (100, "Invalid parameter", "无效的access_token参数,token拉取失败", 0, 1)
|
||||
|
||||
ACCESS_TOKEN_INVALID_OR_NO_LONGER_VALID = (110, "Access token invalid or no longer valid", "access_token无效,token有效期为30天", 0, 1)
|
||||
|
||||
ACCESS_TOKEN_EXPIRED = (111, "Access token expired", "access token过期,token有效期为30天", 0, 1)
|
||||
|
||||
INTERNAL_ERROR = (282000, "internal error", "服务器内部错误", 0, 1)
|
||||
|
||||
INVALID_PARAM = (216100, "invalid param", "请求中包含非法参数!", 0, 1)
|
||||
|
||||
NOT_ENOUGH_PARAM = (216101, "not enough param", "缺少必须的参数!", 0, 0)
|
||||
|
||||
SERVICE_NOT_SUPPORT = (216102, "service not support", "请求了不支持的服务,请检查调用的url", 0, 0)
|
||||
|
||||
PARAM_TOO_LONG = (216103, "param too long", "请求中某些参数过长!", 1, 0)
|
||||
|
||||
APPID_NOT_EXIST = (216110, "appid not exist", "appid不存在", 0, 0)
|
||||
|
||||
EMPTY_IMAGE = (216200, "empty image", "图片为空!", 1, 0)
|
||||
|
||||
IMAGE_FORMAT_ERROR = (216201, "image format error", "上传的图片格式错误,现阶段我们支持的图片格式为:PNG、JPG、JPEG、BMP", 1, 0)
|
||||
|
||||
IMAGE_SIZE_ERROR = (216202, "image size error", "上传的图片大小错误,分辨率不高于4096*4096", 1, 0)
|
||||
|
||||
IMAGE_SIZE_BASE_ERROR = (216203, "image size error", "上传的图片编码有误", 1, 0)
|
||||
|
||||
RECOGNIZE_ERROR = (216630, "recognize error", "识别错误", 2, 2)
|
||||
|
||||
DETECT_ERROR = (216634, "detect error", "检测错误", 2, 2)
|
||||
|
||||
MISSING_PARAMETERS = (282003, "missing parameters: {参数名}", "请求参数缺失", 0, 0)
|
||||
|
||||
BATCH_ROCESSING_ERROR = (282005, "batch processing error", "处理批量任务时发生部分或全部错误", 0, 5)
|
||||
|
||||
BATCH_TASK_LIMIT_REACHED = (282006, "batch task limit reached", "批量任务处理数量超出限制,请将任务数量减少到10或10以下", 1, 5)
|
||||
|
||||
IMAGE_TRANSCODE_ERROR = (282100, "image transcode error", "图片压缩转码错误", 0, 1)
|
||||
|
||||
IMAGE_SPLIT_LIMIT_REACHED = (282101, "image split limit reached", "长图片切分数量超限!", 1, 1)
|
||||
|
||||
TARGET_DETECT_ERROR = (282102, "target detect error", "未检测到图片中识别目标!", 2, 1)
|
||||
|
||||
TARGET_RECOGNIZE_ERROR = (282103, "target recognize error", "图片目标识别错误!", 2, 1)
|
||||
|
||||
URLS_NOT_EXIT = (282110, "urls not exit", "URL参数不存在,请核对URL后再次提交!", 1, 0)
|
||||
|
||||
URL_FORMAT_ILLEGAL = (282111, "url format illegal", "URL格式非法!", 1, 0)
|
||||
|
||||
URL_DOWNLOAD_TIMEOUT = (282112, "url download timeout", "URL格式非法!", 1, 0)
|
||||
|
||||
URL_RESPONSE_INVALID = (282113, "url response invalid", "URL返回无效参数!", 1, 0)
|
||||
|
||||
URL_SIZE_ERROR = (282114, "url size error", "URL长度超过1024字节或为0!", 1, 0)
|
||||
|
||||
REQUEST_ID_NOT_EXIST = (282808, "request id: xxxxx not exist", "request id xxxxx 不存在", 0, 0)
|
||||
|
||||
RESULT_TYPE_ERROR = (282809, "result type error", "返回结果请求错误(不属于excel或json)", 0, 0)
|
||||
|
||||
IMAGE_RECOGNIZE_ERROR = (282810, "image recognize error", "图像识别错误", 2, 1)
|
||||
|
||||
INVALID_ARGUMENT = (283300, "Invalid argument", "入参格式有误,可检查下图片编码、代码格式是否有误", 1, 0)
|
||||
|
||||
INTERNAL_ERROR_2 = (336000, "Internal error", "服务器内部错误", 0, 0)
|
||||
|
||||
INVALID_ARGUMENT_2 = (336001, "Invalid Argument", "入参格式有误,比如缺少必要参数、图片编码错误等等,可检查下图片编码、代码格式是否有误", 0, 0)
|
||||
|
||||
SDK_IMAGE_SIZE_ERROR = ('SDK100', "image size error", "图片大小超限,最短边至少50px,最长边最大4096px ,建议长宽比3:1以内,图片请求格式支持:PNG、JPG、BMP", 1, 0)
|
||||
|
||||
SDK_IMAGE_LENGTH_ERROR = ('SDK101', "image length error", "图片边长不符合要求,最短边至少50px,最长边最大4096px ,建议长宽比3:1以内", 1, 0)
|
||||
|
||||
SDK_READ_IMAGE_FILE_ERROR = ('SDK102', "read image file error", "读取图片文件错误", 0, 1)
|
||||
|
||||
SDK_CONNECTION_OR_READ_DATA_TIME_OUT = ('SDK108', "connection or read data time out", "连接超时或读取数据超时,请检查本地网络设置、文件读取设置", 0, 3)
|
||||
|
||||
SDK_UNSUPPORTED_IMAGE_FORMAT = ('SDK109', "unsupported image format", "不支持的图片格式,当前支持以下几类图片:PNG、JPG、BMP", 1, 0)
|
||||
|
||||
|
||||
BAIDUERRORDATA = {
|
||||
BaiduSdkErrorEnum.UNKNOWN_ERROR.value[0]: BaiduSdkErrorEnum.UNKNOWN_ERROR,
|
||||
BaiduSdkErrorEnum.SERVICE_TEMPORARILY_UNAVAILABLE.value[0]: BaiduSdkErrorEnum.SERVICE_TEMPORARILY_UNAVAILABLE,
|
||||
BaiduSdkErrorEnum.UNSUPPORTED_OPENAPI_METHOD.value[0]: BaiduSdkErrorEnum.UNSUPPORTED_OPENAPI_METHOD,
|
||||
BaiduSdkErrorEnum.API_REQUEST_LIMIT_REACHED.value[0]: BaiduSdkErrorEnum.API_REQUEST_LIMIT_REACHED,
|
||||
BaiduSdkErrorEnum.NO_PERMISSION_TO_ACCESS_DATA.value[0]: BaiduSdkErrorEnum.NO_PERMISSION_TO_ACCESS_DATA,
|
||||
BaiduSdkErrorEnum.GET_SERVICE_TOKEN_FAILED.value[0]: BaiduSdkErrorEnum.GET_SERVICE_TOKEN_FAILED,
|
||||
BaiduSdkErrorEnum.IAM_CERTIFICATION_FAILED.value[0]: BaiduSdkErrorEnum.IAM_CERTIFICATION_FAILED,
|
||||
BaiduSdkErrorEnum.APP_NOT_EXSITS_OR_CREATE_FAILED.value[0]: BaiduSdkErrorEnum.APP_NOT_EXSITS_OR_CREATE_FAILED,
|
||||
BaiduSdkErrorEnum.API_DAILY_REQUEST_LIMIT_REACHED.value[0]: BaiduSdkErrorEnum.API_DAILY_REQUEST_LIMIT_REACHED,
|
||||
BaiduSdkErrorEnum.API_QPS_REQUEST_LIMIT_REACHED.value[0]: BaiduSdkErrorEnum.API_QPS_REQUEST_LIMIT_REACHED,
|
||||
BaiduSdkErrorEnum.API_TOTAL_REQUEST_LIMIT_REACHED.value[0]: BaiduSdkErrorEnum.API_TOTAL_REQUEST_LIMIT_REACHED,
|
||||
BaiduSdkErrorEnum.INVALID_TOKEN.value[0]: BaiduSdkErrorEnum.INVALID_TOKEN,
|
||||
BaiduSdkErrorEnum.ACCESS_TOKEN_INVALID_OR_NO_LONGER_VALID.value[0]: BaiduSdkErrorEnum.ACCESS_TOKEN_INVALID_OR_NO_LONGER_VALID,
|
||||
BaiduSdkErrorEnum.ACCESS_TOKEN_EXPIRED.value[0]: BaiduSdkErrorEnum.ACCESS_TOKEN_EXPIRED,
|
||||
BaiduSdkErrorEnum.INTERNAL_ERROR.value[0]: BaiduSdkErrorEnum.INTERNAL_ERROR,
|
||||
BaiduSdkErrorEnum.INVALID_PARAM.value[0]: BaiduSdkErrorEnum.INVALID_PARAM,
|
||||
BaiduSdkErrorEnum.NOT_ENOUGH_PARAM.value[0]: BaiduSdkErrorEnum.NOT_ENOUGH_PARAM,
|
||||
BaiduSdkErrorEnum.SERVICE_NOT_SUPPORT.value[0]: BaiduSdkErrorEnum.SERVICE_NOT_SUPPORT,
|
||||
BaiduSdkErrorEnum.PARAM_TOO_LONG.value[0]: BaiduSdkErrorEnum.PARAM_TOO_LONG,
|
||||
BaiduSdkErrorEnum.APPID_NOT_EXIST.value[0]: BaiduSdkErrorEnum.APPID_NOT_EXIST,
|
||||
BaiduSdkErrorEnum.EMPTY_IMAGE.value[0]: BaiduSdkErrorEnum.EMPTY_IMAGE,
|
||||
BaiduSdkErrorEnum.IMAGE_FORMAT_ERROR.value[0]: BaiduSdkErrorEnum.IMAGE_FORMAT_ERROR,
|
||||
BaiduSdkErrorEnum.IMAGE_SIZE_ERROR.value[0]: BaiduSdkErrorEnum.IMAGE_SIZE_ERROR,
|
||||
BaiduSdkErrorEnum.IMAGE_SIZE_BASE_ERROR.value[0]: BaiduSdkErrorEnum.IMAGE_SIZE_BASE_ERROR,
|
||||
BaiduSdkErrorEnum.RECOGNIZE_ERROR.value[0]: BaiduSdkErrorEnum.RECOGNIZE_ERROR,
|
||||
BaiduSdkErrorEnum.DETECT_ERROR.value[0]: BaiduSdkErrorEnum.DETECT_ERROR,
|
||||
BaiduSdkErrorEnum.MISSING_PARAMETERS.value[0]: BaiduSdkErrorEnum.MISSING_PARAMETERS,
|
||||
BaiduSdkErrorEnum.BATCH_ROCESSING_ERROR.value[0]: BaiduSdkErrorEnum.BATCH_ROCESSING_ERROR,
|
||||
BaiduSdkErrorEnum.BATCH_TASK_LIMIT_REACHED.value[0]: BaiduSdkErrorEnum.BATCH_TASK_LIMIT_REACHED,
|
||||
BaiduSdkErrorEnum.IMAGE_TRANSCODE_ERROR.value[0]: BaiduSdkErrorEnum.IMAGE_TRANSCODE_ERROR,
|
||||
BaiduSdkErrorEnum.IMAGE_SPLIT_LIMIT_REACHED.value[0]: BaiduSdkErrorEnum.IMAGE_SPLIT_LIMIT_REACHED,
|
||||
BaiduSdkErrorEnum.TARGET_DETECT_ERROR.value[0]: BaiduSdkErrorEnum.TARGET_DETECT_ERROR,
|
||||
BaiduSdkErrorEnum.TARGET_RECOGNIZE_ERROR.value[0]: BaiduSdkErrorEnum.TARGET_RECOGNIZE_ERROR,
|
||||
BaiduSdkErrorEnum.URL_SIZE_ERROR.value[0]: BaiduSdkErrorEnum.URL_SIZE_ERROR,
|
||||
BaiduSdkErrorEnum.REQUEST_ID_NOT_EXIST.value[0]: BaiduSdkErrorEnum.REQUEST_ID_NOT_EXIST,
|
||||
BaiduSdkErrorEnum.RESULT_TYPE_ERROR.value[0]: BaiduSdkErrorEnum.RESULT_TYPE_ERROR,
|
||||
BaiduSdkErrorEnum.IMAGE_RECOGNIZE_ERROR.value[0]: BaiduSdkErrorEnum.IMAGE_RECOGNIZE_ERROR,
|
||||
BaiduSdkErrorEnum.INVALID_ARGUMENT.value[0]: BaiduSdkErrorEnum.INVALID_ARGUMENT,
|
||||
BaiduSdkErrorEnum.INTERNAL_ERROR_2.value[0]: BaiduSdkErrorEnum.INTERNAL_ERROR_2,
|
||||
BaiduSdkErrorEnum.INVALID_ARGUMENT_2.value[0]: BaiduSdkErrorEnum.INVALID_ARGUMENT_2,
|
||||
BaiduSdkErrorEnum.SDK_IMAGE_SIZE_ERROR.value[0]: BaiduSdkErrorEnum.SDK_IMAGE_SIZE_ERROR,
|
||||
BaiduSdkErrorEnum.SDK_IMAGE_LENGTH_ERROR.value[0]: BaiduSdkErrorEnum.SDK_IMAGE_LENGTH_ERROR,
|
||||
BaiduSdkErrorEnum.SDK_READ_IMAGE_FILE_ERROR.value[0]: BaiduSdkErrorEnum.SDK_READ_IMAGE_FILE_ERROR,
|
||||
BaiduSdkErrorEnum.SDK_CONNECTION_OR_READ_DATA_TIME_OUT.value[0]: BaiduSdkErrorEnum.SDK_CONNECTION_OR_READ_DATA_TIME_OUT,
|
||||
BaiduSdkErrorEnum.SDK_UNSUPPORTED_IMAGE_FORMAT.value[0]: BaiduSdkErrorEnum.SDK_UNSUPPORTED_IMAGE_FORMAT,
|
||||
BaiduSdkErrorEnum.URLS_NOT_EXIT.value[0]: BaiduSdkErrorEnum.URLS_NOT_EXIT,
|
||||
BaiduSdkErrorEnum.URL_FORMAT_ILLEGAL.value[0]: BaiduSdkErrorEnum.URL_FORMAT_ILLEGAL,
|
||||
BaiduSdkErrorEnum.URL_DOWNLOAD_TIMEOUT.value[0]: BaiduSdkErrorEnum.URL_DOWNLOAD_TIMEOUT,
|
||||
BaiduSdkErrorEnum.URL_RESPONSE_INVALID.value[0]: BaiduSdkErrorEnum.URL_RESPONSE_INVALID
|
||||
}
|
||||
|
||||
@unique
|
||||
class VehicleEnum(Enum):
|
||||
CAR = ("car", "小汽车", 0)
|
||||
TRICYCLE = ("tricycle", "三轮车", 1)
|
||||
MOTORBIKE = ("motorbike", "摩托车", 2)
|
||||
CARPLATE = ("carplate", "车牌", 3)
|
||||
TRUCK = ("truck", "卡车", 4)
|
||||
BUS = ("bus", "巴士", 5)
|
||||
|
||||
|
||||
VehicleEnumVALUE={
|
||||
VehicleEnum.CAR.value[0]: VehicleEnum.CAR,
|
||||
VehicleEnum.TRICYCLE.value[0]: VehicleEnum.TRICYCLE,
|
||||
VehicleEnum.MOTORBIKE.value[0]: VehicleEnum.MOTORBIKE,
|
||||
VehicleEnum.CARPLATE.value[0]: VehicleEnum.CARPLATE,
|
||||
VehicleEnum.TRUCK.value[0]: VehicleEnum.TRUCK,
|
||||
VehicleEnum.BUS.value[0]: VehicleEnum.BUS
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
from enum import Enum, unique
|
||||
|
||||
|
||||
# 异常枚举
|
||||
@unique
|
||||
class ExceptionType(Enum):
|
||||
|
||||
OR_VIDEO_ADDRESS_EXCEPTION = ("SP000", "未拉取到视频流, 请检查拉流地址是否有视频流!")
|
||||
|
||||
ANALYSE_TIMEOUT_EXCEPTION = ("SP001", "AI分析超时!")
|
||||
|
||||
PULLSTREAM_TIMEOUT_EXCEPTION = ("SP002", "原视频拉流超时!")
|
||||
|
||||
READSTREAM_TIMEOUT_EXCEPTION = ("SP003", "原视频读取视频流超时!")
|
||||
|
||||
GET_VIDEO_URL_EXCEPTION = ("SP004", "获取视频播放地址失败!")
|
||||
|
||||
GET_VIDEO_URL_TIMEOUT_EXCEPTION = ("SP005", "获取原视频播放地址超时!")
|
||||
|
||||
PULL_STREAM_URL_EXCEPTION = ("SP006", "拉流地址不能为空!")
|
||||
|
||||
PUSH_STREAM_URL_EXCEPTION = ("SP007", "推流地址不能为空!")
|
||||
|
||||
PUSH_STREAM_TIME_EXCEPTION = ("SP008", "未生成本地视频地址!")
|
||||
|
||||
AI_MODEL_MATCH_EXCEPTION = ("SP009", "未匹配到对应的AI模型!")
|
||||
|
||||
ILLEGAL_PARAMETER_FORMAT = ("SP010", "非法参数格式!")
|
||||
|
||||
PUSH_STREAMING_CHANNEL_IS_OCCUPIED = ("SP011", "推流通道可能被占用, 请稍后再试!")
|
||||
|
||||
VIDEO_RESOLUTION_EXCEPTION = ("SP012", "不支持该分辨率类型的视频,请切换分辨率再试!")
|
||||
|
||||
READ_IAMGE_URL_EXCEPTION = ("SP013", "未能解析图片地址!")
|
||||
|
||||
DETECTION_TARGET_TYPES_ARE_NOT_SUPPORTED = ("SP014", "不支持该类型的检测目标!")
|
||||
|
||||
WRITE_STREAM_EXCEPTION = ("SP015", "写流异常!")
|
||||
|
||||
OR_VIDEO_DO_NOT_EXEIST_EXCEPTION = ("SP016", "原视频不存在!")
|
||||
|
||||
MODEL_LOADING_EXCEPTION = ("SP017", "模型加载异常!")
|
||||
|
||||
MODEL_ANALYSE_EXCEPTION = ("SP018", "算法模型分析异常!")
|
||||
|
||||
AI_MODEL_CONFIG_EXCEPTION = ("SP019", "模型配置不能为空!")
|
||||
|
||||
AI_MODEL_GET_CONFIG_EXCEPTION = ("SP020", "获取模型配置异常, 请检查模型配置是否正确!")
|
||||
|
||||
MODEL_GROUP_LIMIT_EXCEPTION = ("SP021", "模型组合个数超过限制!")
|
||||
|
||||
MODEL_NOT_SUPPORT_VIDEO_EXCEPTION = ("SP022", "%s不支持视频识别!")
|
||||
|
||||
MODEL_NOT_SUPPORT_IMAGE_EXCEPTION = ("SP023", "%s不支持图片识别!")
|
||||
|
||||
THE_DETECTION_TARGET_CANNOT_BE_EMPTY = ("SP024", "检测目标不能为空!")
|
||||
|
||||
URL_ADDRESS_ACCESS_FAILED = ("SP025", "URL地址访问失败, 请检测URL地址是否正确!")
|
||||
|
||||
UNIVERSAL_TEXT_RECOGNITION_FAILED = ("SP026", "识别失败!")
|
||||
|
||||
COORDINATE_ACQUISITION_FAILED = ("SP027", "飞行坐标识别异常!")
|
||||
|
||||
PUSH_STREAM_EXCEPTION = ("SP028", "推流异常!")
|
||||
|
||||
MODEL_DUPLICATE_EXCEPTION = ("SP029", "存在重复模型配置!")
|
||||
|
||||
DETECTION_TARGET_NOT_SUPPORT = ("SP031", "存在不支持的检测目标!")
|
||||
|
||||
TASK_EXCUTE_TIMEOUT = ("SP032", "任务执行超时!")
|
||||
|
||||
PUSH_STREAM_URL_IS_NULL = ("SP033", "拉流、推流地址不能为空!")
|
||||
|
||||
PULL_STREAM_NUM_LIMIT_EXCEPTION = ("SP034", "转推流数量超过限制!")
|
||||
|
||||
NOT_REQUESTID_TASK_EXCEPTION = ("SP993", "未查询到该任务,无法停止任务!")
|
||||
|
||||
NO_RESOURCES = ("SP995", "服务器暂无资源可以使用,请稍后30秒后再试!")
|
||||
|
||||
NO_CPU_RESOURCES = ("SP996", "暂无CPU资源可以使用,请稍后再试!")
|
||||
|
||||
SERVICE_COMMON_EXCEPTION = ("SP997", "公共服务异常!")
|
||||
|
||||
NO_GPU_RESOURCES = ("SP998", "暂无GPU资源可以使用,请稍后再试!")
|
||||
|
||||
SERVICE_INNER_EXCEPTION = ("SP999", "系统内部异常!")
|
||||
|
|
@ -0,0 +1,768 @@
|
|||
import sys
|
||||
from enum import Enum, unique
|
||||
|
||||
from common.Constant import COLOR
|
||||
|
||||
sys.path.extend(['..', '../AIlib2'])
|
||||
from DMPR import DMPRModel
|
||||
from DMPRUtils.jointUtil import dmpr_yolo
|
||||
from segutils.segmodel import SegModel
|
||||
from utilsK.queRiver import riverDetSegMixProcess
|
||||
from utilsK.crowdGather import gather_post_process
|
||||
from segutils.trafficUtils import tracfficAccidentMixFunction
|
||||
from utilsK.drownUtils import mixDrowing_water_postprocess
|
||||
from utilsK.noParkingUtils import mixNoParking_road_postprocess
|
||||
from utilsK.illParkingUtils import illParking_postprocess
|
||||
from stdc import stdcModel
|
||||
from yolov5 import yolov5Model
|
||||
from DMPRUtils.jointUtil import dmpr_yolo_stdc
|
||||
from AI import default_mix
|
||||
from ocr import ocrModel
|
||||
from utilsK.channel2postUtils import channel2_post_process
|
||||
|
||||
'''
|
||||
参数说明
|
||||
1. 编号
|
||||
2. 模型编号
|
||||
3. 模型名称
|
||||
4. 选用的模型名称
|
||||
5. 模型配置
|
||||
6. 模型引用配置[Detweights文件, Segweights文件, 引用计数]
|
||||
'''
|
||||
|
||||
|
||||
@unique
|
||||
class ModelType(Enum):
|
||||
WATER_SURFACE_MODEL = ("1", "001", "河道模型", 'river', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["排口", "水生植被", "其它", "漂浮物", "污染排口", "菜地", "违建", "岸坡垃圾"],
|
||||
'seg_nclass': 2,
|
||||
'trtFlag_seg': True,
|
||||
'trtFlag_det': True,
|
||||
'segRegionCnt': 1,
|
||||
'segPar': {
|
||||
'modelSize': (640, 360),
|
||||
'mean': (0.485, 0.456, 0.406),
|
||||
'std': (0.229, 0.224, 0.225),
|
||||
'numpy': False,
|
||||
'RGB_convert_first': True,
|
||||
'mixFunction': {
|
||||
'function': riverDetSegMixProcess,
|
||||
'pars': {
|
||||
'slopeIndex': [5, 6, 7],
|
||||
'riverIou': 0.1
|
||||
}
|
||||
}
|
||||
},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Detweights': "../AIlib2/weights/river/yolov5_%s_fp16.engine" % gpuName,
|
||||
'Segweights': '../AIlib2/weights/river/stdc_360X640_%s_fp16.engine' % gpuName
|
||||
})
|
||||
|
||||
# FOREST_FARM_MODEL = ("2", "002", "森林模型", 'forest2', lambda device, gpuName: {
|
||||
# 'device': device,
|
||||
# 'gpu_name': gpuName,
|
||||
# 'labelnames': ["林斑", "病死树", "行人", "火焰", "烟雾","云朵"],
|
||||
# 'trtFlag_det': True,
|
||||
# 'trtFlag_seg': False,
|
||||
# 'Detweights': "../AIlib2/weights/forest2/yolov5_%s_fp16.engine" % gpuName,
|
||||
# 'seg_nclass': 2,
|
||||
# 'segRegionCnt': 0,
|
||||
# 'slopeIndex': [],
|
||||
# 'segPar': None,
|
||||
# 'postFile': {
|
||||
# "name": "post_process",
|
||||
# "conf_thres": 0.25,
|
||||
# "iou_thres": 0.45,
|
||||
# "classes": 6,
|
||||
# "rainbows": COLOR
|
||||
# },
|
||||
# 'Segweights': None
|
||||
# })
|
||||
|
||||
|
||||
FOREST_FARM_MODEL = ("2", "002", "森林模型", 'forest2', lambda device, gpuName: {
|
||||
'labelnames': ["林斑", "病死树", "行人", "火焰", "烟雾","云朵"],
|
||||
'postProcess':{'function':default_mix,'pars':{}},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/forest2/yolov5_%s_fp16.engine"%(gpuName),###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':[0,1,2,3],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
}
|
||||
|
||||
|
||||
],
|
||||
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,4,5,6,7,8,9] ],###控制哪些检测类别显示、输出
|
||||
'segRegionCnt':2,###分割模型结果需要保留的等值线数目
|
||||
"pixScale": 1.2,
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
TRAFFIC_FARM_MODEL = ("3", "003", "交通模型", 'highWay2', lambda device, gpuName: {
|
||||
'device': str(device),
|
||||
'labelnames': ["行人", "车辆", "纵向裂缝", "横向裂缝", "修补", "网状裂纹", "坑槽", "块状裂纹", "积水", "影子", "事故"],
|
||||
'trtFlag_seg': True,
|
||||
'trtFlag_det': True,
|
||||
'seg_nclass': 3,
|
||||
'segRegionCnt': 2,
|
||||
'segPar': {
|
||||
'modelSize': (640, 360),
|
||||
'mean': (0.485, 0.456, 0.406),
|
||||
'std': (0.229, 0.224, 0.225),
|
||||
'predResize': True,
|
||||
'numpy': False,
|
||||
'RGB_convert_first': True,
|
||||
'mixFunction': {
|
||||
'function': tracfficAccidentMixFunction,
|
||||
'pars': {
|
||||
'modelSize': (640, 360),
|
||||
#'modelSize': (1920,1080),
|
||||
'RoadArea': 16000,
|
||||
'roadVehicleAngle': 15,
|
||||
'speedRoadVehicleAngleMax': 75,
|
||||
'roundness': 1.0,
|
||||
'cls': 9,
|
||||
'vehicleFactor': 0.1,
|
||||
'confThres': 0.25,
|
||||
'roadIou': 0.6,
|
||||
'radius': 50,
|
||||
'vehicleFlag': False,
|
||||
'distanceFlag': False
|
||||
}
|
||||
}
|
||||
},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.25,
|
||||
"classes": 10,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Detweights': "../AIlib2/weights/highWay2/yolov5_%s_fp16.engine" % gpuName,
|
||||
'Segweights': '../AIlib2/weights/highWay2/stdc_360X640_%s_fp16.engine' % gpuName
|
||||
})
|
||||
|
||||
EPIDEMIC_PREVENTION_MODEL = ("4", "004", "防疫模型", None, None)
|
||||
|
||||
PLATE_MODEL = ("5", "005", "车牌模型", None, None)
|
||||
|
||||
VEHICLE_MODEL = ("6", "006", "车辆模型", 'vehicle', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'gpu_name': gpuName,
|
||||
'labelnames': ["车辆"],
|
||||
'seg_nclass': 2,
|
||||
'segRegionCnt': 0,
|
||||
'slopeIndex': [],
|
||||
'trtFlag_det': True,
|
||||
'trtFlag_seg': False,
|
||||
'Detweights': "../AIlib2/weights/vehicle/yolov5_%s_fp16.engine" % gpuName,
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Segweights': None
|
||||
})
|
||||
|
||||
PEDESTRIAN_MODEL = ("7", "007", "行人模型", 'pedestrian', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'gpu_name': gpuName,
|
||||
'labelnames': ["行人"],
|
||||
'seg_nclass': 2,
|
||||
'segRegionCnt': 0,
|
||||
'trtFlag_det': True,
|
||||
'trtFlag_seg': False,
|
||||
'Detweights': "../AIlib2/weights/pedestrian/yolov5_%s_fp16.engine" % gpuName,
|
||||
'slopeIndex': [],
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Segweights': None
|
||||
})
|
||||
|
||||
SMOGFIRE_MODEL = ("8", "008", "烟火模型", 'smogfire', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'gpu_name': gpuName,
|
||||
'labelnames': ["火焰", "烟雾"],
|
||||
'seg_nclass': 2, # 分割模型类别数目,默认2类
|
||||
'segRegionCnt': 0,
|
||||
'trtFlag_det': True,
|
||||
'trtFlag_seg': False,
|
||||
'Detweights': "../AIlib2/weights/smogfire/yolov5_%s_fp16.engine" % gpuName,
|
||||
'slopeIndex': [],
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Segweights': None
|
||||
})
|
||||
|
||||
ANGLERSWIMMER_MODEL = ("9", "009", "钓鱼游泳模型", 'AnglerSwimmer', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'gpu_name': gpuName,
|
||||
'labelnames': ["钓鱼", "游泳"],
|
||||
'seg_nclass': 2, # 分割模型类别数目,默认2类
|
||||
'segRegionCnt': 0,
|
||||
'slopeIndex': [],
|
||||
'trtFlag_det': True,
|
||||
'trtFlag_seg': False,
|
||||
'Detweights': "../AIlib2/weights/AnglerSwimmer/yolov5_%s_fp16.engine" % gpuName,
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Segweights': None
|
||||
})
|
||||
|
||||
COUNTRYROAD_MODEL = ("10", "010", "乡村模型", 'countryRoad', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'gpu_name': gpuName,
|
||||
'labelnames': ["违法种植"],
|
||||
'seg_nclass': 2, # 分割模型类别数目,默认2类
|
||||
'segRegionCnt': 0,
|
||||
'slopeIndex': [],
|
||||
'trtFlag_det': True,
|
||||
'trtFlag_seg': False,
|
||||
'Detweights': "../AIlib2/weights/countryRoad/yolov5_%s_fp16.engine" % gpuName,
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Segweights': None
|
||||
})
|
||||
|
||||
SHIP_MODEL = ("11", "011", "船只模型", 'ship2', lambda device, gpuName: {
|
||||
'model_size': (608, 608),
|
||||
'K': 100,
|
||||
'conf_thresh': 0.18,
|
||||
'device': 'cuda:%s' % device,
|
||||
'down_ratio': 4,
|
||||
'num_classes': 15,
|
||||
'weights': '../AIlib2/weights/ship2/obb_608X608_%s_fp16.engine' % gpuName,
|
||||
'dataset': 'dota',
|
||||
'half': False,
|
||||
'mean': (0.5, 0.5, 0.5),
|
||||
'std': (1, 1, 1),
|
||||
'heads': {'hm': None, 'wh': 10, 'reg': 2, 'cls_theta': 1},
|
||||
'decoder': None,
|
||||
'test_flag': True,
|
||||
"rainbows": COLOR,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'drawBox': False,
|
||||
'label_array': None,
|
||||
'labelnames': ("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "船只"),
|
||||
})
|
||||
|
||||
BAIDU_MODEL = ("12", "012", "百度AI图片识别模型", None, None)
|
||||
|
||||
CHANNEL_EMERGENCY_MODEL = ("13", "013", "航道模型", 'channelEmergency', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'gpu_name': gpuName,
|
||||
'labelnames': ["人"],
|
||||
'seg_nclass': 2, # 分割模型类别数目,默认2类
|
||||
'segRegionCnt': 0,
|
||||
'slopeIndex': [],
|
||||
'trtFlag_det': True,
|
||||
'trtFlag_seg': False,
|
||||
'Detweights': "../AIlib2/weights/channelEmergency/yolov5_%s_fp16.engine" % gpuName,
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Segweights': None
|
||||
})
|
||||
|
||||
RIVER2_MODEL = ("15", "015", "河道检测模型", 'river2', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["漂浮物", "岸坡垃圾", "排口", "违建", "菜地", "水生植物", "河湖人员", "钓鱼人员", "船只",
|
||||
"蓝藻"],
|
||||
'trtFlag_seg': True,
|
||||
'trtFlag_det': True,
|
||||
'seg_nclass': 2,
|
||||
'segRegionCnt': 1,
|
||||
'segPar': {
|
||||
'modelSize': (640, 360),
|
||||
'mean': (0.485, 0.456, 0.406),
|
||||
'std': (0.229, 0.224, 0.225),
|
||||
'numpy': False,
|
||||
'RGB_convert_first': True,
|
||||
'mixFunction': {
|
||||
'function': riverDetSegMixProcess,
|
||||
'pars': {
|
||||
'slopeIndex': [1, 3, 4, 7],
|
||||
'riverIou': 0.1
|
||||
}
|
||||
}
|
||||
},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.3,
|
||||
"ovlap_thres_crossCategory": 0.65,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
# "../AIlib2/weights/conf/%s/yolov5.pt" % modeType.value[3]
|
||||
'Detweights': "../AIlib2/weights/river2/yolov5_%s_fp16.engine" % gpuName,
|
||||
# '../AIlib2/weights/conf/%s/stdc_360X640.pth' % modeType.value[3]
|
||||
'Segweights': '../AIlib2/weights/river2/stdc_360X640_%s_fp16.engine' % gpuName
|
||||
})
|
||||
|
||||
CITY_MANGEMENT_MODEL = ("16", "016", "城管模型", 'cityMangement2', lambda device, gpuName: {
|
||||
'labelnames': ["车辆", "垃圾", "商贩", "违停"],
|
||||
'postProcess':{
|
||||
'function':dmpr_yolo_stdc,
|
||||
'pars':{'carCls':0 ,'illCls':3,'scaleRatio':0.5,'border':80,'rubCls': 1, 'Rubfilter': 150}
|
||||
},
|
||||
'models':[
|
||||
{
|
||||
#'weight':'../AIlib2/weights/conf/cityMangement3/yolov5.pt',
|
||||
'weight':'../AIlib2/weights/cityMangement3/yolov5_%s_fp16.engine'%(gpuName),
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.5,'allowedList':[0,1,2,3],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.8,"1":0.4,"2":0.5,"3":0.5 } }
|
||||
},
|
||||
{
|
||||
'weight':'../AIlib2/weights/conf/cityMangement3/dmpr.pth',
|
||||
'par':{
|
||||
'depth_factor':32,'NUM_FEATURE_MAP_CHANNEL':6,'dmpr_thresh':0.1, 'dmprimg_size':640,
|
||||
'name':'dmpr'
|
||||
},
|
||||
'model':DMPRModel,
|
||||
'name':'dmpr'
|
||||
},
|
||||
{
|
||||
'weight':'../AIlib2/weights/conf/cityMangement3/stdc_360X640.pth',
|
||||
|
||||
'par':{
|
||||
'modelSize':(640,360),'mean':(0.485, 0.456, 0.406),'std' :(0.229, 0.224, 0.225),'predResize':True,'numpy':False, 'RGB_convert_first':True,'seg_nclass':2},###分割模型预处理参数
|
||||
'model':stdcModel,
|
||||
'name':'stdc'
|
||||
}
|
||||
],
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.5,
|
||||
"iou_thres": 0.5,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,5,6,7,8,9] ],###控制哪些检测类别显示、输出
|
||||
'segRegionCnt':2,###分割模型结果需要保留的等值线数目
|
||||
"pixScale": 1.2,
|
||||
})
|
||||
|
||||
DROWING_MODEL = ("17", "017", "人员落水模型", 'drowning', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["人头", "人", "船只"],
|
||||
'trtFlag_seg': True,
|
||||
'trtFlag_det': True,
|
||||
'seg_nclass': 2,
|
||||
'segRegionCnt': 2,
|
||||
'segPar': {
|
||||
'modelSize': (640, 360),
|
||||
'mean': (0.485, 0.456, 0.406),
|
||||
'std': (0.229, 0.224, 0.225),
|
||||
'predResize': True,
|
||||
'numpy': False,
|
||||
'RGB_convert_first': True,
|
||||
'mixFunction': {
|
||||
'function': mixDrowing_water_postprocess,
|
||||
'pars': {
|
||||
'modelSize': (640, 360)
|
||||
}
|
||||
}
|
||||
},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.25,
|
||||
"classes": 9,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
# "../AIlib2/weights/conf/%s/yolov5.pt" % modeType.value[3]
|
||||
'Detweights': "../AIlib2/weights/drowning/yolov5_%s_fp16.engine" % gpuName,
|
||||
# '../AIlib2/weights/conf/%s/stdc_360X640.pth' % modeType.value[3]
|
||||
'Segweights': '../AIlib2/weights/drowning/stdc_360X640_%s_fp16.engine' % gpuName
|
||||
})
|
||||
|
||||
NOPARKING_MODEL = (
|
||||
"18", "018", "城市违章模型", 'noParking', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["车辆", "违停"],
|
||||
'trtFlag_seg': True,
|
||||
'trtFlag_det': True,
|
||||
'seg_nclass': 4,
|
||||
'segRegionCnt': 2,
|
||||
'segPar': {
|
||||
'modelSize': (640, 360),
|
||||
'mean': (0.485, 0.456, 0.406),
|
||||
'std': (0.229, 0.224, 0.225),
|
||||
'predResize': True,
|
||||
'numpy': False,
|
||||
'RGB_convert_first': True, ###分割模型预处理参数
|
||||
'mixFunction': {
|
||||
'function': mixNoParking_road_postprocess,
|
||||
'pars': {
|
||||
'modelSize': (640, 360),
|
||||
'roundness': 0.3,
|
||||
'cls': 9,
|
||||
'laneArea': 10,
|
||||
'laneAngleCha': 5,
|
||||
'RoadArea': 16000,
|
||||
'fitOrder':2
|
||||
}
|
||||
}
|
||||
},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.25,
|
||||
"classes": 9,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Detweights': "../AIlib2/weights/noParking/yolov5_%s_fp16.engine" % gpuName,
|
||||
'Segweights': '../AIlib2/weights/noParking/stdc_360X640_%s_fp16.engine' % gpuName
|
||||
})
|
||||
|
||||
ILLPARKING_MODEL = ("19", "019", "车辆违停模型", 'illParking', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["车", "T角点", "L角点", "违停"],
|
||||
'trtFlag_seg': False,
|
||||
'trtFlag_det': True,
|
||||
'seg_nclass': 4,
|
||||
'segRegionCnt': 2,
|
||||
'segPar': {
|
||||
'mixFunction': {
|
||||
'function': illParking_postprocess,
|
||||
'pars': {}
|
||||
}
|
||||
},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.25,
|
||||
"classes": 9,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Detweights': "../AIlib2/weights/illParking/yolov5_%s_fp16.engine" % gpuName,
|
||||
'Segweights': None
|
||||
})
|
||||
|
||||
CITYROAD_MODEL = ("20", "020", "城市公路模型", 'cityRoad', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["护栏", "交通标志", "非交通标志", "施工", "施工"],
|
||||
'trtFlag_seg': False,
|
||||
'trtFlag_det': True,
|
||||
'slopeIndex': [],
|
||||
'seg_nclass': 2,
|
||||
'segRegionCnt': 0,
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.5,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Detweights': "../AIlib2/weights/cityRoad/yolov5_%s_fp16.engine" % gpuName,
|
||||
'Segweights': None
|
||||
})
|
||||
|
||||
POTHOLE_MODEL = ("23", "023", "坑槽检测模型", 'pothole', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'gpu_name': gpuName,
|
||||
'labelnames': ["坑槽"],
|
||||
'seg_nclass': 2, # 分割模型类别数目,默认2类
|
||||
'segRegionCnt': 0,
|
||||
'slopeIndex': [],
|
||||
'trtFlag_det': True,
|
||||
'trtFlag_seg': False,
|
||||
'Detweights': "../AIlib2/weights/pothole/yolov5_%s_fp16.engine" % gpuName,
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Segweights': None,
|
||||
})
|
||||
|
||||
CHANNEL2_MODEL = ("24", "024", "船只综合检测模型", 'channel2', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'gpu_name': gpuName,
|
||||
|
||||
'labelnames': ["国旗", "浮标", "船名", "船只","未挂国旗船只","未封仓"], # 保持原来的标签顺序不变,方便后面业务端增加
|
||||
'segRegionCnt': 0,
|
||||
'postProcess':{'function':channel2_post_process,'name':'channel2','pars':{
|
||||
'objs':[2],
|
||||
'wRation':1/6.0,
|
||||
'hRation':1/6.0,
|
||||
'smallId':0, #旗帜
|
||||
'bigId':3, #船只
|
||||
'newId':4, #未挂国旗船只
|
||||
'uncoverId':5, #未封仓标签
|
||||
'recScale':1.2,
|
||||
'target_cls':3.0, #目标种类
|
||||
'filter_cls':4.0 #被过滤的种类
|
||||
}},
|
||||
'models':[
|
||||
{
|
||||
#'weight':'../AIlib2/weights/conf/channel2/yolov5.pt',
|
||||
# 'weight':'../AIlib2/weights/channel2/yolov5_%s_fp16.engine'%(gpuName),
|
||||
|
||||
'weight':'/home/thsw2/jcq/test/AIlib2/weights/channel2/best.pt', # yolov5 原来模型基础上增加了未封仓
|
||||
|
||||
# 'weight':'../AIlib2/weights/channel2/yolov5_%s_fp16.engine'%(gpuName),
|
||||
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.1,'iou_thres':0.45,'allowedList':list(range(20)),'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.7,"1":0.7,"2":0.8,"3":0.6} }
|
||||
},
|
||||
{
|
||||
# 'weight' : '../AIlib2/weights/ocr2/crnn_ch_4090_fp16_192X32.engine',
|
||||
'weight' : '../AIlib2/weights/conf/ocr2/crnn_ch.pth',
|
||||
'name':'ocr',
|
||||
'model':ocrModel,
|
||||
'par':{
|
||||
'char_file':'../AIlib2/weights/conf/ocr2/benchmark.txt',
|
||||
'mode':'ch',
|
||||
'nc':3,
|
||||
'imgH':32,
|
||||
'imgW':192,
|
||||
'hidden':256,
|
||||
'mean':[0.5,0.5,0.5],
|
||||
'std':[0.5,0.5,0.5],
|
||||
'dynamic':False,
|
||||
},
|
||||
} ,
|
||||
|
||||
|
||||
# {
|
||||
# 'weight':'/home/thsw2/jcq/test/AIlib2/weights1/conf/channel2/yolov5_04.pt', # yolov5_04 添加了uncover 0 4 ;标签 yolov5_jcq
|
||||
# 'name':'yolov5',
|
||||
# 'model':yolov5Model,
|
||||
# 'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.15,'iou_thres':0.25,'allowedList':list(range(20)),'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.7,"1":0.7,"2":0.8,"3":0.6} }
|
||||
# }
|
||||
|
||||
|
||||
],
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3]],
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Segweights': None,
|
||||
})
|
||||
|
||||
RIVERT_MODEL = ("25", "025", "河道检测模型(T)", 'riverT', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["漂浮物", "岸坡垃圾", "排口", "违建", "菜地", "水生植物", "河湖人员", "钓鱼人员", "船只",
|
||||
"蓝藻"],
|
||||
'trtFlag_seg': True,
|
||||
'trtFlag_det': True,
|
||||
'seg_nclass': 2,
|
||||
'segRegionCnt': 1,
|
||||
'segPar': {
|
||||
'modelSize': (640, 360),
|
||||
'mean': (0.485, 0.456, 0.406),
|
||||
'std': (0.229, 0.224, 0.225),
|
||||
'numpy': False,
|
||||
'RGB_convert_first': True,
|
||||
'mixFunction': {
|
||||
'function': riverDetSegMixProcess,
|
||||
'pars': {
|
||||
'slopeIndex': [1, 3, 4, 7],
|
||||
'riverIou': 0.1
|
||||
}
|
||||
}
|
||||
},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.3,
|
||||
"ovlap_thres_crossCategory": 0.65,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
# "../AIlib2/weights/conf/%s/yolov5.pt" % modeType.value[3]
|
||||
'Detweights': "../AIlib2/weights/riverT/yolov5_%s_fp16.engine" % gpuName,
|
||||
# '../AIlib2/weights/conf/%s/stdc_360X640.pth' % modeType.value[3]
|
||||
'Segweights': '../AIlib2/weights/riverT/stdc_360X640_%s_fp16.engine' % gpuName
|
||||
})
|
||||
|
||||
|
||||
|
||||
FORESTCROWD_FARM_MODEL = ("2", "026", "森林人群模型", 'forestCrowd', lambda device, gpuName: {
|
||||
'labelnames': ["林斑", "病死树", "行人", "火焰", "烟雾","人群"],
|
||||
'postProcess':{'function':gather_post_process,'pars':{'pedestrianId':2,'crowdThreshold':4,'gatherId':5,'distancePersonScale':2.0}},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/forestCrowd/yolov5_%s_fp16.engine"%(gpuName),###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.5,'allowedList':[0,1,2,3],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{ "0":0.25,"1":0.25,"2":0.6,"3":0.6,'4':0.6 ,'5':0.6 } },
|
||||
}
|
||||
|
||||
|
||||
],
|
||||
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,4,5,6,7,8,9] ],###控制哪些检测类别显示、输出
|
||||
'segRegionCnt':2,###分割模型结果需要保留的等值线数目
|
||||
"pixScale": 1.2,
|
||||
|
||||
|
||||
})
|
||||
TRAFFICFORDSJ_FARM_MODEL = ("27", "027", "交通模型-大数据局", 'highWay2T', lambda device, gpuName: {
|
||||
'device': str(device),
|
||||
'labelnames': ["行人", "车辆", "纵向裂缝", "横向裂缝", "修补", "网状裂纹", "坑槽", "块状裂纹", "积水", "影子", "事故", "桥梁外观","设施破损缺失","龙门架","防抛网","标识牌损坏","护栏损坏","钢筋裸露" ],
|
||||
'trtFlag_seg': True,
|
||||
'trtFlag_det': True,
|
||||
'seg_nclass': 3,
|
||||
'segRegionCnt': 2,
|
||||
'segPar': {
|
||||
'modelSize': (640, 360),
|
||||
'mean': (0.485, 0.456, 0.406),
|
||||
'std': (0.229, 0.224, 0.225),
|
||||
'predResize': True,
|
||||
'numpy': False,
|
||||
'RGB_convert_first': True,
|
||||
'mixFunction': {
|
||||
'function': tracfficAccidentMixFunction,
|
||||
'pars': {
|
||||
'modelSize': (640, 360),
|
||||
#'modelSize': (1920,1080),
|
||||
'RoadArea': 16000,
|
||||
'roadVehicleAngle': 15,
|
||||
'speedRoadVehicleAngleMax': 75,
|
||||
'roundness': 1.0,
|
||||
'cls': 9,
|
||||
'vehicleFactor': 0.1,
|
||||
'confThres': 0.25,
|
||||
'roadIou': 0.6,
|
||||
'radius': 50,
|
||||
'vehicleFlag': False,
|
||||
'distanceFlag': False
|
||||
}
|
||||
}
|
||||
},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.25,
|
||||
"classes": 10,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Detweights': "../AIlib2/weights/highWay2/yolov5_%s_fp16.engine" % gpuName,
|
||||
'Segweights': '../AIlib2/weights/highWay2/stdc_360X640_%s_fp16.engine' % gpuName
|
||||
})
|
||||
|
||||
|
||||
|
||||
@staticmethod
|
||||
def checkCode(code):
|
||||
for model in ModelType:
|
||||
if model.value[1] == code:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
'''
|
||||
参数1: 检测目标名称
|
||||
参数2: 检测目标
|
||||
参数3: 初始化百度检测客户端
|
||||
'''
|
||||
|
||||
|
||||
@unique
|
||||
class BaiduModelTarget(Enum):
|
||||
VEHICLE_DETECTION = (
|
||||
"车辆检测", 0, lambda client0, client1, url, request_id: client0.vehicleDetectUrl(url, request_id))
|
||||
|
||||
HUMAN_DETECTION = (
|
||||
"人体检测与属性识别", 1, lambda client0, client1, url, request_id: client1.bodyAttr(url, request_id))
|
||||
|
||||
PEOPLE_COUNTING = ("人流量统计", 2, lambda client0, client1, url, request_id: client1.bodyNum(url, request_id))
|
||||
|
||||
|
||||
BAIDU_MODEL_TARGET_CONFIG = {
|
||||
BaiduModelTarget.VEHICLE_DETECTION.value[1]: BaiduModelTarget.VEHICLE_DETECTION,
|
||||
BaiduModelTarget.HUMAN_DETECTION.value[1]: BaiduModelTarget.HUMAN_DETECTION,
|
||||
BaiduModelTarget.PEOPLE_COUNTING.value[1]: BaiduModelTarget.PEOPLE_COUNTING
|
||||
}
|
||||
|
||||
EPIDEMIC_PREVENTION_CONFIG = {1: "行程码", 2: "健康码"}
|
||||
|
||||
|
||||
# 模型分析方式
|
||||
@unique
|
||||
class ModelMethodTypeEnum(Enum):
|
||||
# 方式一: 正常识别方式
|
||||
NORMAL = 1
|
||||
|
||||
# 方式二: 追踪识别方式
|
||||
TRACE = 2
|
||||
|
|
@ -0,0 +1,807 @@
|
|||
import sys
|
||||
from enum import Enum, unique
|
||||
|
||||
from common.Constant import COLOR
|
||||
|
||||
sys.path.extend(['..', '../AIlib2'])
|
||||
from DMPR import DMPRModel
|
||||
from DMPRUtils.jointUtil import dmpr_yolo
|
||||
from segutils.segmodel import SegModel
|
||||
from utilsK.queRiver import riverDetSegMixProcess
|
||||
from utilsK.crowdGather import gather_post_process
|
||||
from segutils.trafficUtils import tracfficAccidentMixFunction
|
||||
from utilsK.drownUtils import mixDrowing_water_postprocess
|
||||
from utilsK.noParkingUtils import mixNoParking_road_postprocess
|
||||
from utilsK.illParkingUtils import illParking_postprocess
|
||||
from stdc import stdcModel
|
||||
from yolov5 import yolov5Model
|
||||
from DMPRUtils.jointUtil import dmpr_yolo_stdc
|
||||
from AI import default_mix
|
||||
from ocr import ocrModel
|
||||
from utilsK.channel2postUtils import channel2_post_process
|
||||
|
||||
'''
|
||||
参数说明
|
||||
1. 编号
|
||||
2. 模型编号
|
||||
3. 模型名称
|
||||
4. 选用的模型名称
|
||||
5. 模型配置
|
||||
6. 模型引用配置[Detweights文件, Segweights文件, 引用计数]
|
||||
'''
|
||||
|
||||
|
||||
@unique
|
||||
class ModelType(Enum):
|
||||
WATER_SURFACE_MODEL = ("1", "001", "河道模型", 'river', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["排口", "水生植被", "其它", "漂浮物", "污染排口", "菜地", "违建", "岸坡垃圾"],
|
||||
'seg_nclass': 2,
|
||||
'trtFlag_seg': True,
|
||||
'trtFlag_det': True,
|
||||
'segRegionCnt': 1,
|
||||
'segPar': {
|
||||
'modelSize': (640, 360),
|
||||
'mean': (0.485, 0.456, 0.406),
|
||||
'std': (0.229, 0.224, 0.225),
|
||||
'numpy': False,
|
||||
'RGB_convert_first': True,
|
||||
'mixFunction': {
|
||||
'function': riverDetSegMixProcess,
|
||||
'pars': {
|
||||
'slopeIndex': [5, 6, 7],
|
||||
'riverIou': 0.1
|
||||
}
|
||||
}
|
||||
},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Detweights': "../AIlib2/weights/river/yolov5_%s_fp16.engine" % gpuName,
|
||||
'Segweights': '../AIlib2/weights/river/stdc_360X640_%s_fp16.engine' % gpuName
|
||||
})
|
||||
|
||||
# FOREST_FARM_MODEL = ("2", "002", "森林模型", 'forest2', lambda device, gpuName: {
|
||||
# 'device': device,
|
||||
# 'gpu_name': gpuName,
|
||||
# 'labelnames': ["林斑", "病死树", "行人", "火焰", "烟雾","云朵"],
|
||||
# 'trtFlag_det': True,
|
||||
# 'trtFlag_seg': False,
|
||||
# 'Detweights': "../AIlib2/weights/forest2/yolov5_%s_fp16.engine" % gpuName,
|
||||
# 'seg_nclass': 2,
|
||||
# 'segRegionCnt': 0,
|
||||
# 'slopeIndex': [],
|
||||
# 'segPar': None,
|
||||
# 'postFile': {
|
||||
# "name": "post_process",
|
||||
# "conf_thres": 0.25,
|
||||
# "iou_thres": 0.45,
|
||||
# "classes": 6,
|
||||
# "rainbows": COLOR
|
||||
# },
|
||||
# 'Segweights': None
|
||||
# })
|
||||
|
||||
|
||||
FOREST_FARM_MODEL = ("2", "002", "森林模型", 'forest2', lambda device, gpuName: {
|
||||
'labelnames': ["林斑", "病死树", "行人", "火焰", "烟雾","云朵"],
|
||||
'postProcess':{'function':default_mix,'pars':{}},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/forest2/yolov5_%s_fp16.engine"%(gpuName),###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':[0,1,2,3],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
}
|
||||
|
||||
|
||||
],
|
||||
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,4,5,6,7,8,9] ],###控制哪些检测类别显示、输出
|
||||
'segRegionCnt':2,###分割模型结果需要保留的等值线数目
|
||||
"pixScale": 1.2,
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
TRAFFIC_FARM_MODEL = ("3", "003", "交通模型", 'highWay2', lambda device, gpuName: {
|
||||
'device': str(device),
|
||||
'labelnames': ["行人", "车辆", "纵向裂缝", "横向裂缝", "修补", "网状裂纹", "坑槽", "块状裂纹", "积水", "影子", "事故"],
|
||||
'trtFlag_seg': True,
|
||||
'trtFlag_det': True,
|
||||
'seg_nclass': 3,
|
||||
'segRegionCnt': 2,
|
||||
'segPar': {
|
||||
#'modelSize': (640, 360),
|
||||
'modelSize': (1920, 1080),
|
||||
'mean': (0.485, 0.456, 0.406),
|
||||
'std': (0.229, 0.224, 0.225),
|
||||
'predResize': True,
|
||||
'numpy': False,
|
||||
'RGB_convert_first': True,
|
||||
'mixFunction': {
|
||||
'function': tracfficAccidentMixFunction,
|
||||
'pars': {
|
||||
#'modelSize': (640, 360),
|
||||
'modelSize': (1920,1080),
|
||||
'RoadArea': 16000,
|
||||
'roadVehicleAngle': 15,
|
||||
'speedRoadVehicleAngleMax': 75,
|
||||
'roundness': 1.0,
|
||||
'cls': 10,
|
||||
'vehicleFactor': 0.1,
|
||||
'confThres': 0.25,
|
||||
'roadIou': 0.6,
|
||||
'radius': 50,
|
||||
'vehicleFlag': False,
|
||||
'distanceFlag': False
|
||||
}
|
||||
}
|
||||
},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.25,
|
||||
"classes": 10,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Detweights': "../AIlib2/weights/highWay2/yolov5_%s_fp16.engine" % gpuName,
|
||||
'Segweights': '../AIlib2/weights/highWay2/stdc_360X640_%s_fp16.engine' % gpuName
|
||||
})
|
||||
|
||||
EPIDEMIC_PREVENTION_MODEL = ("4", "004", "防疫模型", None, None)
|
||||
|
||||
PLATE_MODEL = ("5", "005", "车牌模型", None, None)
|
||||
|
||||
VEHICLE_MODEL = ("6", "006", "车辆模型", 'vehicle', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'gpu_name': gpuName,
|
||||
'labelnames': ["车辆"],
|
||||
'seg_nclass': 2,
|
||||
'segRegionCnt': 0,
|
||||
'slopeIndex': [],
|
||||
'trtFlag_det': True,
|
||||
'trtFlag_seg': False,
|
||||
'Detweights': "../AIlib2/weights/vehicle/yolov5_%s_fp16.engine" % gpuName,
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Segweights': None
|
||||
})
|
||||
|
||||
PEDESTRIAN_MODEL = ("7", "007", "行人模型", 'pedestrian', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'gpu_name': gpuName,
|
||||
'labelnames': ["行人"],
|
||||
'seg_nclass': 2,
|
||||
'segRegionCnt': 0,
|
||||
'trtFlag_det': True,
|
||||
'trtFlag_seg': False,
|
||||
'Detweights': "../AIlib2/weights/pedestrian/yolov5_%s_fp16.engine" % gpuName,
|
||||
'slopeIndex': [],
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Segweights': None
|
||||
})
|
||||
|
||||
SMOGFIRE_MODEL = ("8", "008", "烟火模型", 'smogfire', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'gpu_name': gpuName,
|
||||
'labelnames': ["火焰", "烟雾"],
|
||||
'seg_nclass': 2, # 分割模型类别数目,默认2类
|
||||
'segRegionCnt': 0,
|
||||
'trtFlag_det': True,
|
||||
'trtFlag_seg': False,
|
||||
'Detweights': "../AIlib2/weights/smogfire/yolov5_%s_fp16.engine" % gpuName,
|
||||
'slopeIndex': [],
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Segweights': None
|
||||
})
|
||||
|
||||
ANGLERSWIMMER_MODEL = ("9", "009", "钓鱼游泳模型", 'AnglerSwimmer', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'gpu_name': gpuName,
|
||||
'labelnames': ["钓鱼", "游泳"],
|
||||
'seg_nclass': 2, # 分割模型类别数目,默认2类
|
||||
'segRegionCnt': 0,
|
||||
'slopeIndex': [],
|
||||
'trtFlag_det': True,
|
||||
'trtFlag_seg': False,
|
||||
'Detweights': "../AIlib2/weights/AnglerSwimmer/yolov5_%s_fp16.engine" % gpuName,
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Segweights': None
|
||||
})
|
||||
|
||||
COUNTRYROAD_MODEL = ("10", "010", "乡村模型", 'countryRoad', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'gpu_name': gpuName,
|
||||
'labelnames': ["违法种植"],
|
||||
'seg_nclass': 2, # 分割模型类别数目,默认2类
|
||||
'segRegionCnt': 0,
|
||||
'slopeIndex': [],
|
||||
'trtFlag_det': True,
|
||||
'trtFlag_seg': False,
|
||||
'Detweights': "../AIlib2/weights/countryRoad/yolov5_%s_fp16.engine" % gpuName,
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Segweights': None
|
||||
})
|
||||
|
||||
SHIP_MODEL = ("11", "011", "船只模型", 'ship2', lambda device, gpuName: {
|
||||
'model_size': (608, 608),
|
||||
'K': 100,
|
||||
'conf_thresh': 0.18,
|
||||
'device': 'cuda:%s' % device,
|
||||
'down_ratio': 4,
|
||||
'num_classes': 15,
|
||||
'weights': '../AIlib2/weights/ship2/obb_608X608_%s_fp16.engine' % gpuName,
|
||||
'dataset': 'dota',
|
||||
'half': False,
|
||||
'mean': (0.5, 0.5, 0.5),
|
||||
'std': (1, 1, 1),
|
||||
'heads': {'hm': None, 'wh': 10, 'reg': 2, 'cls_theta': 1},
|
||||
'decoder': None,
|
||||
'test_flag': True,
|
||||
"rainbows": COLOR,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'drawBox': False,
|
||||
'label_array': None,
|
||||
'labelnames': ("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "船只"),
|
||||
})
|
||||
|
||||
BAIDU_MODEL = ("12", "012", "百度AI图片识别模型", None, None)
|
||||
|
||||
CHANNEL_EMERGENCY_MODEL = ("13", "013", "航道模型", 'channelEmergency', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'gpu_name': gpuName,
|
||||
'labelnames': ["人"],
|
||||
'seg_nclass': 2, # 分割模型类别数目,默认2类
|
||||
'segRegionCnt': 0,
|
||||
'slopeIndex': [],
|
||||
'trtFlag_det': True,
|
||||
'trtFlag_seg': False,
|
||||
'Detweights': "../AIlib2/weights/channelEmergency/yolov5_%s_fp16.engine" % gpuName,
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Segweights': None
|
||||
})
|
||||
|
||||
RIVER2_MODEL = ("15", "015", "河道检测模型", 'river2', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["漂浮物", "岸坡垃圾", "排口", "违建", "菜地", "水生植物", "河湖人员", "钓鱼人员", "船只",
|
||||
"蓝藻"],
|
||||
'trtFlag_seg': True,
|
||||
'trtFlag_det': True,
|
||||
'seg_nclass': 2,
|
||||
'segRegionCnt': 1,
|
||||
'segPar': {
|
||||
'modelSize': (640, 360),
|
||||
'mean': (0.485, 0.456, 0.406),
|
||||
'std': (0.229, 0.224, 0.225),
|
||||
'numpy': False,
|
||||
'RGB_convert_first': True,
|
||||
'mixFunction': {
|
||||
'function': riverDetSegMixProcess,
|
||||
'pars': {
|
||||
'slopeIndex': [1, 3, 4, 7],
|
||||
'riverIou': 0.1
|
||||
}
|
||||
}
|
||||
},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.3,
|
||||
"ovlap_thres_crossCategory": 0.65,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
# "../AIlib2/weights/conf/%s/yolov5.pt" % modeType.value[3]
|
||||
'Detweights': "../AIlib2/weights/river2/yolov5_%s_fp16.engine" % gpuName,
|
||||
# '../AIlib2/weights/conf/%s/stdc_360X640.pth' % modeType.value[3]
|
||||
'Segweights': '../AIlib2/weights/river2/stdc_360X640_%s_fp16.engine' % gpuName
|
||||
})
|
||||
|
||||
CITY_MANGEMENT_MODEL = ("16", "016", "城管模型", 'cityMangement2', lambda device, gpuName: {
|
||||
'labelnames': ["车辆", "垃圾", "商贩", "裸土","占道经营","违停"],
|
||||
'postProcess':{
|
||||
'function':dmpr_yolo_stdc,
|
||||
'pars':{'carCls':0 ,'illCls':5,'scaleRatio':0.5,'border':80}
|
||||
},
|
||||
'models':[
|
||||
{
|
||||
#'weight':'../AIlib2/weights/conf/cityMangement3/yolov5.pt',
|
||||
'weight':'../AIlib2/weights/cityMangement3/yolov5_%s_fp16.engine'%(gpuName),
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':[0,1,2,3,4,5],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.8,"1":0.4,"2":0.5,"3":0.5,"4":0.4,"5":0.5 } }
|
||||
},
|
||||
{
|
||||
'weight':'../AIlib2/weights/conf/cityMangement3/dmpr.pth',
|
||||
'par':{
|
||||
'depth_factor':32,'NUM_FEATURE_MAP_CHANNEL':6,'dmpr_thresh':0.1, 'dmprimg_size':640,
|
||||
'name':'dmpr'
|
||||
},
|
||||
'model':DMPRModel,
|
||||
'name':'dmpr'
|
||||
},
|
||||
{
|
||||
'weight':'../AIlib2/weights/conf/cityMangement3/stdc_360X640.pth',
|
||||
'par':{
|
||||
'modelSize':(640,360),'mean':(0.485, 0.456, 0.406),'std' :(0.229, 0.224, 0.225),'predResize':True,'numpy':False, 'RGB_convert_first':True,'seg_nclass':2},###分割模型预处理参数
|
||||
'model':stdcModel,
|
||||
'name':'stdc'
|
||||
}
|
||||
],
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,5,6,7,8,9] ],###控制哪些检测类别显示、输出
|
||||
'segRegionCnt':2,###分割模型结果需要保留的等值线数目
|
||||
"pixScale": 1.2,
|
||||
})
|
||||
|
||||
DROWING_MODEL = ("17", "017", "人员落水模型", 'drowning', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["人头", "人", "船只"],
|
||||
'trtFlag_seg': True,
|
||||
'trtFlag_det': True,
|
||||
'seg_nclass': 2,
|
||||
'segRegionCnt': 2,
|
||||
'segPar': {
|
||||
'modelSize': (640, 360),
|
||||
'mean': (0.485, 0.456, 0.406),
|
||||
'std': (0.229, 0.224, 0.225),
|
||||
'predResize': True,
|
||||
'numpy': False,
|
||||
'RGB_convert_first': True,
|
||||
'mixFunction': {
|
||||
'function': mixDrowing_water_postprocess,
|
||||
'pars': {
|
||||
'modelSize': (640, 360)
|
||||
}
|
||||
}
|
||||
},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.25,
|
||||
"classes": 9,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
# "../AIlib2/weights/conf/%s/yolov5.pt" % modeType.value[3]
|
||||
'Detweights': "../AIlib2/weights/drowning/yolov5_%s_fp16.engine" % gpuName,
|
||||
# '../AIlib2/weights/conf/%s/stdc_360X640.pth' % modeType.value[3]
|
||||
'Segweights': '../AIlib2/weights/drowning/stdc_360X640_%s_fp16.engine' % gpuName
|
||||
})
|
||||
|
||||
NOPARKING_MODEL = (
|
||||
"18", "018", "城市违章模型", 'noParking', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["车辆", "违停"],
|
||||
'trtFlag_seg': True,
|
||||
'trtFlag_det': True,
|
||||
'seg_nclass': 4,
|
||||
'segRegionCnt': 2,
|
||||
'segPar': {
|
||||
'modelSize': (640, 360),
|
||||
'mean': (0.485, 0.456, 0.406),
|
||||
'std': (0.229, 0.224, 0.225),
|
||||
'predResize': True,
|
||||
'numpy': False,
|
||||
'RGB_convert_first': True, ###分割模型预处理参数
|
||||
'mixFunction': {
|
||||
'function': mixNoParking_road_postprocess,
|
||||
'pars': {
|
||||
'modelSize': (640, 360),
|
||||
'roundness': 0.3,
|
||||
'cls': 9,
|
||||
'laneArea': 10,
|
||||
'laneAngleCha': 5,
|
||||
'RoadArea': 16000,
|
||||
'fitOrder':2
|
||||
}
|
||||
}
|
||||
},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.25,
|
||||
"classes": 9,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Detweights': "../AIlib2/weights/noParking/yolov5_%s_fp16.engine" % gpuName,
|
||||
'Segweights': '../AIlib2/weights/noParking/stdc_360X640_%s_fp16.engine' % gpuName
|
||||
})
|
||||
|
||||
ILLPARKING_MODEL = ("19", "019", "车辆违停模型", 'illParking', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["车", "T角点", "L角点", "违停"],
|
||||
'trtFlag_seg': False,
|
||||
'trtFlag_det': True,
|
||||
'seg_nclass': 4,
|
||||
'segRegionCnt': 2,
|
||||
'segPar': {
|
||||
'mixFunction': {
|
||||
'function': illParking_postprocess,
|
||||
'pars': {}
|
||||
}
|
||||
},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.25,
|
||||
"classes": 9,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Detweights': "../AIlib2/weights/illParking/yolov5_%s_fp16.engine" % gpuName,
|
||||
'Segweights': None
|
||||
})
|
||||
|
||||
CITYROAD_MODEL = ("20", "020", "城市公路模型", 'cityRoad', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["护栏", "交通标志", "非交通标志", "施工", "施工"],
|
||||
'trtFlag_seg': False,
|
||||
'trtFlag_det': True,
|
||||
'slopeIndex': [],
|
||||
'seg_nclass': 2,
|
||||
'segRegionCnt': 0,
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.8,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Detweights': "../AIlib2/weights/cityRoad/yolov5_%s_fp16.engine" % gpuName,
|
||||
'Segweights': None
|
||||
})
|
||||
|
||||
POTHOLE_MODEL = ("23", "023", "坑槽检测模型", 'pothole', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'gpu_name': gpuName,
|
||||
'labelnames': ["坑槽"],
|
||||
'seg_nclass': 2, # 分割模型类别数目,默认2类
|
||||
'segRegionCnt': 0,
|
||||
'slopeIndex': [],
|
||||
'trtFlag_det': True,
|
||||
'trtFlag_seg': False,
|
||||
'Detweights': "../AIlib2/weights/pothole/yolov5_%s_fp16.engine" % gpuName,
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Segweights': None,
|
||||
})
|
||||
|
||||
CHANNEL2_MODEL = ("24", "024", "船只综合检测模型", 'channel2', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'gpu_name': gpuName,
|
||||
'labelnames': ["国旗", "浮标", "船名", "船只","未挂国旗船只"],
|
||||
'segRegionCnt': 0,
|
||||
'postProcess':{'function':channel2_post_process,'name':'channel2','pars':{
|
||||
'objs':[2],
|
||||
'wRation':1/6.0,
|
||||
'hRation':1/6.0,
|
||||
'smallId':0,
|
||||
'bigId':3,
|
||||
'newId':4,
|
||||
'recScale':1.2}},
|
||||
'models':[
|
||||
{
|
||||
#'weight':'../AIlib2/weights/conf/channel2/yolov5.pt',
|
||||
'weight':'../AIlib2/weights/channel2/yolov5_%s_fp16.engine'%(gpuName),
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.1,'iou_thres':0.45,'allowedList':list(range(20)),'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.7,"1":0.7,"2":0.8,"3":0.6} }
|
||||
},
|
||||
{
|
||||
# 'weight' : '../AIlib2/weights/ocr2/crnn_ch_4090_fp16_192X32.engine',
|
||||
'weight' : '../AIlib2/weights/conf/ocr2/crnn_ch.pth',
|
||||
'name':'ocr',
|
||||
'model':ocrModel,
|
||||
'par':{
|
||||
'char_file':'../AIlib2/weights/conf/ocr2/benchmark.txt',
|
||||
'mode':'ch',
|
||||
'nc':3,
|
||||
'imgH':32,
|
||||
'imgW':192,
|
||||
'hidden':256,
|
||||
'mean':[0.5,0.5,0.5],
|
||||
'std':[0.5,0.5,0.5],
|
||||
'dynamic':False,
|
||||
},
|
||||
}
|
||||
],
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3]],
|
||||
'segPar': None,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Segweights': None,
|
||||
})
|
||||
|
||||
RIVERT_MODEL = ("25", "025", "河道检测模型(T)", 'riverT', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["漂浮物", "岸坡垃圾", "排口", "违建", "菜地", "水生植物", "河湖人员", "钓鱼人员", "船只",
|
||||
"蓝藻"],
|
||||
'trtFlag_seg': True,
|
||||
'trtFlag_det': True,
|
||||
'seg_nclass': 2,
|
||||
'segRegionCnt': 1,
|
||||
'segPar': {
|
||||
'modelSize': (640, 360),
|
||||
'mean': (0.485, 0.456, 0.406),
|
||||
'std': (0.229, 0.224, 0.225),
|
||||
'numpy': False,
|
||||
'RGB_convert_first': True,
|
||||
'mixFunction': {
|
||||
'function': riverDetSegMixProcess,
|
||||
'pars': {
|
||||
'slopeIndex': [1, 3, 4, 7],
|
||||
'riverIou': 0.1
|
||||
}
|
||||
}
|
||||
},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.3,
|
||||
"ovlap_thres_crossCategory": 0.65,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
# "../AIlib2/weights/conf/%s/yolov5.pt" % modeType.value[3]
|
||||
'Detweights': "../AIlib2/weights/riverT/yolov5_%s_fp16.engine" % gpuName,
|
||||
# '../AIlib2/weights/conf/%s/stdc_360X640.pth' % modeType.value[3]
|
||||
'Segweights': '../AIlib2/weights/riverT/stdc_360X640_%s_fp16.engine' % gpuName
|
||||
})
|
||||
|
||||
|
||||
|
||||
FORESTCROWD_FARM_MODEL = ("26", "026", "森林人群模型", 'forestCrowd', lambda device, gpuName: {
|
||||
'labelnames': ["林斑", "病死树", "行人", "火焰", "烟雾","人群"],
|
||||
'postProcess':{'function':gather_post_process,'pars':{'pedestrianId':2,'crowdThreshold':4,'gatherId':5,'distancePersonScale':2.0}},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/forestCrowd/yolov5_%s_fp16.engine"%(gpuName),###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':[0,1,2,3],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{ "0":0.25,"1":0.25,"2":0.6,"3":0.6,'4':0.6 ,'5':0.6 } },
|
||||
}
|
||||
|
||||
|
||||
],
|
||||
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,4,5,6,7,8,9] ],###控制哪些检测类别显示、输出
|
||||
'segRegionCnt':2,###分割模型结果需要保留的等值线数目
|
||||
"pixScale": 1.2,
|
||||
|
||||
|
||||
})
|
||||
TRAFFICFORDSJ_FARM_MODEL = ("27", "027", "交通模型-大数据局", 'highWay2T', lambda device, gpuName: {
|
||||
'device': str(device),
|
||||
'labelnames': ["行人", "车辆", "纵向裂缝", "横向裂缝", "修补", "网状裂纹", "坑槽", "块状裂纹", "积水", "影子", "事故", "桥梁外观","设施破损缺失","龙门架","防抛网","标识牌损坏","护栏损坏","钢筋裸露" ],
|
||||
'trtFlag_seg': True,
|
||||
'trtFlag_det': True,
|
||||
'seg_nclass': 3,
|
||||
'segRegionCnt': 2,
|
||||
'segPar': {
|
||||
'modelSize': (640, 360),
|
||||
'mean': (0.485, 0.456, 0.406),
|
||||
'std': (0.229, 0.224, 0.225),
|
||||
'predResize': True,
|
||||
'numpy': False,
|
||||
'RGB_convert_first': True,
|
||||
'mixFunction': {
|
||||
'function': tracfficAccidentMixFunction,
|
||||
'pars': {
|
||||
'modelSize': (640, 360),
|
||||
#'modelSize': (1920,1080),
|
||||
'RoadArea': 16000,
|
||||
'roadVehicleAngle': 15,
|
||||
'speedRoadVehicleAngleMax': 75,
|
||||
'roundness': 1.0,
|
||||
'cls': 9,
|
||||
'vehicleFactor': 0.1,
|
||||
'confThres': 0.25,
|
||||
'roadIou': 0.6,
|
||||
'radius': 50,
|
||||
'vehicleFlag': False,
|
||||
'distanceFlag': False
|
||||
}
|
||||
}
|
||||
},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.25,
|
||||
"classes": 10,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'Detweights': "../AIlib2/weights/highWay2/yolov5_%s_fp16.engine" % gpuName,
|
||||
'Segweights': '../AIlib2/weights/highWay2/stdc_360X640_%s_fp16.engine' % gpuName
|
||||
})
|
||||
|
||||
SMARTSITE_MODEL = ("28", "028", "智慧工地模型", 'smartSite', lambda device, gpuName: {
|
||||
'labelnames': [ "工人","塔式起重机","悬臂","起重机","压路机","推土机","挖掘机","卡车","装载机","泵车","混凝土搅拌车","打桩","其他车辆" ],
|
||||
'postProcess':{'function':default_mix,'pars':{}},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/smartSite/yolov5_%s_fp16.engine"%(gpuName),###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':list(range(20)),'segRegionCnt':1, 'trtFlag_det':True,'trtFlag_seg':False, "score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
}
|
||||
|
||||
|
||||
],
|
||||
'postFile': {
|
||||
"rainbows": COLOR
|
||||
},
|
||||
|
||||
})
|
||||
|
||||
RUBBISH_MODEL = ("29", "029", "垃圾模型", 'rubbish', lambda device, gpuName: {
|
||||
'labelnames': [ "建筑垃圾","白色垃圾","其他垃圾"],
|
||||
'postProcess':{'function':default_mix,'pars':{}},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/rubbish/yolov5_%s_fp16.engine"%(gpuName),###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':list(range(20)),'segRegionCnt':1, 'trtFlag_det':True,'trtFlag_seg':False, "score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
}
|
||||
|
||||
|
||||
],
|
||||
'postFile': {
|
||||
"rainbows": COLOR
|
||||
},
|
||||
|
||||
})
|
||||
|
||||
FIREWORK_MODEL = ("30", "030", "烟花模型", 'firework', lambda device, gpuName: {
|
||||
'labelnames': [ "烟花"],
|
||||
'postProcess':{'function':default_mix,'pars':{}},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/firework/yolov5_%s_fp16.engine"%(gpuName),###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':list(range(20)),'segRegionCnt':1, 'trtFlag_det':True,'trtFlag_seg':False, "score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
}
|
||||
|
||||
|
||||
],
|
||||
'postFile': {
|
||||
"rainbows": COLOR
|
||||
},
|
||||
|
||||
})
|
||||
|
||||
|
||||
@staticmethod
|
||||
def checkCode(code):
|
||||
for model in ModelType:
|
||||
if model.value[1] == code:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
'''
|
||||
参数1: 检测目标名称
|
||||
参数2: 检测目标
|
||||
参数3: 初始化百度检测客户端
|
||||
'''
|
||||
|
||||
|
||||
@unique
|
||||
class BaiduModelTarget(Enum):
|
||||
VEHICLE_DETECTION = (
|
||||
"车辆检测", 0, lambda client0, client1, url, request_id: client0.vehicleDetectUrl(url, request_id))
|
||||
|
||||
HUMAN_DETECTION = (
|
||||
"人体检测与属性识别", 1, lambda client0, client1, url, request_id: client1.bodyAttr(url, request_id))
|
||||
|
||||
PEOPLE_COUNTING = ("人流量统计", 2, lambda client0, client1, url, request_id: client1.bodyNum(url, request_id))
|
||||
|
||||
|
||||
BAIDU_MODEL_TARGET_CONFIG = {
|
||||
BaiduModelTarget.VEHICLE_DETECTION.value[1]: BaiduModelTarget.VEHICLE_DETECTION,
|
||||
BaiduModelTarget.HUMAN_DETECTION.value[1]: BaiduModelTarget.HUMAN_DETECTION,
|
||||
BaiduModelTarget.PEOPLE_COUNTING.value[1]: BaiduModelTarget.PEOPLE_COUNTING
|
||||
}
|
||||
|
||||
EPIDEMIC_PREVENTION_CONFIG = {1: "行程码", 2: "健康码"}
|
||||
|
||||
|
||||
# 模型分析方式
|
||||
@unique
|
||||
class ModelMethodTypeEnum(Enum):
|
||||
# 方式一: 正常识别方式
|
||||
NORMAL = 1
|
||||
|
||||
# 方式二: 追踪识别方式
|
||||
TRACE = 2
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,762 @@
|
|||
import sys
|
||||
from enum import Enum, unique
|
||||
|
||||
from common.Constant import COLOR
|
||||
|
||||
sys.path.extend(['..', '../AIlib2'])
|
||||
from segutils.segmodel import SegModel
|
||||
from utilsK.queRiver import riverDetSegMixProcess_N
|
||||
from segutils.trafficUtils import tracfficAccidentMixFunction_N
|
||||
from utilsK.drownUtils import mixDrowing_water_postprocess_N
|
||||
from utilsK.noParkingUtils import mixNoParking_road_postprocess_N
|
||||
from utilsK.illParkingUtils import illParking_postprocess
|
||||
from DMPR import DMPRModel
|
||||
from DMPRUtils.jointUtil import dmpr_yolo
|
||||
from yolov5 import yolov5Model
|
||||
from stdc import stdcModel
|
||||
from AI import default_mix
|
||||
from DMPRUtils.jointUtil import dmpr_yolo_stdc
|
||||
|
||||
'''
|
||||
参数说明
|
||||
1. 编号
|
||||
2. 模型编号
|
||||
3. 模型名称
|
||||
4. 选用的模型名称
|
||||
'''
|
||||
|
||||
|
||||
@unique
|
||||
class ModelType2(Enum):
|
||||
WATER_SURFACE_MODEL = ("1", "001", "河道模型", 'river', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["排口", "水生植被", "其它", "漂浮物", "污染排口", "菜地", "违建", "岸坡垃圾"],
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,4,5,6,7] ],###控制哪些检测类别显示、输出
|
||||
'trackPar': {
|
||||
'sort_max_age': 2, # 跟踪链断裂时允许目标消失最大的次数。超过之后,会认为是新的目标。
|
||||
'sort_min_hits': 3, # 每隔目标连续出现的次数,超过这个次数才认为是一个目标。
|
||||
'sort_iou_thresh': 0.2, # 检测最小的置信度。
|
||||
'det_cnt': 10, # 每隔几次做一个跟踪和检测,默认10。
|
||||
'windowsize': 29, # 轨迹平滑长度,一定是奇数,表示每隔几帧做一平滑,默认29。一个目标在多个帧中出现,每一帧中都有一个位置,这些位置的连线交轨迹。
|
||||
'patchCnt': 100, # 每次送入图像的数量,不宜少于100帧。
|
||||
},
|
||||
'postProcess':{'function':riverDetSegMixProcess_N,'pars':{'slopeIndex':[1,3,4,7], 'riverIou':0.1}}, #分割和检测混合处理的函数
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'txtFontSize': 80,
|
||||
'digitFont': {
|
||||
'line_thickness': 2,
|
||||
'boxLine_thickness': 1,
|
||||
'fontSize': 1.0,
|
||||
'segLineShow': False,
|
||||
'waterLineColor': (0, 255, 255),
|
||||
'waterLineWidth': 3
|
||||
},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/river/yolov5_%s_fp16.engine"% gpuName,###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{
|
||||
'half':True,
|
||||
'device':'cuda:0' ,
|
||||
'conf_thres':0.25,
|
||||
'iou_thres':0.45,
|
||||
'allowedList':[0,1,2,3],
|
||||
'segRegionCnt':1,
|
||||
'trtFlag_det':False,
|
||||
'trtFlag_seg':False,
|
||||
"score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
},
|
||||
{
|
||||
'weight':'../AIlib2/weights/conf/river/stdc_360X640.pth',
|
||||
'par':{
|
||||
'modelSize':(640,360),
|
||||
'mean':(0.485, 0.456, 0.406),
|
||||
'std' :(0.229, 0.224, 0.225),
|
||||
'numpy':False,
|
||||
'RGB_convert_first':True,
|
||||
'seg_nclass':2},###分割模型预处理参数
|
||||
'model':stdcModel,
|
||||
'name':'stdc'
|
||||
}
|
||||
|
||||
],
|
||||
})
|
||||
|
||||
FOREST_FARM_MODEL = ("2", "002", "森林模型", 'forest2', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["林斑", "病死树", "行人", "火焰", "烟雾"],
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/forest2/yolov5_%s_fp16.engine"% gpuName,###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,
|
||||
'device':'cuda:0' ,
|
||||
'conf_thres':0.25,
|
||||
'iou_thres':0.45,
|
||||
'allowedList':[0,1,2,3],
|
||||
'segRegionCnt':1,
|
||||
'trtFlag_det':False,
|
||||
'trtFlag_seg':False,
|
||||
"score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 }
|
||||
},
|
||||
}
|
||||
],
|
||||
'trackPar':{'sort_max_age':2,'sort_min_hits':3,'sort_iou_thresh':0.2,'det_cnt':10,'windowsize':29,'patchCnt':100},
|
||||
'postProcess':{'function':default_mix,'pars':{ }},
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'txtFontSize': 80,
|
||||
'digitFont': {
|
||||
'line_thickness': 2,
|
||||
'boxLine_thickness': 1,
|
||||
'fontSize': 1.0,
|
||||
'segLineShow': False,
|
||||
'waterLineColor': (0, 255, 255),
|
||||
'waterLineWidth': 3
|
||||
}
|
||||
})
|
||||
|
||||
TRAFFIC_FARM_MODEL = ("3", "003", "交通模型", 'highWay2', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["行人", "车辆", "纵向裂缝", "横向裂缝", "修补", "网状裂纹", "坑槽", "块状裂纹", "积水", "事故"],
|
||||
'trackPar':{'sort_max_age':2,'sort_min_hits':3,'sort_iou_thresh':0.2,'det_cnt':5,'windowsize':29,'patchCnt':100},
|
||||
'postProcess':{
|
||||
'function':tracfficAccidentMixFunction_N,
|
||||
'pars':{
|
||||
'RoadArea': 16000,
|
||||
'vehicleArea': 10,
|
||||
'roadVehicleAngle': 15,
|
||||
'speedRoadVehicleAngleMax': 75,
|
||||
'radius': 50 ,
|
||||
'roundness': 1.0,
|
||||
'cls': 9,
|
||||
'vehicleFactor': 0.1,
|
||||
'cls':9,
|
||||
'confThres':0.25,
|
||||
'roadIou':0.6,
|
||||
'vehicleFlag':False,
|
||||
'distanceFlag': False,
|
||||
'modelSize':(640,360),
|
||||
}
|
||||
},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/highWay2/yolov5_%s_fp16.engine"% gpuName,###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{
|
||||
'half':True,
|
||||
'device':'cuda:0' ,
|
||||
'conf_thres':0.25,
|
||||
'iou_thres':0.45,
|
||||
'allowedList':[0,1,2,3],
|
||||
'segRegionCnt':1,
|
||||
'trtFlag_det':False,
|
||||
'trtFlag_seg':False,
|
||||
"score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
},
|
||||
{
|
||||
'weight':'../AIlib2/weights/conf/highWay2/stdc_360X640.pth',
|
||||
'par':{
|
||||
'modelSize':(640,360),
|
||||
'mean':(0.485, 0.456, 0.406),
|
||||
'std' :(0.229, 0.224, 0.225),
|
||||
'predResize':True,
|
||||
'numpy':False,
|
||||
'RGB_convert_first':True,
|
||||
'seg_nclass':3},###分割模型预处理参数
|
||||
'model':stdcModel,
|
||||
'name':'stdc'
|
||||
}
|
||||
],
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,5,6,7,8,9] ],###控制哪些检测类别显示、输出
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.25,
|
||||
"classes": 9,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'txtFontSize': 20,
|
||||
'digitFont': {
|
||||
'line_thickness': 2,
|
||||
'boxLine_thickness': 1,
|
||||
'fontSize': 1.0,
|
||||
'waterLineColor': (0, 255, 255),
|
||||
'segLineShow': False,
|
||||
'waterLineWidth': 2
|
||||
}
|
||||
})
|
||||
|
||||
EPIDEMIC_PREVENTION_MODEL = ("4", "004", "防疫模型", None, None)
|
||||
|
||||
PLATE_MODEL = ("5", "005", "车牌模型", None, None)
|
||||
|
||||
VEHICLE_MODEL = ("6", "006", "车辆模型", 'vehicle', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["车辆"],
|
||||
'trackPar':{'sort_max_age':2,'sort_min_hits':3,'sort_iou_thresh':0.2,'det_cnt':10,'windowsize':29,'patchCnt':100},
|
||||
'postProcess':{'function':default_mix,'pars':{ }},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/vehicle/yolov5_%s_fp16.engine"% gpuName,###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,
|
||||
'device':'cuda:0' ,
|
||||
'conf_thres':0.25,
|
||||
'iou_thres':0.45,
|
||||
'allowedList':[0,1,2,3],
|
||||
'segRegionCnt':1,
|
||||
'trtFlag_det':False,
|
||||
'trtFlag_seg':False,
|
||||
"score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
}
|
||||
],
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,4,5,6] ],###控制哪些检测类别显示、输出
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'txtFontSize': 40,
|
||||
'digitFont': {
|
||||
'line_thickness': 2,
|
||||
'boxLine_thickness': 1,
|
||||
'fontSize': 1.0,
|
||||
'waterLineColor': (0, 255, 255),
|
||||
'segLineShow': False,
|
||||
'waterLineWidth': 3
|
||||
}
|
||||
})
|
||||
|
||||
PEDESTRIAN_MODEL = ("7", "007", "行人模型", 'pedestrian', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["行人"],
|
||||
'trackPar':{'sort_max_age':2,'sort_min_hits':3,'sort_iou_thresh':0.2,'det_cnt':10,'windowsize':29,'patchCnt':100},
|
||||
'postProcess':{'function':default_mix,'pars':{ }},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/pedestrian/yolov5_%s_fp16.engine"% gpuName,###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':[0,1,2,3],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
}
|
||||
],
|
||||
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,4,5,6] ],###控制哪些检测类别显示、输出
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'digitFont': {
|
||||
'line_thickness': 2,
|
||||
'boxLine_thickness': 1,
|
||||
'fontSize': 1.0,
|
||||
'segLineShow': False,
|
||||
'waterLineColor': (0, 255, 255),
|
||||
'waterLineWidth': 3
|
||||
}
|
||||
})
|
||||
|
||||
SMOGFIRE_MODEL = ("8", "008", "烟火模型", 'smogfire', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["烟雾", "火焰"],
|
||||
'trackPar':{'sort_max_age':2,'sort_min_hits':3,'sort_iou_thresh':0.2,'det_cnt':10,'windowsize':29,'patchCnt':100},
|
||||
'postProcess':{'function':default_mix,'pars':{ }},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/smogfire/yolov5_%s_fp16.engine"% gpuName,###检测模型路径
|
||||
#'weight':'../AIlib2/weights/conf/%s/yolov5.pt'%(opt['business'] ),
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':[0,1,2,3],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
}
|
||||
],
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,4,5,6] ],###控制哪些检测类别显示、输出
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'txtFontSize': 40,
|
||||
'digitFont': {
|
||||
'line_thickness': 2,
|
||||
'boxLine_thickness': 1,
|
||||
'fontSize': 1.0,
|
||||
'segLineShow': False,
|
||||
'waterLineColor': (0, 255, 255),
|
||||
'waterLineWidth': 3
|
||||
}
|
||||
})
|
||||
|
||||
ANGLERSWIMMER_MODEL = ("9", "009", "钓鱼游泳模型", 'AnglerSwimmer', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["钓鱼", "游泳"],
|
||||
'trackPar':{'sort_max_age':2,'sort_min_hits':3,'sort_iou_thresh':0.2,'det_cnt':10,'windowsize':29,'patchCnt':100},
|
||||
'postProcess':{'function':default_mix,'pars':{ }},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/AnglerSwimmer/yolov5_%s_fp16.engine"% gpuName,###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':[0,1,2,3],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
}
|
||||
],
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,4,5,6] ],###控制哪些检测类别显示、输出
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'txtFontSize': 40,
|
||||
'digitFont': {
|
||||
'line_thickness': 2,
|
||||
'boxLine_thickness': 1,
|
||||
'fontSize': 1.0,
|
||||
'segLineShow': False,
|
||||
'waterLineColor': (0, 255, 255),
|
||||
'waterLineWidth': 3
|
||||
},
|
||||
})
|
||||
|
||||
COUNTRYROAD_MODEL = ("10", "010", "乡村模型", 'countryRoad', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["违法种植"],
|
||||
'trackPar':{'sort_max_age':2,'sort_min_hits':3,'sort_iou_thresh':0.2,'det_cnt':10,'windowsize':29,'patchCnt':100},
|
||||
'postProcess':{'function':default_mix,'pars':{ }},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/countryRoad/yolov5_%s_fp16.engine"% gpuName,###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':[0,1,2,3],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
}
|
||||
],
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,4,5,6] ],###控制哪些检测类别显示、输出
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'txtFontSize': 40,
|
||||
'digitFont': {
|
||||
'line_thickness': 2,
|
||||
'boxLine_thickness': 1,
|
||||
'fontSize': 1.0,
|
||||
'segLineShow': False,
|
||||
'waterLineColor': (0, 255, 255),
|
||||
'waterLineWidth': 3
|
||||
}
|
||||
})
|
||||
|
||||
SHIP_MODEL = ("11", "011", "船只模型", 'ship2', lambda device, gpuName: {
|
||||
'obbModelPar': {
|
||||
'labelnames': ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "船只"],
|
||||
'model_size': (608, 608),
|
||||
'K': 100,
|
||||
'conf_thresh': 0.3,
|
||||
'down_ratio': 4,
|
||||
'num_classes': 15,
|
||||
'dataset': 'dota',
|
||||
'heads': {
|
||||
'hm': None,
|
||||
'wh': 10,
|
||||
'reg': 2,
|
||||
'cls_theta': 1
|
||||
},
|
||||
'mean': (0.5, 0.5, 0.5),
|
||||
'std': (1, 1, 1),
|
||||
'half': False,
|
||||
'test_flag': True,
|
||||
'decoder': None,
|
||||
'weights': '../AIlib2/weights/ship2/obb_608X608_%s_fp16.engine' % gpuName
|
||||
},
|
||||
'trackPar': {
|
||||
'sort_max_age': 2, # 跟踪链断裂时允许目标消失最大的次数。超过之后,会认为是新的目标。
|
||||
'sort_min_hits': 3, # 每隔目标连续出现的次数,超过这个次数才认为是一个目标。
|
||||
'sort_iou_thresh': 0.2, # 检测最小的置信度。
|
||||
'det_cnt': 10, # 每隔几次做一个跟踪和检测,默认10。
|
||||
'windowsize': 29, # 轨迹平滑长度,一定是奇数,表示每隔几帧做一平滑,默认29。一个目标在多个帧中出现,每一帧中都有一个位置,这些位置的连线交轨迹。
|
||||
'patchCnt': 100, # 每次送入图像的数量,不宜少于100帧。
|
||||
},
|
||||
'device': "cuda:%s" % device,
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'drawBox': False,
|
||||
'drawPar': {
|
||||
"rainbows": COLOR,
|
||||
'digitWordFont': {
|
||||
'line_thickness': 2,
|
||||
'boxLine_thickness': 1,
|
||||
'wordSize': 40,
|
||||
'fontSize': 1.0,
|
||||
'label_location': 'leftTop'
|
||||
}
|
||||
},
|
||||
'labelnames': ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "船只"]
|
||||
})
|
||||
|
||||
BAIDU_MODEL = ("12", "012", "百度AI图片识别模型", None, None)
|
||||
|
||||
CHANNEL_EMERGENCY_MODEL = ("13", "013", "航道模型", 'channelEmergency', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["人"],
|
||||
'trackPar':{'sort_max_age':2,'sort_min_hits':3,'sort_iou_thresh':0.2,'det_cnt':10,'windowsize':29,'patchCnt':100},
|
||||
'postProcess':{'function':default_mix,'pars':{ }},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/channelEmergency/yolov5_%s_fp16.engine"% gpuName,###检测模型路径
|
||||
#'weight':'../AIlib2/weights/conf/%s/yolov5.pt'%(opt['business'] ),
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':[0,1,2,3],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
}
|
||||
],
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [] ],###控制哪些检测类别显示、输出
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'txtFontSize': 40,
|
||||
'digitFont': {
|
||||
'line_thickness': 2,
|
||||
'boxLine_thickness': 1,
|
||||
'fontSize': 1.0,
|
||||
'segLineShow': False,
|
||||
'waterLineColor': (0, 255, 255),
|
||||
'waterLineWidth': 3
|
||||
}
|
||||
})
|
||||
|
||||
RIVER2_MODEL = ("15", "015", "河道检测模型", 'river2', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["漂浮物", "岸坡垃圾", "排口", "违建", "菜地", "水生植物", "河湖人员", "钓鱼人员", "船只",
|
||||
"蓝藻"],
|
||||
'trackPar':{'sort_max_age':2,'sort_min_hits':3,'sort_iou_thresh':0.2,'det_cnt':10,'windowsize':29,'patchCnt':100},
|
||||
'postProcess':{'function':riverDetSegMixProcess_N,'pars':{'slopeIndex':[1,3,4,7], 'riverIou':0.1}}, #分割和检测混合处理的函数
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/river2/yolov5_%s_fp16.engine"% gpuName,###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':[0,1,2,3],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
},
|
||||
{
|
||||
'weight':'../AIlib2/weights/conf/river2/stdc_360X640.pth',
|
||||
'par':{
|
||||
'modelSize':(640,360),'mean':(0.485, 0.456, 0.406),'std' :(0.229, 0.224, 0.225),'numpy':False, 'RGB_convert_first':True,'seg_nclass':2},###分割模型预处理参数
|
||||
'model':stdcModel,
|
||||
'name':'stdc'
|
||||
}
|
||||
],
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,4,5,6] ],###控制哪些检测类别显示、输出
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.3,
|
||||
"ovlap_thres_crossCategory": 0.65,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'txtFontSize': 80,
|
||||
'digitFont': {
|
||||
'line_thickness': 2,
|
||||
'boxLine_thickness': 1,
|
||||
'fontSize': 1.0,
|
||||
'segLineShow': False,
|
||||
'waterLineColor': (0, 255, 255),
|
||||
'waterLineWidth': 3
|
||||
}
|
||||
})
|
||||
|
||||
CITY_MANGEMENT_MODEL = ("16", "016", "城管模型", 'cityMangement2', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["车辆", "垃圾", "商贩", "违停"],
|
||||
'trackPar':{'sort_max_age':2,'sort_min_hits':3,'sort_iou_thresh':0.2,'det_cnt':5,'windowsize':29,'patchCnt':100},
|
||||
'postProcess':{
|
||||
'function':dmpr_yolo_stdc,
|
||||
'pars':{'carCls':0 ,'illCls':3,'scaleRatio':0.5,'border':80}
|
||||
},
|
||||
'models':[
|
||||
{
|
||||
'weight':"../AIlib2/weights/cityMangement3/yolov5_%s_fp16.engine"% gpuName,###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':[0,1,2,3],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.8,"1":0.5,"2":0.5,"3":0.5 } }
|
||||
|
||||
},
|
||||
{
|
||||
'weight':"../AIlib2/weights/cityMangement3/dmpr_%s.engine"% gpuName,###DMPR模型路径
|
||||
'par':{
|
||||
'depth_factor':32,'NUM_FEATURE_MAP_CHANNEL':6,'dmpr_thresh':0.3, 'dmprimg_size':640,
|
||||
'name':'dmpr'
|
||||
},
|
||||
'model':DMPRModel,
|
||||
'name':'dmpr'
|
||||
},
|
||||
{
|
||||
'weight':"../AIlib2/weights/cityMangement3/stdc_360X640_%s_fp16.engine"% gpuName,###分割模型路径
|
||||
'par':{
|
||||
'modelSize':(640,360),'mean':(0.485, 0.456, 0.406),'std' :(0.229, 0.224, 0.225),'predResize':True,'numpy':False, 'RGB_convert_first':True,'seg_nclass':2},###分割模型预处理参数
|
||||
'model':stdcModel,
|
||||
'name':'stdc'
|
||||
|
||||
}
|
||||
],
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,5,6,7,8,9] ],###控制哪些检测类别显示、输出
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'txtFontSize': 20,
|
||||
'digitFont': {
|
||||
'line_thickness': 2,
|
||||
'boxLine_thickness': 1,
|
||||
'fontSize': 1.0,
|
||||
'segLineShow': False,
|
||||
'waterLineColor': (0, 255, 255),
|
||||
'waterLineWidth': 2
|
||||
}
|
||||
})
|
||||
|
||||
DROWING_MODEL = ("17", "017", "人员落水模型", 'drowning', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["人头", "人", "船只"],
|
||||
'trackPar':{'sort_max_age':2,'sort_min_hits':3,'sort_iou_thresh':0.2,'det_cnt':10,'windowsize':29,'patchCnt':100},
|
||||
'postProcess':{'function':mixDrowing_water_postprocess_N,
|
||||
'pars':{ }},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/drowning/yolov5_%s_fp16.engine"% gpuName,###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':[0,1,2,3],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
},
|
||||
{
|
||||
'weight':'../AIlib2/weights/conf/drowning/stdc_360X640.pth',
|
||||
'par':{
|
||||
'modelSize':(640,360),'mean':(0.485, 0.456, 0.406),'std' :(0.229, 0.224, 0.225),'predResize':True,'numpy':False, 'RGB_convert_first':True,'seg_nclass':2},###分割模型预处理参数
|
||||
'model':stdcModel,
|
||||
'name':'stdc'
|
||||
}
|
||||
],
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,5,6,7,8,9] ],###控制哪些检测类别显示、输出
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.25,
|
||||
"classes": 9,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'txtFontSize': 20,
|
||||
'digitFont': {
|
||||
'line_thickness': 2,
|
||||
'boxLine_thickness': 1,
|
||||
'fontSize': 1.0,
|
||||
'waterLineColor': (0, 255, 255),
|
||||
'segLineShow': False,
|
||||
'waterLineWidth': 2
|
||||
}
|
||||
})
|
||||
|
||||
NOPARKING_MODEL = (
|
||||
"18", "018", "城市违章模型", 'noParking', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["车辆", "违停"],
|
||||
'trackPar':{'sort_max_age':2,'sort_min_hits':3,'sort_iou_thresh':0.2,'det_cnt':10,'windowsize':29,'patchCnt':100},
|
||||
'postProcess':{'function':mixNoParking_road_postprocess_N,
|
||||
'pars': { 'roundness': 0.3, 'cls': 9, 'laneArea': 10, 'laneAngleCha': 5 ,'RoadArea': 16000,'fitOrder':2, 'modelSize':(640,360)}
|
||||
} ,
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/noParking/yolov5_%s_fp16.engine"% gpuName,###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':[0,1,2,3],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
},
|
||||
{
|
||||
'weight':'../AIlib2/weights/conf/noParking/stdc_360X640.pth',
|
||||
'par':{
|
||||
'modelSize':(640,360),'mean':(0.485, 0.456, 0.406),'std' :(0.229, 0.224, 0.225),'predResize':True,'numpy':False, 'RGB_convert_first':True,'seg_nclass':4},###分割模型预处理参数
|
||||
'model':stdcModel,
|
||||
'name':'stdc'
|
||||
}
|
||||
],
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,5,6,7,8,9] ],###控制哪些检测类别显示、输出
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.25,
|
||||
"classes": 9,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'txtFontSize': 20,
|
||||
'digitFont': {
|
||||
'line_thickness': 2,
|
||||
'boxLine_thickness': 1,
|
||||
'fontSize': 1.0,
|
||||
'waterLineColor': (0, 255, 255),
|
||||
'segLineShow': False,
|
||||
'waterLineWidth': 2
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
CITYROAD_MODEL = ("20", "020", "城市公路模型", 'cityRoad', lambda device, gpuName: {
|
||||
'device': device,
|
||||
'labelnames': ["护栏", "交通标志", "非交通标志", "施工", "施工"],
|
||||
'trackPar':{'sort_max_age':2,'sort_min_hits':3,'sort_iou_thresh':0.2,'det_cnt':10,'windowsize':29,'patchCnt':100},
|
||||
'postProcess':{'function':default_mix,'pars':{ }},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/cityRoad/yolov5_%s_fp16.engine"% gpuName,###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.8,'iou_thres':0.45,'allowedList':[0,1,2,3],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3 } },
|
||||
}
|
||||
],
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0,1,2,3,4,5,6] ],###控制哪些检测类别显示、输出
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.8,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'txtFontSize': 40,
|
||||
'digitFont': {
|
||||
'line_thickness': 2,
|
||||
'boxLine_thickness': 1,
|
||||
'fontSize': 1.0,
|
||||
'segLineShow': False,
|
||||
'waterLineColor': (0, 255, 255),
|
||||
'waterLineWidth': 3
|
||||
}
|
||||
})
|
||||
|
||||
POTHOLE_MODEL = ("23", "023", "坑槽检测模型", 'pothole', lambda device, gpuName: { # 目前集成到另外的模型中去了 不单独使用
|
||||
'device': device,
|
||||
'labelnames': ["坑槽"],
|
||||
'trackPar':{'sort_max_age':2,'sort_min_hits':3,'sort_iou_thresh':0.2,'det_cnt':3,'windowsize':29,'patchCnt':100},
|
||||
'postProcess':{'function':default_mix,'pars':{ }},
|
||||
'models':
|
||||
[
|
||||
{
|
||||
'weight':"../AIlib2/weights/pothole/yolov5_%s_fp16.engine"% gpuName,###检测模型路径
|
||||
'name':'yolov5',
|
||||
'model':yolov5Model,
|
||||
'par':{ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':[0,1,2,3],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False, "score_byClass":{"0":0.25,"1":0.3,"2":0.3,"3":0.3}},
|
||||
}
|
||||
],
|
||||
'detModelpara':[{"id":str(x),"config":{"k1":"v1","k2":"v2"}} for x in [0]],###控制哪些检测类别显示、输出
|
||||
'postFile': {
|
||||
"name": "post_process",
|
||||
"conf_thres": 0.25,
|
||||
"iou_thres": 0.45,
|
||||
"classes": 5,
|
||||
"rainbows": COLOR
|
||||
},
|
||||
'txtFontSize': 40,
|
||||
'digitFont': {
|
||||
'line_thickness': 2,
|
||||
'boxLine_thickness': 1,
|
||||
'fontSize': 1.0,
|
||||
'segLineShow': False,
|
||||
'waterLineColor': (0, 255, 255),
|
||||
'waterLineWidth': 3
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@staticmethod
|
||||
def checkCode(code):
|
||||
for model in ModelType2:
|
||||
if model.value[1] == code:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
'''
|
||||
参数1: 检测目标名称
|
||||
参数2: 检测目标
|
||||
参数3: 初始化百度检测客户端
|
||||
'''
|
||||
|
||||
|
||||
@unique
|
||||
class BaiduModelTarget2(Enum):
|
||||
VEHICLE_DETECTION = (
|
||||
"车辆检测", 0, lambda client0, client1, url, request_id: client0.vehicleDetectUrl(url, request_id))
|
||||
|
||||
HUMAN_DETECTION = (
|
||||
"人体检测与属性识别", 1, lambda client0, client1, url, request_id: client1.bodyAttr(url, request_id))
|
||||
|
||||
PEOPLE_COUNTING = ("人流量统计", 2, lambda client0, client1, url, request_id: client1.bodyNum(url, request_id))
|
||||
|
||||
|
||||
BAIDU_MODEL_TARGET_CONFIG2 = {
|
||||
BaiduModelTarget2.VEHICLE_DETECTION.value[1]: BaiduModelTarget2.VEHICLE_DETECTION,
|
||||
BaiduModelTarget2.HUMAN_DETECTION.value[1]: BaiduModelTarget2.HUMAN_DETECTION,
|
||||
BaiduModelTarget2.PEOPLE_COUNTING.value[1]: BaiduModelTarget2.PEOPLE_COUNTING
|
||||
}
|
||||
|
||||
EPIDEMIC_PREVENTION_CONFIG = {1: "行程码", 2: "健康码"}
|
||||
|
||||
|
||||
# 模型分析方式
|
||||
@unique
|
||||
class ModelMethodTypeEnum2(Enum):
|
||||
# 方式一: 正常识别方式
|
||||
NORMAL = 1
|
||||
|
||||
# 方式二: 追踪识别方式
|
||||
TRACE = 2
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
from enum import Enum, unique
|
||||
|
||||
|
||||
# 录屏状态枚举
|
||||
@unique
|
||||
class RecordingStatus(Enum):
|
||||
|
||||
RECORDING_WAITING = ("5", "待录制")
|
||||
|
||||
RECORDING_RETRYING = ("10", "重试中")
|
||||
|
||||
RECORDING_RUNNING = ("15", "录制中")
|
||||
|
||||
RECORDING_SUCCESS = ("20", "录制完成")
|
||||
|
||||
RECORDING_TIMEOUT = ("25", "录制超时")
|
||||
|
||||
RECORDING_FAILED = ("30", "录制失败")
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
from enum import Enum, unique
|
||||
|
||||
|
||||
@unique
|
||||
class PushStreamStatus(Enum):
|
||||
WAITING = (5, "待推流")
|
||||
|
||||
RETRYING = (10, "重试中")
|
||||
|
||||
RUNNING = (15, "推流中")
|
||||
|
||||
STOPPING = (20, "停止中")
|
||||
|
||||
SUCCESS = (25, "完成")
|
||||
|
||||
TIMEOUT = (30, "超时")
|
||||
|
||||
FAILED = (35, "失败")
|
||||
|
||||
|
||||
@unique
|
||||
class ExecuteStatus(Enum):
|
||||
WAITING = (5, "待执行")
|
||||
|
||||
RUNNING = (10, "执行中")
|
||||
|
||||
STOPPING = (15, "停止中")
|
||||
|
||||
SUCCESS = (20, "执行完成")
|
||||
|
||||
TIMEOUT = (25, "超时")
|
||||
|
||||
FAILED = (30, "失败")
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from loguru import logger
|
||||
|
||||
|
||||
"""
|
||||
自定义异常
|
||||
"""
|
||||
|
||||
|
||||
class ServiceException(Exception): # 继承异常类
|
||||
def __init__(self, code, msg, desc=None):
|
||||
self.code = code
|
||||
if desc is None:
|
||||
self.msg = msg
|
||||
else:
|
||||
self.msg = msg % desc
|
||||
|
||||
def __str__(self):
|
||||
logger.error("异常编码:{}, 异常描述:{}", self.code, self.msg)
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
|
|
@ -0,0 +1,118 @@
|
|||
Package Version
|
||||
-------------------------- ------------
|
||||
aiohttp 3.8.4
|
||||
aiosignal 1.3.1
|
||||
alibabacloud-credentials 0.3.2
|
||||
alibabacloud-endpoint-util 0.0.3
|
||||
alibabacloud-gateway-spi 0.0.1
|
||||
alibabacloud-openapi-util 0.2.1
|
||||
alibabacloud-tea 0.3.1
|
||||
alibabacloud-tea-openapi 0.3.7
|
||||
alibabacloud-tea-util 0.3.8
|
||||
alibabacloud-tea-xml 0.0.2
|
||||
alibabacloud-vod20170321 2.16.16
|
||||
aliyun-python-sdk-core 2.13.36
|
||||
aliyun-python-sdk-core-v3 2.13.33
|
||||
aliyun-python-sdk-kms 2.16.0
|
||||
aliyun-python-sdk-live 3.9.35
|
||||
aliyun-python-sdk-vod 2.16.16
|
||||
argon2-cffi 23.1.0
|
||||
argon2-cffi-bindings 21.2.0
|
||||
async-timeout 4.0.2
|
||||
attrs 23.1.0
|
||||
baidu-aip 4.16.10
|
||||
Cerberus 1.3.4
|
||||
certifi 2022.12.7
|
||||
cffi 1.15.1
|
||||
chardet 5.1.0
|
||||
charset-normalizer 3.1.0
|
||||
click 8.1.3
|
||||
coloredlogs 15.0.1
|
||||
contourpy 1.0.7
|
||||
crcmod 1.7
|
||||
cryptography 40.0.2
|
||||
cycler 0.11.0
|
||||
Cython 0.29.34
|
||||
dotadevkit 1.3.0
|
||||
easydict 1.10
|
||||
ffmpeg-python 0.2.0
|
||||
ffprobe 0.5
|
||||
filelock 3.9.0
|
||||
filetype 1.2.0
|
||||
filterpy 1.4.5
|
||||
flatbuffers 23.3.3
|
||||
fonttools 4.39.3
|
||||
frozenlist 1.3.3
|
||||
future 0.18.3
|
||||
gmpy2 2.1.2
|
||||
GPUtil 1.4.0
|
||||
humanfriendly 10.0
|
||||
idna 3.4
|
||||
imageio 2.31.1
|
||||
importlib-resources 5.12.0
|
||||
Jinja2 3.1.2
|
||||
jmespath 0.10.0
|
||||
kafka-python 2.0.2
|
||||
kiwisolver 1.4.4
|
||||
lazy_loader 0.3
|
||||
loguru 0.7.0
|
||||
MarkupSafe 2.1.1
|
||||
matplotlib 3.7.1
|
||||
meson 1.1.0
|
||||
minio 7.2.7
|
||||
mkl-fft 1.3.1
|
||||
mkl-random 1.2.2
|
||||
mkl-service 2.4.0
|
||||
mpmath 1.3.0
|
||||
multidict 6.0.4
|
||||
networkx 2.8.4
|
||||
numpy 1.24.3
|
||||
nvidia-cublas-cu11 11.11.3.6
|
||||
nvidia-cuda-runtime-cu11 11.8.89
|
||||
nvidia-cudnn-cu11 8.9.0.131
|
||||
onnx 1.14.0
|
||||
onnxruntime 1.14.1
|
||||
opencv-contrib-python 4.7.0.72
|
||||
opencv-python 4.7.0.72
|
||||
opencv-python-headless 4.7.0.72
|
||||
oss2 2.17.0
|
||||
packaging 23.1
|
||||
paho-mqtt 2.1.0
|
||||
pandas 2.0.1
|
||||
Pillow 9.5.0
|
||||
pip 23.0.1
|
||||
protobuf 4.22.4
|
||||
psutil 5.9.5
|
||||
pycparser 2.21
|
||||
pycryptodome 3.17
|
||||
pyparsing 3.0.9
|
||||
python-dateutil 2.8.2
|
||||
python-vlc 3.0.18122
|
||||
pytz 2023.3
|
||||
PyWavelets 1.4.1
|
||||
PyYAML 6.0
|
||||
requests 2.30.0
|
||||
ruamel.yaml 0.17.22
|
||||
ruamel.yaml.clib 0.2.7
|
||||
scikit-image 0.21.0
|
||||
scipy 1.10.1
|
||||
seaborn 0.12.2
|
||||
setuptools 66.0.0
|
||||
shapely 2.0.1
|
||||
six 1.16.0
|
||||
sympy 1.11.1
|
||||
tensorrt 8.5.1.7
|
||||
tifffile 2023.7.4
|
||||
torch 1.9.1+cu111
|
||||
torchaudio 2.0.0
|
||||
torchvision 0.10.1+cu111
|
||||
tqdm 4.65.0
|
||||
triton 2.0.0
|
||||
ttkbootstrap 1.10.1
|
||||
typing_extensions 4.5.0
|
||||
tzdata 2023.3
|
||||
urllib3 2.0.2
|
||||
voduploadsdk 1.0.2
|
||||
wheel 0.38.4
|
||||
yarl 1.9.2
|
||||
zipp 3.15.0
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
scp -r common concurrency dsp_master.py entity enums exception font image __init__.py output __pycache__ readme.md service test util vodsdk thsw2@192.168.10.66:/home/thsw2/WJ/test/tuoheng_algN
|
||||
|
||||
|
||||
|
||||
scp -r common concurrency dsp_master.py entity enums exception font image __init__.py output __pycache__ readme.md service test util vodsdk thsw@192.168.10.11:/home/thsw/WJ/test/tuoheng_algN
|
||||
|
|
@ -0,0 +1,602 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import time,os
|
||||
from os.path import join
|
||||
from traceback import format_exc
|
||||
import json
|
||||
from cerberus import Validator
|
||||
|
||||
from common.Constant import ONLINE_START_SCHEMA, ONLINE_STOP_SCHEMA, OFFLINE_START_SCHEMA, OFFLINE_STOP_SCHEMA, \
|
||||
IMAGE_SCHEMA, RECORDING_START_SCHEMA, RECORDING_STOP_SCHEMA, PULL2PUSH_START_SCHEMA, PULL2PUSH_STOP_SCHEMA
|
||||
from common.YmlConstant import service_yml_path, kafka_yml_path
|
||||
from concurrency.FeedbackThread import FeedbackThread
|
||||
from concurrency.uploadGPU import uploadGPUinfos
|
||||
from concurrency.IntelligentRecognitionProcess2 import OnlineIntelligentRecognitionProcess2, \
|
||||
OfflineIntelligentRecognitionProcess2, PhotosIntelligentRecognitionProcess2
|
||||
from concurrency.Pull2PushStreamProcess import PushStreamProcess
|
||||
from entity.FeedBack import message_feedback, recording_feedback, pull_stream_feedback
|
||||
from enums.AnalysisStatusEnum import AnalysisStatus
|
||||
from enums.AnalysisTypeEnum import AnalysisType
|
||||
from enums.ExceptionEnum import ExceptionType
|
||||
from enums.ModelTypeEnum import ModelMethodTypeEnum, ModelType
|
||||
from enums.RecordingStatusEnum import RecordingStatus
|
||||
from enums.StatusEnum import PushStreamStatus, ExecuteStatus
|
||||
from exception.CustomerException import ServiceException
|
||||
from loguru import logger
|
||||
from multiprocessing import Queue
|
||||
from concurrency.IntelligentRecognitionProcess import OnlineIntelligentRecognitionProcess, \
|
||||
OfflineIntelligentRecognitionProcess, PhotosIntelligentRecognitionProcess, ScreenRecordingProcess
|
||||
from util.CpuUtils import print_cpu_ex_status
|
||||
from util.FileUtils import create_dir_not_exist
|
||||
from util.GPUtils import get_first_gpu_name, print_gpu_ex_status, check_cude_is_available,select_best_server
|
||||
from util.KafkaUtils import CustomerKafkaConsumer
|
||||
from util.QueUtil import put_queue
|
||||
from util.RWUtils import getConfigs
|
||||
from kafka import KafkaProducer, KafkaConsumer
|
||||
'''
|
||||
分发服务
|
||||
'''
|
||||
|
||||
|
||||
class DispatcherService:
|
||||
__slots__ = ('__context', '__feedbackThread', '__listeningProcesses', '__fbQueue', '__topics','__taskType', '__task_type',
|
||||
'__kafka_config', '__recordingProcesses', '__pull2PushProcesses','__topicsPort','__gpuTopic','__role','__uploadGPUThread','__gpuDics','__producer')
|
||||
|
||||
def __init__(self, base_dir, env):
|
||||
# 检测cuda是否活动
|
||||
check_cude_is_available()
|
||||
# 获取全局上下文配置
|
||||
self.__context = getConfigs(join(base_dir, service_yml_path % env))
|
||||
# 创建任务执行, 视频保存路径
|
||||
create_dir_not_exist(join(base_dir, self.__context["video"]["file_path"]))
|
||||
# 将根路径和环境设置到上下文中
|
||||
self.__context["base_dir"], self.__context["env"] = base_dir, env
|
||||
|
||||
# 问题反馈线程
|
||||
self.__feedbackThread,self.__uploadGPUThread, self.__fbQueue = None,None, Queue()
|
||||
# 实时、离线、图片任务进程字典
|
||||
self.__listeningProcesses = {}
|
||||
# 录屏任务进程字典
|
||||
self.__recordingProcesses = {}
|
||||
# 转推流任务进程字典
|
||||
self.__pull2PushProcesses = {}
|
||||
self.__kafka_config = getConfigs(join(base_dir, kafka_yml_path % env))
|
||||
|
||||
self.__producer = KafkaProducer(
|
||||
bootstrap_servers=self.__kafka_config['bootstrap_servers'],#tencent yun
|
||||
value_serializer=lambda v: v.encode('utf-8'))
|
||||
|
||||
self.__gpuDics = { }#用于存储gpu信息的字典
|
||||
self.__role = self.__context["role"]
|
||||
self.__topics = [
|
||||
self.__kafka_config["topic"]["dsp-alg-online-tasks-topic"], # 实时监听topic
|
||||
self.__kafka_config["topic"]["dsp-alg-offline-tasks-topic"], # 离线监听topic
|
||||
self.__kafka_config["topic"]["dsp-alg-image-tasks-topic"], # 图片监听topic
|
||||
self.__kafka_config["topic"]["dsp-recording-task-topic"], # 录屏监听topic
|
||||
self.__kafka_config["topic"]["dsp-push-stream-task-topic"] # 推流监听topic
|
||||
]
|
||||
|
||||
self.__topicsPort = [
|
||||
self.__kafka_config["topicPort"]["dsp-alg-online-tasks-topic"], # 实时监听topic
|
||||
self.__kafka_config["topicPort"]["dsp-alg-offline-tasks-topic"], # 离线监听topic
|
||||
self.__kafka_config["topicPort"]["dsp-alg-image-tasks-topic"], # 图片监听topic
|
||||
self.__kafka_config["topicPort"]["dsp-recording-task-topic"], # 录屏监听topic
|
||||
self.__kafka_config["topicPort"]["dsp-push-stream-task-topic"] # 推流监听topic
|
||||
]
|
||||
self.__gpuTopic = [self.__kafka_config["topicGPU"]]
|
||||
|
||||
if self.__role==1:
|
||||
self.__topics = self.__topics + self.__topicsPort + self.__gpuTopic
|
||||
|
||||
|
||||
# 对应topic的各个lambda表达式
|
||||
self.__task_type = {
|
||||
self.__topics[0]: (AnalysisType.ONLINE.value, lambda x, y: self.online(x, y),
|
||||
lambda x, y, z: self.identify_method(x, y, z)),
|
||||
self.__topics[1]: (AnalysisType.OFFLINE.value, lambda x, y: self.offline(x, y),
|
||||
lambda x, y, z: self.identify_method(x, y, z)),
|
||||
self.__topics[2]: (AnalysisType.IMAGE.value, lambda x, y: self.image(x, y),
|
||||
lambda x, y, z: self.identify_method(x, y, z)),
|
||||
self.__topics[3]: (AnalysisType.RECORDING.value, lambda x, y: self.recording(x, y),
|
||||
lambda x, y, z: self.recording_method(x, y, z)),
|
||||
self.__topics[4]: (AnalysisType.PULLTOPUSH.value, lambda x, y: self.pullStream(x, y),
|
||||
lambda x, y, z: self.push_stream_method(x, y, z))
|
||||
|
||||
}
|
||||
self.__taskType={
|
||||
self.__kafka_config["topic"]["dsp-alg-online-tasks-topic"]:0, # 实时监听topic
|
||||
self.__kafka_config["topic"]["dsp-alg-offline-tasks-topic"]:1, # 离线监听topic
|
||||
self.__kafka_config["topic"]["dsp-alg-image-tasks-topic"]:2, # 图片监听topic
|
||||
self.__kafka_config["topic"]["dsp-recording-task-topic"]:3, # 录屏监听topic
|
||||
self.__kafka_config["topic"]["dsp-push-stream-task-topic"]:4 # 推流监听topic
|
||||
}
|
||||
gpu_name_array = get_first_gpu_name()
|
||||
gpu_array = [g for g in ('3090', '2080', '4090', 'A10') if g in gpu_name_array]
|
||||
gpu_name = '2080Ti'
|
||||
if len(gpu_array) > 0:
|
||||
if gpu_array[0] != '2080':
|
||||
gpu_name = gpu_array[0]
|
||||
else:
|
||||
raise Exception("GPU资源不在提供的模型所支持的范围内!请先提供对应的GPU模型!")
|
||||
logger.info("当前服务环境为: {}, 服务器GPU使用型号: {}", env, gpu_name)
|
||||
self.__context["gpu_name"] = gpu_name
|
||||
self.start_service()
|
||||
|
||||
# 服务调用启动方法
|
||||
def start_service(self):
|
||||
# 初始化kafka监听者
|
||||
customerKafkaConsumer = CustomerKafkaConsumer(self.__kafka_config, topics=self.__topics)
|
||||
####增加一个线程,用于试试监控和发送gpu状态####
|
||||
####
|
||||
logger.info("(♥◠‿◠)ノ゙ DSP【算法调度服务】启动成功 服务器IP:{}".format(self.__kafka_config['bootstrap_servers'] ))
|
||||
while True:
|
||||
try:
|
||||
# 检查任务进程运行情况,去除结束的任务
|
||||
self.check_process_task()
|
||||
# 启动反馈线程
|
||||
self.start_feedback_thread()
|
||||
self.start_uploadGPU_thread()
|
||||
msg = customerKafkaConsumer.poll()
|
||||
if msg is not None and len(msg) > 0:
|
||||
for k, v in msg.items():
|
||||
for m in v:
|
||||
message = m.value
|
||||
#如果收到的信息是gpu状态的话,收到信息后,更新自己的gpu服务器状态,下面不再执行
|
||||
if m.topic in self.__gpuTopic:
|
||||
customerKafkaConsumer.commit_offset(m,'x'*16,False)
|
||||
#更新机器资源现状
|
||||
ip = message['System']['Local IP Address']
|
||||
self.__gpuDics[ip]=message
|
||||
continue
|
||||
#如果收到的信息是门户消息,收到信息后,要根据Gpu状态,转发到对应的机器。
|
||||
elif m.topic in self.__topicsPort:
|
||||
customerKafkaConsumer.commit_offset(m, 'y'*16)
|
||||
#状态分析
|
||||
#recondGpu={'hostname':'thsw2','IP':'192.168.10.66','gpuId':0}
|
||||
recondGpu= select_best_server(self.__gpuDics)
|
||||
if recondGpu is None:
|
||||
print( 'recondGpu:',recondGpu, ' self.__gpuDics: ',self.__gpuDics,' topic:',m.topic, ' message:',message )
|
||||
continue
|
||||
#转发消息
|
||||
message['transmit_topic'] = m.topic + '-' + recondGpu['IP']
|
||||
transmitMsg={'transmit':message}
|
||||
msg_json = json.dumps( message )
|
||||
future = self.__producer.send( message['transmit_topic'] ,msg_json)
|
||||
try:
|
||||
future.get(timeout=2)
|
||||
logger.info( "转发消息成功,消息topic:{},消息内容:{}",message['transmit_topic'],message )
|
||||
except kafka_errors as e:
|
||||
print('------transmitted error:',e)
|
||||
logger.info("转发消息失败")
|
||||
traceback.format_exc()
|
||||
else:
|
||||
requestId = message.get("request_id")
|
||||
if requestId is None:
|
||||
logger.error("请求参数格式错误, 请检查请求体格式是否正确!message:%s"%(message))
|
||||
continue
|
||||
customerKafkaConsumer.commit_offset(m, requestId)
|
||||
logger.info("当前拉取到的消息, topic:{}, offset:{}, partition: {}, body: {}, requestId:{}",
|
||||
m.topic, m.offset, m.partition, message, requestId)
|
||||
|
||||
message['taskType']=self.__taskType[m.topic]
|
||||
topic_method = self.__task_type[m.topic]
|
||||
topic_method[2](topic_method[1], message, topic_method[0])
|
||||
else:
|
||||
print_gpu_ex_status()
|
||||
print_cpu_ex_status(self.__context["base_dir"])
|
||||
time.sleep(1)
|
||||
except Exception:
|
||||
logger.error("主线程异常:{}", format_exc())
|
||||
|
||||
|
||||
|
||||
|
||||
def identify_method(self, handle_method, message, analysisType):
|
||||
try:
|
||||
check_cude_is_available()
|
||||
handle_method(message, analysisType)
|
||||
except ServiceException as s:
|
||||
logger.error("消息监听异常:{}, requestId: {}", s.msg, message["request_id"])
|
||||
put_queue(self.__fbQueue, message_feedback(message["request_id"], AnalysisStatus.FAILED.value, analysisType,
|
||||
s.code, s.msg), timeout=1)
|
||||
except Exception:
|
||||
logger.error("消息监听异常:{}, requestId: {}", format_exc(), message["request_id"])
|
||||
put_queue(self.__fbQueue, message_feedback(message["request_id"], AnalysisStatus.FAILED.value, analysisType,
|
||||
ExceptionType.SERVICE_INNER_EXCEPTION.value[0],
|
||||
ExceptionType.SERVICE_INNER_EXCEPTION.value[1]), timeout=1)
|
||||
finally:
|
||||
del message
|
||||
|
||||
def push_stream_method(self, handle_method, message, analysisType):
|
||||
try:
|
||||
check_cude_is_available()
|
||||
handle_method(message, analysisType)
|
||||
except ServiceException as s:
|
||||
logger.error("消息监听异常:{}, requestId: {}", s.msg, message['request_id'])
|
||||
videoInfo = [{"id": url.get("id"), "status": PushStreamStatus.FAILED.value[0]} for url in
|
||||
message.get("video_urls", []) if url.get("id") is not None]
|
||||
put_queue(self.__fbQueue, pull_stream_feedback(message['request_id'], ExecuteStatus.FAILED.value[0],
|
||||
s.code, s.msg, videoInfo), timeout=1)
|
||||
except Exception:
|
||||
logger.error("消息监听异常:{}, requestId: {}", format_exc(), message['request_id'])
|
||||
videoInfo = [{"id": url.get("id"), "status": PushStreamStatus.FAILED.value[0]} for url in
|
||||
message.get("video_urls", []) if url.get("id") is not None]
|
||||
put_queue(self.__fbQueue, pull_stream_feedback(message.get("request_id"), ExecuteStatus.FAILED.value[0],
|
||||
ExceptionType.SERVICE_INNER_EXCEPTION.value[0],
|
||||
ExceptionType.SERVICE_INNER_EXCEPTION.value[1], videoInfo),
|
||||
timeout=1)
|
||||
finally:
|
||||
del message
|
||||
|
||||
def recording_method(self, handle_method, message, analysisType):
|
||||
try:
|
||||
check_cude_is_available()
|
||||
handle_method(message, analysisType)
|
||||
except ServiceException as s:
|
||||
logger.error("消息监听异常:{}, requestId: {}", s.msg, message["request_id"])
|
||||
put_queue(self.__fbQueue,
|
||||
recording_feedback(message["request_id"], RecordingStatus.RECORDING_FAILED.value[0],
|
||||
error_code=s.code, error_msg=s.msg), timeout=1)
|
||||
except Exception:
|
||||
logger.error("消息监听异常:{}, requestId: {}", format_exc(), message["request_id"])
|
||||
put_queue(self.__fbQueue,
|
||||
recording_feedback(message["request_id"], RecordingStatus.RECORDING_FAILED.value[0],
|
||||
ExceptionType.SERVICE_INNER_EXCEPTION.value[0],
|
||||
ExceptionType.SERVICE_INNER_EXCEPTION.value[1]), timeout=1)
|
||||
finally:
|
||||
del message
|
||||
|
||||
# 开启实时进程
|
||||
def startOnlineProcess(self, msg, analysisType):
|
||||
|
||||
#0521:
|
||||
default_enabled = str(msg.get("defaultEnabled", "True")).lower() == "true"
|
||||
|
||||
if default_enabled:
|
||||
print("执行默认程序(defaultEnabled=True)")
|
||||
self.__context['service']['algSwitch'] = True
|
||||
# 这里放默认逻辑的代码
|
||||
else:
|
||||
print("执行替代程序(defaultEnabled=False)")
|
||||
# 这里放非默认逻辑的代码
|
||||
self.__context['service']['algSwitch'] = False
|
||||
|
||||
|
||||
print("---line264-Dispatcher.py---",self.__context)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if self.__listeningProcesses.get(msg["request_id"]):
|
||||
logger.warning("实时重复任务,请稍后再试!requestId:{}", msg["request_id"])
|
||||
return
|
||||
|
||||
model_type = self.__context["service"]["model"]["model_type"]
|
||||
codes = [model.get("code") for model in msg["models"] if model.get("code")]
|
||||
if ModelMethodTypeEnum.NORMAL.value == model_type or ModelType.ILLPARKING_MODEL.value[1] in codes:
|
||||
coir = OnlineIntelligentRecognitionProcess(self.__fbQueue, msg, analysisType, self.__context)
|
||||
else:
|
||||
coir = OnlineIntelligentRecognitionProcess2(self.__fbQueue, msg, analysisType, self.__context)
|
||||
coir.start()
|
||||
logger.info("开始实时进程!requestId:{},pid:{}, ppid:{}", msg["request_id"],os.getpid(),os.getppid())
|
||||
self.__listeningProcesses[msg["request_id"]] = coir
|
||||
|
||||
# 结束实时进程
|
||||
def stopOnlineProcess(self, msg):
|
||||
ps = self.__listeningProcesses.get(msg["request_id"])
|
||||
if ps is None:
|
||||
logger.warning("未查询到该任务,无法停止任务!requestId:{}", msg["request_id"])
|
||||
return
|
||||
ps.sendEvent({"command": "stop"})
|
||||
|
||||
# 新增该函数用于,向子任务发送命令(algStart,algStop)
|
||||
def sendCmdToChildProcess(self, msg,cmd="algStart"):
|
||||
ps = self.__listeningProcesses.get(msg["request_id"])
|
||||
if ps is None:
|
||||
logger.warning("未查询到该任务,无法停止任务!requestId:{}", msg["request_id"])
|
||||
return
|
||||
ps.sendEvent({"command": cmd})
|
||||
|
||||
@staticmethod
|
||||
def check_process(listeningProcess):
|
||||
for requestId in list(listeningProcess.keys()):
|
||||
if not listeningProcess[requestId].is_alive():
|
||||
del listeningProcess[requestId]
|
||||
|
||||
def check_process_task(self):
|
||||
self.check_process(self.__listeningProcesses)
|
||||
self.check_process(self.__recordingProcesses)
|
||||
self.check_process(self.__pull2PushProcesses)
|
||||
|
||||
# 开启离线进程
|
||||
def startOfflineProcess(self, msg, analysisType):
|
||||
if self.__listeningProcesses.get(msg["request_id"]):
|
||||
logger.warning("离线重复任务,请稍后再试!requestId:{}", msg["request_id"])
|
||||
return
|
||||
model_type = self.__context["service"]["model"]["model_type"]
|
||||
codes = [model.get("code") for model in msg["models"] if model.get("code")]
|
||||
if ModelMethodTypeEnum.NORMAL.value == model_type:
|
||||
first = OfflineIntelligentRecognitionProcess(self.__fbQueue, msg, analysisType, self.__context)
|
||||
else:
|
||||
first = OfflineIntelligentRecognitionProcess2(self.__fbQueue, msg, analysisType, self.__context)
|
||||
first.start()
|
||||
self.__listeningProcesses[msg["request_id"]] = first
|
||||
|
||||
# 结束离线进程
|
||||
def stopOfflineProcess(self, msg):
|
||||
ps = self.__listeningProcesses.get(msg["request_id"])
|
||||
if ps is None:
|
||||
logger.warning("未查询到该任务,无法停止任务!requestId:{}", msg["request_id"])
|
||||
return
|
||||
ps.sendEvent({"command": "stop"})
|
||||
|
||||
# 开启图片分析进程
|
||||
def startImageProcess(self, msg, analysisType):
|
||||
pp = self.__listeningProcesses.get(msg["request_id"])
|
||||
if pp is not None:
|
||||
logger.warning("重复任务,请稍后再试!requestId:{}", msg["request_id"])
|
||||
return
|
||||
model_type = self.__context["service"]["model"]["model_type"]
|
||||
codes = [model.get("code") for model in msg["models"] if model.get("code")]
|
||||
if ModelMethodTypeEnum.NORMAL.value == model_type or ModelType.ILLPARKING_MODEL.value[1] in codes:
|
||||
imaged = PhotosIntelligentRecognitionProcess(self.__fbQueue, msg, analysisType, self.__context)
|
||||
else:
|
||||
imaged = PhotosIntelligentRecognitionProcess2(self.__fbQueue, msg, analysisType, self.__context)
|
||||
# 创建在线识别进程并启动
|
||||
imaged.start()
|
||||
self.__listeningProcesses[msg["request_id"]] = imaged
|
||||
|
||||
'''
|
||||
校验kafka消息
|
||||
'''
|
||||
|
||||
|
||||
|
||||
@staticmethod
|
||||
def check_msg(msg, schema):
|
||||
|
||||
|
||||
# #0521
|
||||
# # 检查 defaultEnabled 是否为 True(兼容字符串和布尔值)
|
||||
# default_enabled = str(msg1.get("defaultEnabled", "True")).lower() == "true"
|
||||
|
||||
# # 如果不是 True,强制设置 command 为 'algStop'
|
||||
# if not default_enabled and msg1["command"] == "algStart" :
|
||||
# msg1["command"] = "algStop"
|
||||
|
||||
# msg = msg1
|
||||
|
||||
|
||||
try:
|
||||
v = Validator(schema, allow_unknown=True)
|
||||
result = v.validate(msg)
|
||||
if not result:
|
||||
logger.error("参数校验异常: {}, requestId: {}", v.errors, msg["request_id"])
|
||||
raise ServiceException(ExceptionType.ILLEGAL_PARAMETER_FORMAT.value[0],
|
||||
ExceptionType.ILLEGAL_PARAMETER_FORMAT.value[1])
|
||||
except ServiceException as s:
|
||||
raise s
|
||||
except Exception:
|
||||
logger.error("参数校验异常: {}, requestId: {}", format_exc(), msg["request_id"])
|
||||
raise ServiceException(ExceptionType.ILLEGAL_PARAMETER_FORMAT.value[0],
|
||||
ExceptionType.ILLEGAL_PARAMETER_FORMAT.value[1])
|
||||
|
||||
'''
|
||||
开启反馈线程,用于发送消息
|
||||
'''
|
||||
|
||||
def start_feedback_thread(self):
|
||||
if self.__feedbackThread is None:
|
||||
self.__feedbackThread = FeedbackThread(self.__fbQueue, self.__kafka_config)
|
||||
self.__feedbackThread.setDaemon(True)
|
||||
self.__feedbackThread.start()
|
||||
time.sleep(1)
|
||||
if self.__feedbackThread and not self.__feedbackThread.is_alive():
|
||||
logger.error("反馈线程异常停止, 开始重新启动反馈线程!!!!!")
|
||||
self.__feedbackThread = FeedbackThread(self.__fbQueue, self.__kafka_config)
|
||||
self.__feedbackThread.setDaemon(True)
|
||||
self.__feedbackThread.start()
|
||||
time.sleep(1)
|
||||
|
||||
def start_uploadGPU_thread(self):
|
||||
if self.__uploadGPUThread is None:
|
||||
self.__uploadGPUThread = uploadGPUinfos(self.__context, self.__kafka_config)
|
||||
self.__uploadGPUThread.setDaemon(True)
|
||||
self.__uploadGPUThread.start()
|
||||
time.sleep(1)
|
||||
if self.__uploadGPUThread and not self.__uploadGPUThread.is_alive():
|
||||
logger.error("反馈线程异常停止, 开始重新启动反馈线程!!!!!")
|
||||
self.__uploadGPUThread = uploadGPUinfos(self.__context, self.__kafka_config)
|
||||
self.__uploadGPUThread.setDaemon(True)
|
||||
self.__uploadGPUThread.start()
|
||||
time.sleep(1)
|
||||
|
||||
'''
|
||||
在线分析逻辑
|
||||
'''
|
||||
|
||||
#0520:主要是在线分析 -- "algStart","algStop" 外部多增加一层逻辑
|
||||
|
||||
# def online(self, message, analysisType):
|
||||
# if "start" == message.get("command"):
|
||||
# self.check_msg(message, ONLINE_START_SCHEMA)
|
||||
# if len(self.__listeningProcesses) >= int(self.__context['service']["task"]["limit"]):
|
||||
# raise ServiceException(ExceptionType.NO_RESOURCES.value[0],
|
||||
# ExceptionType.NO_RESOURCES.value[1])
|
||||
# self.startOnlineProcess(message, analysisType)
|
||||
# elif message.get("command") in ["algStart","algStop"]:
|
||||
# self.sendCmdToChildProcess(message,cmd=message.get("command"))
|
||||
# elif "stop" == message.get("command"):
|
||||
# self.check_msg(message, ONLINE_STOP_SCHEMA)
|
||||
# self.stopOnlineProcess(message)
|
||||
# else:
|
||||
# raise ServiceException(ExceptionType.ILLEGAL_PARAMETER_FORMAT.value[0],
|
||||
# ExceptionType.ILLEGAL_PARAMETER_FORMAT.value[1])
|
||||
|
||||
|
||||
def online(self, message, analysisType):
|
||||
|
||||
|
||||
|
||||
# #0521
|
||||
# # 检查 defaultEnabled 是否为 True(兼容字符串和布尔值)
|
||||
|
||||
# #逻辑还是有问题 - 肯定是先判断是否为 true
|
||||
# default_enabled = str(message1.get("defaultEnabled", "True")).lower() == "True"
|
||||
|
||||
# # 如果不是 True,强制设置 command 为 'algStop'
|
||||
# if not default_enabled :
|
||||
|
||||
# message.get("command")
|
||||
# message = message1
|
||||
|
||||
|
||||
|
||||
|
||||
# message = message
|
||||
# print("line429",message)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if "start" == message.get("command"):
|
||||
self.check_msg(message, ONLINE_START_SCHEMA)
|
||||
if len(self.__listeningProcesses) >= int(self.__context['service']["task"]["limit"]):
|
||||
raise ServiceException(ExceptionType.NO_RESOURCES.value[0],
|
||||
ExceptionType.NO_RESOURCES.value[1])
|
||||
self.startOnlineProcess(message, analysisType)
|
||||
|
||||
# elif (message.get("command") in ["algStart","algStop"] ) and (message.get("defaultEnabled",True)):
|
||||
# self.sendCmdToChildProcess(message,cmd=message.get("command"))
|
||||
|
||||
|
||||
elif (
|
||||
message is not None # 防止 message 为 None
|
||||
and isinstance(message, dict) # 确保 message 是字典
|
||||
and (command := message.get("command")) in ["algStart", "algStop"] # Python 3.8+ 海象运算符
|
||||
and message.get("defaultEnabled", True) is not False # 显式排除 False
|
||||
):
|
||||
self.sendCmdToChildProcess(message, cmd=command)
|
||||
|
||||
|
||||
|
||||
|
||||
elif "stop" == message.get("command"):
|
||||
self.check_msg(message, ONLINE_STOP_SCHEMA)
|
||||
self.stopOnlineProcess(message)
|
||||
else:
|
||||
raise ServiceException(ExceptionType.ILLEGAL_PARAMETER_FORMAT.value[0],
|
||||
ExceptionType.ILLEGAL_PARAMETER_FORMAT.value[1])
|
||||
|
||||
|
||||
|
||||
|
||||
def offline(self, message, analysisType):
|
||||
|
||||
|
||||
# #0521
|
||||
# # 检查 defaultEnabled 是否为 True(兼容字符串和布尔值)
|
||||
# default_enabled = str(message.get("defaultEnabled", "True")).lower() == "true"
|
||||
|
||||
# # 如果不是 True,强制设置 command 为 'algStop'
|
||||
# if not default_enabled and message["command"] == "algStart" :
|
||||
# message["command"] = "algStop"
|
||||
|
||||
# message = message
|
||||
# print("line429",message)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if "start" == message.get("command"):
|
||||
self.check_msg(message, OFFLINE_START_SCHEMA)
|
||||
if len(self.__listeningProcesses) >= int(self.__context['service']["task"]["limit"]):
|
||||
raise ServiceException(ExceptionType.NO_RESOURCES.value[0],
|
||||
ExceptionType.NO_RESOURCES.value[1])
|
||||
self.startOfflineProcess(message, analysisType)
|
||||
elif message.get("command") in ["algStart","algStop"]:
|
||||
self.sendCmdToChildProcess( message,cmd=message.get("command"))
|
||||
elif "stop" == message.get("command"):
|
||||
self.check_msg(message, OFFLINE_STOP_SCHEMA)
|
||||
self.stopOfflineProcess(message)
|
||||
else:
|
||||
raise ServiceException(ExceptionType.ILLEGAL_PARAMETER_FORMAT.value[0],
|
||||
ExceptionType.ILLEGAL_PARAMETER_FORMAT.value[1])
|
||||
|
||||
def image(self, message, analysisType):
|
||||
if "start" == message.get("command"):
|
||||
self.check_msg(message, IMAGE_SCHEMA)
|
||||
if len(self.__listeningProcesses) >= int(self.__context['service']["task"]["image"]["limit"]):
|
||||
raise ServiceException(ExceptionType.NO_RESOURCES.value[0],
|
||||
ExceptionType.NO_RESOURCES.value[1])
|
||||
self.startImageProcess(message, analysisType)
|
||||
else:
|
||||
raise ServiceException(ExceptionType.ILLEGAL_PARAMETER_FORMAT.value[0],
|
||||
ExceptionType.ILLEGAL_PARAMETER_FORMAT.value[1])
|
||||
|
||||
def recording(self, message, analysisType):
|
||||
if "start" == message.get("command"):
|
||||
self.check_msg(message, RECORDING_START_SCHEMA)
|
||||
if len(self.__recordingProcesses) >= int(self.__context['service']["task"]["limit"]):
|
||||
raise ServiceException(ExceptionType.NO_RESOURCES.value[0],
|
||||
ExceptionType.NO_RESOURCES.value[1])
|
||||
self.startRecordingProcess(message, analysisType)
|
||||
elif "stop" == message.get("command"):
|
||||
self.check_msg(message, RECORDING_STOP_SCHEMA)
|
||||
self.stopRecordingProcess(message)
|
||||
else:
|
||||
raise ServiceException(ExceptionType.ILLEGAL_PARAMETER_FORMAT.value[0],
|
||||
ExceptionType.ILLEGAL_PARAMETER_FORMAT.value[1])
|
||||
|
||||
# 开启录屏进程
|
||||
def startRecordingProcess(self, msg, analysisType):
|
||||
if self.__listeningProcesses.get(msg["request_id"]):
|
||||
logger.warning("重复任务,请稍后再试!requestId:{}", msg["request_id"])
|
||||
return
|
||||
srp = ScreenRecordingProcess(self.__fbQueue, self.__context, msg, analysisType)
|
||||
srp.start()
|
||||
self.__recordingProcesses[msg["request_id"]] = srp
|
||||
|
||||
# 结束录屏进程
|
||||
def stopRecordingProcess(self, msg):
|
||||
rdp = self.__recordingProcesses.get(msg["request_id"])
|
||||
if rdp is None:
|
||||
logger.warning("未查询到该任务,无法停止任务!requestId:{}", msg["request_id"])
|
||||
return
|
||||
rdp.sendEvent({"command": "stop"})
|
||||
|
||||
def pullStream(self, message, analysisType):
|
||||
if "start" == message.get("command"):
|
||||
self.check_msg(message, PULL2PUSH_START_SCHEMA)
|
||||
if len(self.__pull2PushProcesses) >= int(self.__context['service']["task"]["limit"]):
|
||||
raise ServiceException(ExceptionType.NO_RESOURCES.value[0],
|
||||
ExceptionType.NO_RESOURCES.value[1])
|
||||
|
||||
self.startPushStreamProcess(message, analysisType)
|
||||
elif "stop" == message.get("command"):
|
||||
self.check_msg(message, PULL2PUSH_STOP_SCHEMA)
|
||||
self.stopPushStreamProcess(message)
|
||||
else:
|
||||
raise ServiceException(ExceptionType.ILLEGAL_PARAMETER_FORMAT.value[0],
|
||||
ExceptionType.ILLEGAL_PARAMETER_FORMAT.value[1])
|
||||
|
||||
def startPushStreamProcess(self, msg, analysisType):
|
||||
if self.__pull2PushProcesses.get(msg["request_id"]):
|
||||
logger.warning("重复任务,请稍后再试!requestId:{}", msg["request_id"])
|
||||
return
|
||||
srp = PushStreamProcess(self.__fbQueue, self.__context, msg, analysisType)
|
||||
srp.start()
|
||||
self.__pull2PushProcesses[msg["request_id"]] = srp
|
||||
|
||||
# 结束录屏进程
|
||||
def stopPushStreamProcess(self, msg):
|
||||
srp = self.__pull2PushProcesses.get(msg["request_id"])
|
||||
if srp is None:
|
||||
logger.warning("未查询到该任务,无法停止任务!requestId:{}", msg["request_id"])
|
||||
return
|
||||
srp.sendEvent({"command": "stop", "videoIds": msg.get("video_ids", [])})
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/bin/bash
|
||||
current_dir=$(cd "$(dirname "$0")"; pwd)
|
||||
active=$(basename "$(dirname "$current_dir")")
|
||||
conda_env="alg"
|
||||
echo "当前程序所在目录: $current_dir, 当前程序启动环境: $active"
|
||||
if [[ "a${active}" != "adev" && "a${active}" != "atest" && "a${active}" != "aprod" ]]; then
|
||||
echo "###############################################################";
|
||||
echo "启动失败, 当前环境只支持dev、test、prod";
|
||||
echo "环境是根据程序所在目录自动匹配的, 请检测程序路径配置是否正确!";
|
||||
echo "###############################################################";
|
||||
exit 1
|
||||
fi
|
||||
cd $current_dir
|
||||
pid=`ps x | grep "/home/th/anaconda3/envs/${conda_env}/bin/python3.8" | grep -v grep | awk '{print $1}'`
|
||||
if [ -n "$pid" ]; then
|
||||
echo "alg进程已存在, 进程id: $pid"
|
||||
kill -9 ${pid};
|
||||
echo "杀掉当前alg进程, 进程号:$pid"
|
||||
sleep 1
|
||||
pid_1=`ps x | grep "/home/th/anaconda3/envs/${conda_env}/bin/python3.8" | grep -v grep | awk '{print $1}'`
|
||||
if [ -n "$pid_1" ]; then
|
||||
echo "###############################################################";
|
||||
echo "杀掉alg进程失败!"
|
||||
echo "###############################################################";
|
||||
exit 1
|
||||
else
|
||||
echo "杀掉alg进程成功!!"
|
||||
fi
|
||||
fi
|
||||
nohup /home/th/anaconda3/envs/${conda_env}/bin/python3.8 dsp_master.py ${active} > /dev/null 2>&1 &
|
||||
sleep 1
|
||||
pid_end=`ps x | grep "/home/th/anaconda3/envs/${conda_env}/bin/python3.8" | grep -v grep | awk '{print $1}'`
|
||||
if [ -n "$pid_end" ]; then
|
||||
echo "alg启动成功, $pid_end"
|
||||
else
|
||||
echo "###############################################################";
|
||||
echo "alg启动失败!!!!!!!!!!!!!!!!!!!!!!"
|
||||
echo "###############################################################";
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/bash
|
||||
conda_env="alg"
|
||||
pid=`ps x | grep "/home/th/anaconda3/envs/${conda_env}/bin/python3.8" | grep -v grep | awk '{print $1}'`
|
||||
if [ -n "$pid" ]; then
|
||||
kill -9 ${pid};
|
||||
echo "杀掉当前alg进程, 进程号:$pid"
|
||||
fi
|
||||
sleep 1
|
||||
pid_end=`ps x | grep "/home/th/anaconda3/envs/${conda_env}/bin/python3.8" | grep -v grep | awk '{print $1}'`
|
||||
if [ -n "$pid_end" ]; then
|
||||
echo "###############################################################";
|
||||
echo "alg停止失败!!!!!, $pid_end"
|
||||
echo "###############################################################";
|
||||
exit 1
|
||||
else
|
||||
echo "###############################################################";
|
||||
echo "alg停止成功!!!!!!!!!!!!!!!!!!!!!!"
|
||||
echo "###############################################################";
|
||||
fi
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
dd = {}
|
||||
print(dd.get('name', 'aaa'))
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 189 KiB |
|
|
@ -0,0 +1,119 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
|
||||
import cv2
|
||||
import oss2
|
||||
import time
|
||||
|
||||
from loguru import logger
|
||||
|
||||
'''
|
||||
图片上传使用OSS
|
||||
1. 阿里云对象存储OSS官网地址:https://help.aliyun.com/product/31815.html?spm=a2c4g.32006.0.0.8c546cf0BpkAQ2
|
||||
2. 阿里云对象存储OSS SDK示例地址:https://help.aliyun.com/document_detail/32006.html?spm=a2c4g.32006.0.0.66874b78q1pwLa
|
||||
3. python安装SDK地址: https://help.aliyun.com/document_detail/85288.html?spm=a2c4g.32026.0.0.3f24417coCphWj
|
||||
4. 安装SDK: pip install oss2
|
||||
5. 安装python-devel
|
||||
安装python-devel
|
||||
由于SDK需要crcmod库计算CRC校验码,而crcmod依赖Python.h文件,如果系统缺少这个头文件,安装SDK不会失败,但crcmod的C扩展模式安装会失败,因此导致上传、下载等操作效率非常低下。
|
||||
如果python-devel包不存在,则首先要安装这个包。
|
||||
对于Windows系统和Mac OS X系统,由于安装Python的时候会将Python依赖的头文件一并安装,因此您无需安装python-devel。
|
||||
对于CentOS、RHEL、Fedora系统,请执行以下命令安装python-devel。
|
||||
sudo yum install python-devel
|
||||
对于Debian,Ubuntu系统,请执行以下命令安装python-devel。
|
||||
sudo apt-get install python-dev
|
||||
6、图片域名地址:https://image.t-aaron.com/
|
||||
'''
|
||||
|
||||
|
||||
class AliyunOssSdk:
|
||||
|
||||
def __init__(self):
|
||||
self.__client = None
|
||||
self.__access_key = 'LTAI5tMiefafZ6br4zmrQWv9'
|
||||
self.__access_secret = 'JgzQjSCkwZ7lefZO6egOArw38YH1Tk'
|
||||
self.__endpoint = 'http://oss-cn-shanghai.aliyuncs.com'
|
||||
self.__bucket = 'ta-tech-image'
|
||||
|
||||
def get_oss_bucket(self):
|
||||
if not self.__client:
|
||||
auth = oss2.Auth(self.__access_key, self.__access_secret)
|
||||
self.__client = oss2.Bucket(auth, self.__endpoint, self.__bucket, connect_timeout=30)
|
||||
|
||||
def upload_file(self, updatePath, fileByte):
|
||||
logger.info("开始上传文件到oss!")
|
||||
MAX_RETRIES = 3
|
||||
retry_count = 0
|
||||
while True:
|
||||
try:
|
||||
self.get_oss_bucket()
|
||||
result = self.__client.put_object(updatePath, fileByte)
|
||||
return result
|
||||
logger.info("上传文件到oss成功!")
|
||||
break
|
||||
except Exception as e:
|
||||
self.__client = None
|
||||
retry_count += 1
|
||||
time.sleep(1)
|
||||
logger.info("上传文件到oss失败, 重试次数:{}", retry_count)
|
||||
if retry_count > MAX_RETRIES:
|
||||
logger.exception("上传文件到oss重试失败:{}", e)
|
||||
raise e
|
||||
|
||||
|
||||
YY_MM_DD_HH_MM_SS = "%Y-%m-%d %H:%M:%S"
|
||||
YMDHMSF = "%Y%m%d%H%M%S%f"
|
||||
|
||||
def generate_timestamp():
|
||||
"""根据当前时间获取时间戳,返回整数"""
|
||||
return int(time.time())
|
||||
|
||||
def now_date_to_str(fmt=None):
|
||||
if fmt is None:
|
||||
fmt = YY_MM_DD_HH_MM_SS
|
||||
return datetime.datetime.now().strftime(fmt)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 初始化oss对象
|
||||
ossClient = AliyunOssSdk()
|
||||
# 读取本地图片
|
||||
image_frame = cv2.imread('aaa.jpeg')
|
||||
or_result, or_image = cv2.imencode(".jpg", image_frame)
|
||||
# 图片名称命名规则
|
||||
# 1、base_dir 基本文件夹名称,由拓恒公司传参
|
||||
# 2、time_now 现在的时间
|
||||
# 3、current_frame 当前视频的帧数
|
||||
# 4、last_frame 如果有跳帧操作, 填写跳帧的步长,如果没有,和current_frame参数保持一致
|
||||
# 5、random_num 随机时间字符串
|
||||
# 6、mode_type 类型:实时视频直播的方式用(online) 离线视频直播(填写视频地址识别)用(offline)
|
||||
# 7、requestId 请求id, 拓恒公司传参
|
||||
# 8、image_type 原图用(OR) AI识别后的图片用(AI)
|
||||
random_num = now_date_to_str(YMDHMSF)
|
||||
time_now = now_date_to_str("%Y-%m-%d-%H-%M-%S")
|
||||
image_format = "{base_dir}/{time_now}_frame-{current_frame}-{last_frame}_type_{random_num}-{mode_type}-{base_dir}" \
|
||||
"-{requestId}_{image_type}.jpg"
|
||||
image_name = image_format.format(
|
||||
base_dir='PWL202304141639429276',
|
||||
time_now=time_now,
|
||||
current_frame='0',
|
||||
last_frame='0',
|
||||
random_num=random_num,
|
||||
mode_type='offline',
|
||||
requestId='111111111111111111',
|
||||
image_type='OR')
|
||||
result = ossClient.upload_file(image_name, or_image.tobytes())
|
||||
# print('http status: {0}'.format(result.status))
|
||||
# # 请求ID。请求ID是本次请求的唯一标识,强烈建议在程序日志中添加此参数。
|
||||
# print('request_id: {0}'.format(result.request_id))
|
||||
# # ETag是put_object方法返回值特有的属性,用于标识一个Object的内容。
|
||||
# print('ETag: {0}'.format(result.etag))
|
||||
# # HTTP响应头部。
|
||||
# print('date: {0}'.format(result.headers['date']))
|
||||
# print(result.__reduce__())
|
||||
# 对于图片上传, 上传成功后,直接将image_name给拓恒公司就可以了
|
||||
# 如果测试查看图片是否上传成功
|
||||
# 可以使用域名拼接
|
||||
image_url = 'https://image.t-aaron.com/' + image_name
|
||||
print(image_url)
|
||||
# 拓恒公司只需要image_name
|
||||
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
# -*- coding: UTF-8 -*-
|
||||
import json
|
||||
import traceback
|
||||
from aliyunsdkcore.client import AcsClient
|
||||
from aliyunsdkvod.request.v20170321 import CreateUploadVideoRequest
|
||||
from aliyunsdkvod.request.v20170321 import GetPlayInfoRequest
|
||||
from vodsdk.AliyunVodUtils import *
|
||||
from vodsdk.AliyunVodUploader import AliyunVodUploader
|
||||
from vodsdk.UploadVideoRequest import UploadVideoRequest
|
||||
|
||||
# # # 填入AccessKey信息
|
||||
def init_vod_client(accessKeyId, accessKeySecret):
|
||||
regionId = 'cn-shanghai' # 点播服务接入地域
|
||||
connectTimeout = 3 # 连接超时,单位为秒
|
||||
return AcsClient(accessKeyId, accessKeySecret, regionId, auto_retry=True, max_retry_time=3, timeout=connectTimeout)
|
||||
def create_upload_video(clt):
|
||||
request = CreateUploadVideoRequest.CreateUploadVideoRequest()
|
||||
request.set_Title('dddddd')
|
||||
request.set_FileName('/home/thsw/chenyukun/video/111111.mp4')
|
||||
request.set_Description('Video Description')
|
||||
# //CoverURL示例:http://192.168.0.0/16/tps/TB1qnJ1PVXXXXXCXXXXXXXXXXXX-700-700.png
|
||||
# request.set_CoverURL('<your Cover URL>')
|
||||
# request.set_Tags('tag1,tag2')
|
||||
# request.set_CateId(0)
|
||||
|
||||
# request.set_accept_format('JSON')
|
||||
response = json.loads(clt.do_action_with_exception(request))
|
||||
return response
|
||||
|
||||
try:
|
||||
clt = init_vod_client('LTAI5tSJ62TLMUb4SZuf285A', 'MWYynm30filZ7x0HqSHlU3pdLVNeI7')
|
||||
uploadInfo = create_upload_video(clt)
|
||||
print(json.dumps(uploadInfo, ensure_ascii=False, indent=4))
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print(traceback.format_exc())
|
||||
|
||||
# 刷新音视频凭证
|
||||
# from aliyunsdkvod.request.v20170321 import RefreshUploadVideoRequest
|
||||
# def refresh_upload_video(clt, videoId):
|
||||
# request = RefreshUploadVideoRequest.RefreshUploadVideoRequest()
|
||||
# request.set_VideoId(videoId)
|
||||
# request.set_accept_format('JSON')
|
||||
# return json.loads(clt.do_action_with_exception(request))
|
||||
#
|
||||
# try:
|
||||
# clt = init_vod_client('LTAI5tSJ62TLMUb4SZuf285A', 'MWYynm30filZ7x0HqSHlU3pdLVNeI7')
|
||||
# uploadInfo = refresh_upload_video(clt, "d6c419c33da245758f71e362b5ee8b56")
|
||||
# print(json.dumps(uploadInfo, ensure_ascii=False, indent=4))
|
||||
#
|
||||
# except Exception as e:
|
||||
# print(e)
|
||||
# print(traceback.format_exc())
|
||||
#
|
||||
#
|
||||
# # 获取播放地址
|
||||
# def init_vod_client(accessKeyId, accessKeySecret):
|
||||
# regionId = 'cn-shanghai' # 点播服务接入地域
|
||||
# connectTimeout = 3 # 连接超时,单位为秒
|
||||
# return AcsClient(accessKeyId, accessKeySecret, regionId, auto_retry=True, max_retry_time=3, timeout=connectTimeout)
|
||||
# def get_play_info(clt, videoId):
|
||||
# request = GetPlayInfoRequest.GetPlayInfoRequest()
|
||||
# request.set_accept_format('JSON')
|
||||
# request.set_VideoId(videoId)
|
||||
# request.set_AuthTimeout(3600*5)
|
||||
# response = json.loads(clt.do_action_with_exception(request))
|
||||
# return response
|
||||
#
|
||||
# try:
|
||||
# clt = init_vod_client('LTAI5tSJ62TLMUb4SZuf285A', 'MWYynm30filZ7x0HqSHlU3pdLVNeI7')
|
||||
# playInfo = get_play_info(clt, uploadInfo["VideoId"])
|
||||
# print(json.dumps(playInfo, ensure_ascii=False, indent=4))
|
||||
#
|
||||
# except Exception as e:
|
||||
# print(e)
|
||||
# print(traceback.format_exc())
|
||||
#
|
||||
# # 获取视频播放凭证
|
||||
# from aliyunsdkvod.request.v20170321 import GetVideoPlayAuthRequest
|
||||
# def get_video_playauth(clt, videoId):
|
||||
# request = GetVideoPlayAuthRequest.GetVideoPlayAuthRequest()
|
||||
# request.set_accept_format('JSON')
|
||||
# request.set_VideoId(videoId)
|
||||
# request.set_AuthInfoTimeout(3000)
|
||||
# response = json.loads(clt.do_action_with_exception(request))
|
||||
# return response
|
||||
#
|
||||
# try:
|
||||
# clt = init_vod_client('LTAI5tSJ62TLMUb4SZuf285A', 'MWYynm30filZ7x0HqSHlU3pdLVNeI7')
|
||||
# playAuth = get_video_playauth(clt, uploadInfo["VideoId"])
|
||||
# print(json.dumps(playAuth, ensure_ascii=False, indent=4))
|
||||
#
|
||||
# except Exception as e:
|
||||
# print(e)
|
||||
# print(traceback.format_exc())
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# accessKeyId='LTAI5tSJ62TLMUb4SZuf285A'
|
||||
# accessKeySecret='MWYynm30filZ7x0HqSHlU3pdLVNeI7'
|
||||
# filePath="/home/thsw/chenyukun/video/111111.mp4"
|
||||
# # 测试上传本地音视频
|
||||
# def testUploadLocalVideo(accessKeyId, accessKeySecret, filePath, storageLocation=None):
|
||||
# try:
|
||||
# # 可以指定上传脚本部署的ECS区域。如果ECS区域和视频点播存储区域相同,则自动使用内网上传,上传更快且更省公网流量。
|
||||
# # ecsRegionId ="cn-shanghai"
|
||||
# # uploader = AliyunVodUploader(accessKeyId, accessKeySecret, ecsRegionId)
|
||||
# # 不指定上传脚本部署的ECS区域。
|
||||
# uploader = AliyunVodUploader(accessKeyId, accessKeySecret)
|
||||
# uploadVideoRequest = UploadVideoRequest(filePath, 'aiOnLineVideo')
|
||||
# # 可以设置视频封面,如果是本地或网络图片可使用UploadImageRequest上传图片到视频点播,获取到ImageURL
|
||||
# #ImageURL示例:https://example.com/sample-****.jpg
|
||||
# #uploadVideoRequest.setCoverURL('<your Image URL>')
|
||||
# # 标签
|
||||
# # uploadVideoRequest.setTags('taa')
|
||||
# if storageLocation:
|
||||
# uploadVideoRequest.setStorageLocation(storageLocation)
|
||||
# videoId = uploader.uploadLocalVideo(uploadVideoRequest)
|
||||
# print("videoId: %s" % (videoId))
|
||||
#
|
||||
# except AliyunVodException as e:
|
||||
# print(e)
|
||||
# testUploadLocalVideo(accessKeyId, accessKeySecret, filePath)
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# This file is auto-generated, don't edit it. Thanks.
|
||||
import sys
|
||||
|
||||
from typing import List
|
||||
|
||||
from alibabacloud_vod20170321.client import Client as vod20170321Client
|
||||
from alibabacloud_tea_openapi import models as open_api_models
|
||||
from alibabacloud_darabonba_env.client import Client as EnvClient
|
||||
from alibabacloud_vod20170321 import models as vod_20170321_models
|
||||
from alibabacloud_tea_console.client import Client as ConsoleClient
|
||||
from alibabacloud_tea_util.client import Client as UtilClient
|
||||
from vodsdk.AliyunVodUtils import *
|
||||
from vodsdk.AliyunVodUploader import AliyunVodUploader
|
||||
from vodsdk.UploadVideoRequest import UploadVideoRequest
|
||||
|
||||
class Sample:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def initialization(
|
||||
region_id: str,
|
||||
) -> vod20170321Client:
|
||||
config = open_api_models.Config()
|
||||
# 您的AccessKey ID
|
||||
config.access_key_id = EnvClient.get_env('LTAI5tSJ62TLMUb4SZuf285A')
|
||||
# 您的AccessKey Secret
|
||||
config.access_key_secret = EnvClient.get_env('MWYynm30filZ7x0HqSHlU3pdLVNeI7')
|
||||
# 您的可用区ID
|
||||
config.region_id = region_id
|
||||
return vod20170321Client(config)
|
||||
|
||||
@staticmethod
|
||||
def get_play_info_sample(
|
||||
client: vod20170321Client,
|
||||
video_id: str,
|
||||
) -> vod_20170321_models.GetPlayInfoResponse:
|
||||
request = vod_20170321_models.GetPlayInfoRequest()
|
||||
# 视频ID。
|
||||
request.video_id = video_id
|
||||
response = client.get_play_info(request)
|
||||
return response
|
||||
|
||||
@staticmethod
|
||||
async def get_play_info_sample_async(
|
||||
client: vod20170321Client,
|
||||
video_id: str,
|
||||
) -> vod_20170321_models.GetPlayInfoResponse:
|
||||
request = vod_20170321_models.GetPlayInfoRequest()
|
||||
# 视频ID。
|
||||
request.video_id = video_id
|
||||
response = await client.get_play_info_async(request)
|
||||
return response
|
||||
|
||||
@staticmethod
|
||||
def main(
|
||||
args: List[str],
|
||||
) -> None:
|
||||
try:
|
||||
region_id = args[0]
|
||||
video_id = args[1]
|
||||
client = Sample.initialization(region_id)
|
||||
response_get_play_info = Sample.get_play_info_sample(client, video_id)
|
||||
ConsoleClient.log(UtilClient.to_jsonstring(UtilClient.to_map(response_get_play_info)))
|
||||
except Exception as error:
|
||||
ConsoleClient.log(error.message)
|
||||
|
||||
@staticmethod
|
||||
async def main_async(
|
||||
args: List[str],
|
||||
) -> None:
|
||||
try:
|
||||
region_id = args[0]
|
||||
video_id = args[1]
|
||||
client = Sample.initialization(region_id)
|
||||
response_get_play_info = await Sample.get_play_info_sample_async(client, video_id)
|
||||
ConsoleClient.log(UtilClient.to_jsonstring(UtilClient.to_map(response_get_play_info)))
|
||||
except Exception as error:
|
||||
ConsoleClient.log(error.message)
|
||||
|
||||
accessKeyId='LTAI5tSJ62TLMUb4SZuf285A'
|
||||
accessKeySecret='MWYynm30filZ7x0HqSHlU3pdLVNeI7'
|
||||
filePath="/home/thsw/chenyukun/video/111111.mp4"
|
||||
# 测试上传本地音视频
|
||||
def testUploadLocalVideo(accessKeyId, accessKeySecret, filePath, storageLocation=None):
|
||||
try:
|
||||
# 可以指定上传脚本部署的ECS区域。如果ECS区域和视频点播存储区域相同,则自动使用内网上传,上传更快且更省公网流量。
|
||||
# ecsRegionId ="cn-shanghai"
|
||||
# uploader = AliyunVodUploader(accessKeyId, accessKeySecret, ecsRegionId)
|
||||
# 不指定上传脚本部署的ECS区域。
|
||||
uploader = AliyunVodUploader(accessKeyId, accessKeySecret)
|
||||
uploadVideoRequest = UploadVideoRequest(filePath, 'aiOnLineVideo')
|
||||
# 可以设置视频封面,如果是本地或网络图片可使用UploadImageRequest上传图片到视频点播,获取到ImageURL
|
||||
#ImageURL示例:https://example.com/sample-****.jpg
|
||||
#uploadVideoRequest.setCoverURL('<your Image URL>')
|
||||
# 标签
|
||||
# uploadVideoRequest.setTags('taa')
|
||||
if storageLocation:
|
||||
uploadVideoRequest.setStorageLocation(storageLocation)
|
||||
videoId = uploader.uploadLocalVideo(uploadVideoRequest)
|
||||
print("videoId: %s" % (videoId))
|
||||
|
||||
except AliyunVodException as e:
|
||||
print(e)
|
||||
# testUploadLocalVideo(accessKeyId, accessKeySecret, filePath)
|
||||
from alibabacloud_tea_util import models as util_models
|
||||
import time
|
||||
def get_video_url(video_id):
|
||||
config = open_api_models.Config(access_key_id=accessKeyId, access_key_secret=accessKeySecret)
|
||||
config.endpoint = f'vod.aliyuncs.com'
|
||||
client = vod20170321Client(config)
|
||||
get_play_info_request = vod_20170321_models.GetPlayInfoRequest(video_id=video_id)
|
||||
runtime = util_models.RuntimeOptions()
|
||||
start = time.time()
|
||||
while True:
|
||||
try:
|
||||
# 复制代码运行请自行打印 API 的返回值
|
||||
vod_20170321_models.GetPlayInfoResponse = client.get_play_info_with_options(get_play_info_request, runtime)
|
||||
play_url = vod_20170321_models.GetPlayInfoResponse.body.play_info_list.play_info[0].play_url
|
||||
return play_url
|
||||
except Exception as error:
|
||||
print("bbbbbbbbbbbbbb")
|
||||
print(error)
|
||||
time.sleep(5)
|
||||
end = time.time()
|
||||
result = int(end - start)
|
||||
if result > 1200:
|
||||
print("aaaaaaaa")
|
||||
raise error
|
||||
import json
|
||||
import traceback
|
||||
from aliyunsdkcore.client import AcsClient
|
||||
from aliyunsdkvod.request.v20170321 import CreateUploadVideoRequest
|
||||
from aliyunsdkvod.request.v20170321 import GetPlayInfoRequest
|
||||
from vodsdk.AliyunVodUtils import *
|
||||
from vodsdk.AliyunVodUploader import AliyunVodUploader
|
||||
from vodsdk.UploadVideoRequest import UploadVideoRequest
|
||||
# 获取播放地址
|
||||
def init_vod_client(accessKeyId, accessKeySecret):
|
||||
regionId = 'cn-shanghai' # 点播服务接入地域
|
||||
connectTimeout = 3 # 连接超时,单位为秒
|
||||
return AcsClient(accessKeyId, accessKeySecret, regionId, auto_retry=True, max_retry_time=3, timeout=connectTimeout)
|
||||
def get_play_info(clt, videoId):
|
||||
request = GetPlayInfoRequest.GetPlayInfoRequest()
|
||||
request.set_accept_format('JSON')
|
||||
request.set_VideoId(videoId)
|
||||
request.set_AuthTimeout(3600*5)
|
||||
response = json.loads(clt.do_action_with_exception(request))
|
||||
return response
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# testUploadLocalVideo(accessKeyId, accessKeySecret, "/home/thsw/chenyukun/video/百水河7.mp4")
|
||||
# print(Sample.get_play_info_sample(Sample.initialization('cn-shanghai'), 'dfaf3d140f714d9889562bff10a6f69a'))
|
||||
# print(get_video_url('3bb41d547bad44a7a9202017b8025838'))
|
||||
try:
|
||||
clt = init_vod_client('LTAI5tSJ62TLMUb4SZuf285A', 'MWYynm30filZ7x0HqSHlU3pdLVNeI7')
|
||||
playInfo = get_play_info(clt, "43e00a1a9d334c30b743d1cd6138207a")
|
||||
print(playInfo["PlayInfoList"]["PlayInfo"][0]["PlayURL"])
|
||||
print(json.dumps(playInfo, ensure_ascii=False, indent=4))
|
||||
|
||||
except Exception as e:
|
||||
print("HTTP Status: 403" not in str(e))
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import time
|
||||
|
||||
import json
|
||||
|
||||
from aliyunsdkcore.client import AcsClient
|
||||
from aliyunsdkvod.request.v20170321 import GetPlayInfoRequest
|
||||
from vodsdk.AliyunVodUtils import *
|
||||
from vodsdk.AliyunVodUploader import AliyunVodUploader
|
||||
from vodsdk.UploadVideoRequest import UploadVideoRequest
|
||||
|
||||
'''
|
||||
视频上传使用vod
|
||||
1. 阿里云VOD文档地址:https://help.aliyun.com/product/29932.html?spm=5176.8413026.J_3895079540.5.1b4a1029mXvncc
|
||||
2. 阿里云对象存储OSS SDK示例地址:https://help.aliyun.com/document_detail/64148.html?spm=a2c4g.64148.0.0.5ae54150jUecEU
|
||||
4. 安装SDK:
|
||||
python -m pip install aliyun-python-sdk-core -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
python -m pip install aliyun-python-sdk-live -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
python -m pip install aliyun-python-sdk-core-v3 -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
python -m pip install aliyun-python-sdk-vod -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
python -m pip install alibabacloud_vod20170321 -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
python -m pip install oss2 -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
python -m pip install voduploadsdk -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
5. 视频域名地址:https://vod.play.t-aaron.com/
|
||||
'''
|
||||
|
||||
|
||||
class AliyunVodSdk:
|
||||
|
||||
def __init__(self):
|
||||
self.__client = None
|
||||
self.__access_key = 'LTAI5tMiefafZ6br4zmrQWv9'
|
||||
self.__access_secret = 'JgzQjSCkwZ7lefZO6egOArw38YH1Tk'
|
||||
self.__regionId = "cn-shanghai"
|
||||
self.__cateId = '1000468340'
|
||||
|
||||
def init_vod_client(self):
|
||||
return AcsClient(self.__access_key, self.__access_secret, self.__regionId, auto_retry=True, max_retry_time=3,
|
||||
timeout=5)
|
||||
|
||||
'''
|
||||
根据videoId获取视频地址
|
||||
'''
|
||||
|
||||
def get_play_info(self, videoId):
|
||||
logger.info("开始获取视频地址,videoId:{}", videoId)
|
||||
start = time.time()
|
||||
while True:
|
||||
try:
|
||||
clt = self.init_vod_client()
|
||||
request = GetPlayInfoRequest.GetPlayInfoRequest()
|
||||
request.set_accept_format('JSON')
|
||||
request.set_VideoId(videoId)
|
||||
request.set_AuthTimeout(3600 * 5)
|
||||
response = json.loads(clt.do_action_with_exception(request))
|
||||
play_url = response["PlayInfoList"]["PlayInfo"][0]["PlayURL"]
|
||||
logger.info("获取视频地址成功,视频地址: {}", play_url)
|
||||
return play_url
|
||||
except Exception as e:
|
||||
logger.error("获取视频地址失败,5秒后重试, requestId: {}")
|
||||
time.sleep(5)
|
||||
current_time = time.time()
|
||||
if "HTTP Status: 403" not in str(e):
|
||||
logger.exception("获取视频地址失败: {}", e)
|
||||
raise e
|
||||
if "HTTP Status: 403" in str(e) and ("UploadFail" in str(e) or "TranscodeFail" in str(e)):
|
||||
self.logger.exception("获取视频地址失败: {}", e)
|
||||
raise e
|
||||
diff_time = current_time - start
|
||||
if diff_time > 60 * 60 * 2:
|
||||
logger.exception("获取视频地址失败超时异常: {},超时时间:{}", e, diff_time)
|
||||
raise e
|
||||
|
||||
def upload_local_video(self, filePath, file_title, storageLocation=None):
|
||||
logger.info("开始执行vod视频上传, filePath: {}", filePath)
|
||||
uploader = AliyunVodUploader(self.__access_key, self.__access_secret)
|
||||
uploadVideoRequest = UploadVideoRequest(filePath, file_title)
|
||||
uploadVideoRequest.setCateId(self.__cateId)
|
||||
if storageLocation:
|
||||
uploadVideoRequest.setStorageLocation(storageLocation)
|
||||
MAX_RETRIES = 3
|
||||
retry_count = 0
|
||||
while True:
|
||||
try:
|
||||
result = uploader.uploadLocalVideo(uploadVideoRequest)
|
||||
logger.info("vod视频上传成功, videoId:{}", result.get("VideoId"))
|
||||
return result.get("VideoId")
|
||||
except AliyunVodException as e:
|
||||
retry_count += 1
|
||||
time.sleep(3)
|
||||
logger.error("vod视频上传失败,重试次数:{}", retry_count)
|
||||
if retry_count >= MAX_RETRIES:
|
||||
self.logger.exception("vod视频上传重试失败: {}", e)
|
||||
raise e
|
||||
|
||||
|
||||
YY_MM_DD_HH_MM_SS = "%Y-%m-%d %H:%M:%S"
|
||||
YMDHMSF = "%Y%m%d%H%M%S%f"
|
||||
|
||||
|
||||
def generate_timestamp():
|
||||
"""根据当前时间获取时间戳,返回整数"""
|
||||
return int(time.time())
|
||||
|
||||
|
||||
def now_date_to_str(fmt=None):
|
||||
if fmt is None:
|
||||
fmt = YY_MM_DD_HH_MM_SS
|
||||
return datetime.datetime.now().strftime(fmt)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 本地原视频命名
|
||||
random_time = now_date_to_str(YMDHMSF)
|
||||
# # 如果是离线视频,将 _on_or_ 替换为 _off_or_
|
||||
# orFilePath = "%s%s%s%s%s" % ('本地路径', random_time, "_on_or_", 'requestId', ".mp4")
|
||||
# # 本地AI识别后的视频命名
|
||||
# # 如果是离线视频,将 _on_ai_ 替换为 _off_ai_
|
||||
# aiFilePath = "%s%s%s%s%s" % ('本地路径', random_time, "_on_ai_", 'requestId', ".mp4")
|
||||
# filePath = "%s%s%s%s%s" % ('D:\\shipin\\', random_time, "_on_ai_", '11111111', ".mp4")
|
||||
filePath = 'D:\\shipin\\777.mp4'
|
||||
codClinet = AliyunVodSdk()
|
||||
result = codClinet.upload_local_video(filePath, 'aiOnLineVideo1')
|
||||
print(result)
|
||||
url = codClinet.get_play_info(result)
|
||||
print(url)
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# This file is auto-generated, don't edit it. Thanks.
|
||||
import sys
|
||||
|
||||
from typing import List
|
||||
from Tea.core import TeaCore
|
||||
|
||||
from alibabacloud_vod20170321.client import Client as Vod20170321Client
|
||||
from alibabacloud_tea_openapi import models as open_api_models
|
||||
from alibabacloud_darabonba_env.client import Client as EnvClient
|
||||
from alibabacloud_vod20170321 import models as vod_20170321_models
|
||||
from alibabacloud_tea_console.client import Client as ConsoleClient
|
||||
from alibabacloud_tea_util.client import Client as UtilClient
|
||||
|
||||
|
||||
class Sample:
|
||||
"""
|
||||
write your Darabonba code here...
|
||||
"""
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def init_vod_client(
|
||||
access_key_id: str,
|
||||
access_key_secret: str,
|
||||
region_id: str,
|
||||
) -> Vod20170321Client:
|
||||
"""
|
||||
使用AK&SK初始化账号Client
|
||||
"""
|
||||
config = open_api_models.Config()
|
||||
config.access_key_id = access_key_id
|
||||
config.access_key_secret = access_key_secret
|
||||
config.region_id = region_id
|
||||
return Vod20170321Client(config)
|
||||
|
||||
@staticmethod
|
||||
def main(
|
||||
args: List[str],
|
||||
) -> None:
|
||||
client = Sample.init_vod_client('LTAI5tSJ62TLMUb4SZuf285A', 'MWYynm30filZ7x0HqSHlU3pdLVNeI7', args[0])
|
||||
# 1.获取视频上传地址和凭证,并生成视频信息
|
||||
create_upload_video_request = vod_20170321_models.CreateUploadVideoRequest(
|
||||
title=args[1],
|
||||
file_name=args[2]
|
||||
)
|
||||
create_upload_video_response = client.create_upload_video(create_upload_video_request)
|
||||
ConsoleClient.log(UtilClient.to_jsonstring(TeaCore.to_map(create_upload_video_response)))
|
||||
# 媒体id
|
||||
upload_video_id = create_upload_video_response.body.video_id
|
||||
ConsoleClient.log(upload_video_id)
|
||||
# 如果视频文件过大,上传超时后可以刷新视频凭证,然后继续上传
|
||||
refresh_upload_video_request = vod_20170321_models.RefreshUploadVideoRequest(
|
||||
video_id=upload_video_id
|
||||
)
|
||||
refresh_upload_video_reponse = client.refresh_upload_video(refresh_upload_video_request)
|
||||
ConsoleClient.log(UtilClient.to_jsonstring(TeaCore.to_map(refresh_upload_video_reponse)))
|
||||
# # 2.oss视频文件上传,需要用户实现
|
||||
# # 3.上传过程中,获取媒体上传详情
|
||||
# get_upload_details_request = vod_20170321_models.GetUploadDetailsRequest(
|
||||
# media_ids=upload_video_id
|
||||
# )
|
||||
# get_upload_details_reponse = client.get_upload_details(get_upload_details_request)
|
||||
# ConsoleClient.log(UtilClient.to_jsonstring(TeaCore.to_map(get_upload_details_reponse)))
|
||||
# # 4.媒体上传完成之后,可以获取媒体播放信息进行播放
|
||||
# # 4.1 通过播放凭证播放
|
||||
# get_play_info_request = vod_20170321_models.GetPlayInfoRequest(
|
||||
# video_id=upload_video_id
|
||||
# )
|
||||
# get_play_info_reponse = client.get_play_info(get_play_info_request)
|
||||
# ConsoleClient.log(UtilClient.to_jsonstring(TeaCore.to_map(get_play_info_reponse)))
|
||||
# # 4.2 通过播放地址播放
|
||||
# get_video_play_auth_request = vod_20170321_models.GetVideoPlayAuthRequest(
|
||||
# video_id=upload_video_id
|
||||
# )
|
||||
# get_video_play_auth_reponse = client.get_video_play_auth(get_video_play_auth_request)
|
||||
# ConsoleClient.log(UtilClient.to_jsonstring(TeaCore.to_map(get_video_play_auth_reponse)))
|
||||
|
||||
@staticmethod
|
||||
async def main_async(
|
||||
args: List[str],
|
||||
) -> None:
|
||||
client = Sample.init_vod_client(EnvClient.get_env('ACCESS_KEY_ID'), EnvClient.get_env('ACCESS_KEY_SECRET'), args[0])
|
||||
# 1.获取视频上传地址和凭证,并生成视频信息
|
||||
create_upload_video_request = vod_20170321_models.CreateUploadVideoRequest(
|
||||
title=args[1],
|
||||
file_name=args[2]
|
||||
)
|
||||
create_upload_video_response = await client.create_upload_video_async(create_upload_video_request)
|
||||
ConsoleClient.log(UtilClient.to_jsonstring(TeaCore.to_map(create_upload_video_response)))
|
||||
# 媒体id
|
||||
upload_video_id = create_upload_video_response.body.video_id
|
||||
ConsoleClient.log(upload_video_id)
|
||||
# 如果视频文件过大,上传超时后可以刷新视频凭证,然后继续上传
|
||||
refresh_upload_video_request = vod_20170321_models.RefreshUploadVideoRequest(
|
||||
video_id=upload_video_id
|
||||
)
|
||||
refresh_upload_video_reponse = await client.refresh_upload_video_async(refresh_upload_video_request)
|
||||
ConsoleClient.log(UtilClient.to_jsonstring(TeaCore.to_map(refresh_upload_video_reponse)))
|
||||
# 2.oss视频文件上传,需要用户实现
|
||||
# 3.上传过程中,获取媒体上传详情
|
||||
get_upload_details_request = vod_20170321_models.GetUploadDetailsRequest(
|
||||
media_ids=upload_video_id
|
||||
)
|
||||
get_upload_details_reponse = await client.get_upload_details_async(get_upload_details_request)
|
||||
ConsoleClient.log(UtilClient.to_jsonstring(TeaCore.to_map(get_upload_details_reponse)))
|
||||
# 4.媒体上传完成之后,可以获取媒体播放信息进行播放
|
||||
# 4.1 通过播放凭证播放
|
||||
get_play_info_request = vod_20170321_models.GetPlayInfoRequest(
|
||||
video_id=upload_video_id
|
||||
)
|
||||
get_play_info_reponse = await client.get_play_info_async(get_play_info_request)
|
||||
ConsoleClient.log(UtilClient.to_jsonstring(TeaCore.to_map(get_play_info_reponse)))
|
||||
# 4.2 通过播放地址播放
|
||||
get_video_play_auth_request = vod_20170321_models.GetVideoPlayAuthRequest(
|
||||
video_id=upload_video_id
|
||||
)
|
||||
get_video_play_auth_reponse = await client.get_video_play_auth_async(get_video_play_auth_request)
|
||||
ConsoleClient.log(UtilClient.to_jsonstring(TeaCore.to_map(get_video_play_auth_reponse)))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
Sample.main(['cn-shanghai', "/home/thsw/chenyukun/video/111111.mp4", "/home/thsw/chenyukun/video/111111.mp4"])
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
import json
|
||||
import traceback
|
||||
from aliyunsdkcore.client import AcsClient
|
||||
from aliyunsdkvod.request.v20170321 import CreateUploadVideoRequest
|
||||
from aliyunsdkvod.request.v20170321 import GetPlayInfoRequest
|
||||
from vodsdk.AliyunVodUtils import *
|
||||
from vodsdk.AliyunVodUploader import AliyunVodUploader
|
||||
from vodsdk.UploadVideoRequest import UploadVideoRequest
|
||||
# 获取播放地址
|
||||
def init_vod_client(accessKeyId, accessKeySecret):
|
||||
regionId = 'cn-shanghai' # 点播服务接入地域
|
||||
connectTimeout = 3 # 连接超时,单位为秒
|
||||
return AcsClient(accessKeyId, accessKeySecret, regionId, auto_retry=True, max_retry_time=3, timeout=connectTimeout)
|
||||
def get_play_info(clt, videoId):
|
||||
request = GetPlayInfoRequest.GetPlayInfoRequest()
|
||||
request.set_accept_format('JSON')
|
||||
request.set_VideoId(videoId)
|
||||
request.set_AuthTimeout(3600*5)
|
||||
response = json.loads(clt.do_action_with_exception(request))
|
||||
return response
|
||||
try:
|
||||
clt = init_vod_client('LTAI5tSJ62TLMUb4SZuf285A', 'MWYynm30filZ7x0HqSHlU3pdLVNeI7')
|
||||
playInfo = get_play_info(clt, "f2bd66de44f742a5bb7d603c295dc47f")
|
||||
print(json.dumps(playInfo, ensure_ascii=False, indent=4))
|
||||
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
print("403" in str(e))
|
||||
# print(traceback.format_exc())
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
|
||||
|
||||
|
||||
"""
|
||||
1、ChainMap是什么
|
||||
ChainMap最基本的使用,可以用来合并两个或者更多个字典,当查询的时候,从前往后依次查询。
|
||||
ChainMap:将多个字典视为一个,解锁Python超能力。
|
||||
ChainMap是由Python标准库提供的一种数据结构,允许你将多个字典视为一个。换句话说:ChainMap是一个基于多dict的可更新的视图,它的行为就像一个普通的dict。
|
||||
ChainMap类用于快速链接多个映射,以便将它们视为一个单元。它通常比创建新字典和多次调用update()快得多。
|
||||
你以前可能从来没有听说过ChainMap,你可能会认为ChainMap的使用情况是非常特定的。坦率地说,你是对的。
|
||||
我知道的用例包括:
|
||||
通过多个字典搜索
|
||||
提供链缺省值
|
||||
经常计算字典子集的性能关键的应用程序
|
||||
2、特性
|
||||
1)找到一个就不找了:这个列表是按照第一次搜索到最后一次搜索的顺序组织的,搜索查询底层映射,直到一个键被找到。
|
||||
2)更新原始映射:不同的是,写,更新和删除只操作第一个映射。
|
||||
3)支持所有常用字典方法。
|
||||
简而言之ChainMap:将多个字典视为一个,解锁Python超能力。
|
||||
Python标准库中的集合模块包含许多为性能而设计的实用的数据结构。著名的包括命名元组或计数器。
|
||||
今天,通过实例,我们来看看鲜为人知的ChainMap。通过浏览具体的示例,我希望给你一个提示,关于在更高级的Python工作中使用ChainMap将如何从中受益。
|
||||
"""
|
||||
|
||||
from collections import ChainMap
|
||||
baseline = {'music': 'bach', 'art': 'rembrandt'}
|
||||
adjustments = {'art': 'van gogh', 'opera': 'carmen'}
|
||||
test = ChainMap(adjustments, baseline)
|
||||
print(test)
|
||||
test1 = list(ChainMap(adjustments, baseline))
|
||||
print(test1)
|
||||
# 存在重复元素时,也不会去重
|
||||
dcic1 = {'label1': '11', 'label2': '22'}
|
||||
dcic2 = {'label2': '22', 'label3': '33'}
|
||||
dcic3 = {'label4': '44', 'label5': '55'}
|
||||
last = ChainMap(dcic1, dcic2, dcic3)
|
||||
print(last)
|
||||
print(last['label2'])
|
||||
|
||||
"""
|
||||
new_child()方法
|
||||
用法:new_child(m=None)
|
||||
返回一个新的ChainMap类,包含了一个新映射(map),后面跟随当前实例的全部映射map。
|
||||
如果m被指定,它就成为不同新的实例,就是在所有映射前加上 m,如果没有指定,就加上一个空字典,
|
||||
这样的话一个 d.new_child() 调用等价于ChainMap({}, *d.maps) 。这个方法用于创建子上下文,不改变任何父映射的值。
|
||||
"""
|
||||
aa = last.new_child(m={'key_new': 888})
|
||||
print(aa)
|
||||
|
||||
"""
|
||||
parents属性
|
||||
属性返回一个新的ChainMap包含所有的当前实例的映射,除了第一个。
|
||||
这样可以在搜索的时候跳过第一个映射。使用的场景类似在 nested scopes 嵌套作用域中使用nonlocal关键词。
|
||||
用例也可以类比内建函数super() 。一个d.parents 的引用等价于ChainMap(*d.maps[1:])。
|
||||
"""
|
||||
print(aa.parents)
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
import collections
|
||||
import re
|
||||
from collections import Counter
|
||||
|
||||
print(collections.__all__)
|
||||
"""
|
||||
['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList',
|
||||
'UserString', 'Counter', 'OrderedDict', 'ChainMap']
|
||||
这个模块实现了特定目标的容器,以提供Python标准内建容器dict , list , set , 和tuple 的替代选择。
|
||||
deque: 类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop)
|
||||
defaultdict: 字典的子类,提供了一个工厂函数,为字典查询提供一个默认值
|
||||
namedtuple(): 创建命名元组子类的工厂函数,生成可以使用名字来访问元素内容的tuple子类
|
||||
UserDict: 封装了字典对象,简化了字典子类化
|
||||
UserList: 封装了列表对象,简化了列表子类化
|
||||
UserString: 封装了字符串对象,简化了字符串子类化(中文版翻译有误)
|
||||
Counter: 字典的子类,提供了可哈希对象的计数功能
|
||||
OrderedDict: 字典的子类,保存了他们被添加的顺序,有序字典
|
||||
ChainMap: 类似字典(dict)的容器类,将多个映射集合到一个视图里面
|
||||
"""
|
||||
|
||||
text = 'remove an existing key one level down remove an existing key one level down'
|
||||
# \w 匹配非特殊字符,即a-z、A-Z、0-9、_、汉字
|
||||
words = re.findall(r'\w+', text)
|
||||
print(Counter(words).most_common(10))
|
||||
|
||||
#计算列表中单词的个数
|
||||
cnt = Counter()
|
||||
for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
|
||||
cnt[word] += 1
|
||||
print(cnt)
|
||||
|
||||
# #上述这样计算有点嘛,下面的方法更简单,直接计算就行
|
||||
L = ['red', 'blue', 'red', 'green', 'blue', 'blue']
|
||||
print(Counter(L))
|
||||
|
||||
# 元素从一个iterable 被计数或从其他的mapping (or counter)初始化:
|
||||
# 字符串计数
|
||||
print(Counter('gallahad'))
|
||||
|
||||
# 字典计数
|
||||
print(Counter({'red': 4, 'blue': 2}))
|
||||
|
||||
# 是个啥玩意计数
|
||||
print(Counter(cats=4, dogs=8))
|
||||
|
||||
"""
|
||||
1、elements()
|
||||
描述:返回一个迭代器,其中每个元素将重复出现计数值所指定次。 元素会按首次出现的顺序返回。 如果一个元素的计数值小于1,elements() 将会忽略它。
|
||||
语法:elements( )
|
||||
参数:无
|
||||
"""
|
||||
c = Counter(a=4, b=2, c=0, d=-2)
|
||||
print(c)
|
||||
print(list(c.elements()))
|
||||
print(sorted(c.elements()))
|
||||
c = Counter(a=4, b=2, c=0, d=5)
|
||||
print(list(c.elements()))
|
||||
|
||||
"""
|
||||
2、most_common()
|
||||
返回一个列表,其中包含n个最常见的元素及出现次数,按常见程度由高到低排序。
|
||||
如果n被省略或为None,most_common() 将返回计数器中的所有元素,
|
||||
计数值相等的元素按首次出现的顺序排序,经常用来计算top词频的词语。
|
||||
"""
|
||||
print(Counter('abracadabra').most_common(3))
|
||||
print(Counter('abracadabra').most_common(5))
|
||||
|
||||
"""
|
||||
3、subtract()
|
||||
从迭代对象或映射对象减去元素。像dict.update() 但是是减去,而不是替换。输入和输出都可以是0或者负数。
|
||||
"""
|
||||
c = Counter(a=4, b=2, c=0, d=-2)
|
||||
d = Counter(a=1, b=2, c=3, d=4)
|
||||
c.subtract(d)
|
||||
print(c)
|
||||
|
||||
#减去一个abcd
|
||||
str0 = Counter('aabbccdde')
|
||||
str0.subtract('abcd')
|
||||
print(str0)
|
||||
|
||||
"""
|
||||
4、字典方法
|
||||
通常字典方法都可用于Counter对象,除了有两个方法工作方式与字典并不相同。
|
||||
fromkeys(iterable)
|
||||
这个类方法没有在Counter中实现。
|
||||
update([iterable-or-mapping])
|
||||
从迭代对象计数元素或者从另一个映射对象 (或计数器) 添加。 像 dict.update() 但是是加上,而不是替换。
|
||||
另外,迭代对象应该是序列元素,而不是一个 (key, value) 对。
|
||||
"""
|
||||
c = Counter(a=4, b=2, c=0, d=-2)
|
||||
print(sum(c.values()))
|
||||
print(list(c))
|
||||
print(set(c))
|
||||
print(dict(c))
|
||||
print(c.items())
|
||||
print(+c) # 删除零计数和负计数
|
||||
c.clear()
|
||||
print(c)
|
||||
"""
|
||||
5、数学操作
|
||||
这个功能非常强大,提供了几个数学操作,可以结合 Counter 对象,以生产 multisets (计数器中大于0的元素)。
|
||||
加和减,结合计数器,通过加上或者减去元素的相应计数。交集和并集返回相应计数的最小或最大值。
|
||||
每种操作都可以接受带符号的计数,但是输出会忽略掉结果为零或者小于零的计数。
|
||||
"""
|
||||
c = Counter(a=3, b=1)
|
||||
d = Counter(a=1, b=2)
|
||||
print(c+d)
|
||||
print(c - d)
|
||||
print(c & d)
|
||||
print(c | d)
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
from collections import OrderedDict
|
||||
|
||||
|
||||
"""
|
||||
1、popitem
|
||||
语法:popitem(last=True)
|
||||
功能:有序字典的 popitem() 方法移除并返回一个 (key, value) 键值对。
|
||||
如果 last 值为真,则按 LIFO 后进先出的顺序返回键值对,否则就按 FIFO 先进先出的顺序返回键值对。
|
||||
"""
|
||||
d = OrderedDict.fromkeys('abcde')
|
||||
print(d)
|
||||
print(d.popitem())
|
||||
# #last=False时,弹出第一个
|
||||
print(d.popitem(last=False))
|
||||
print(d.popitem(last=True))
|
||||
|
||||
"""
|
||||
2、move_to_end
|
||||
"""
|
||||
d = OrderedDict.fromkeys('abcde')
|
||||
d.move_to_end('b')
|
||||
print(d)
|
||||
d.move_to_end('b', last=False)
|
||||
print(d)
|
||||
|
||||
"""
|
||||
3、reversed()
|
||||
相对于通常的映射方法,有序字典还另外提供了逆序迭代的支持,通过reversed()。
|
||||
"""
|
||||
d = OrderedDict.fromkeys('acbde')
|
||||
print(d)
|
||||
print(list(reversed(d)))
|
||||
|
||||
c = OrderedDict({'a': 1, 'c': 2, 'b': 3})
|
||||
print(c)
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# import collections
|
||||
#
|
||||
# print(collections.__all__)
|
||||
# print(dir(collections))
|
||||
#
|
||||
# d = {}
|
||||
# d.setdefault(2, []).append(23)
|
||||
# d.setdefault(2, []).append(11)
|
||||
# print(d)
|
||||
# d.setdefault(2, []).append(23)
|
||||
#
|
||||
# # 定义一个curry风格函数
|
||||
# x = lambda y: [
|
||||
# print(y),
|
||||
# print("..."),
|
||||
# x
|
||||
# ][-1]
|
||||
# print(x(1)(2))
|
||||
#
|
||||
# import heapq
|
||||
# print(heapq.nlargest(1, [
|
||||
# {'S': 5, 'H': 3},
|
||||
# {'S': 7, 'H': 1},
|
||||
# {'S': 0, 'H': 2}
|
||||
# ], key=lambda x: x['S']))
|
||||
#
|
||||
# s = [1, [2, [3, [4, [5, 6], 7], 8], (9, 0)]]
|
||||
# f = lambda x: [y for _x in x for y in f(_x)] if isinstance(x, (list, tuple)) else [x]
|
||||
#
|
||||
# print(f(s)) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
|
||||
|
||||
"""
|
||||
默认字典-defaultdict
|
||||
在Python字典中收集数据通常是很有用的。
|
||||
在字典中获取一个 key 有两种方法, 第一种 get , 第二种 通过 [] 获取.
|
||||
使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict。
|
||||
当我使用普通的字典时,用法一般是dict={},添加元素的只需要dict[element] =value即,调用的时候也是如此,
|
||||
dict[element] = xxx,但前提是element字典里,如果不在字典里就会报错
|
||||
这时defaultdict就能排上用场了,defaultdict的作用是在于,当字典里的key不存在但被查找时,
|
||||
返回的不是keyError而是一个默认值,这个默认值是什么呢,下面会说
|
||||
|
||||
1、基础介绍
|
||||
defaultdict([default_factory[, ...]])
|
||||
返回一个新的类似字典的对象。 defaultdict是内置dict类的子类。它重载了一个方法并添加了一个可写的实例变量。
|
||||
其余的功能与dict类相同,此处不再重复说明。
|
||||
本对象包含一个名为default_factory的属性,构造时,第一个参数用于为该属性提供初始值,默认为 None。
|
||||
所有其他参数(包括关键字参数)都相当于传递给 dict 的构造函数。
|
||||
defaultdict 对象除了支持标准 dict 的操作,还支持以下方法作为扩展:
|
||||
__missing__(key)
|
||||
如果 default_factory 属性为 None,则调用本方法会抛出 KeyError 异常,附带参数 key。
|
||||
如果 default_factory 不为 None,则它会被(不带参数地)调用来为 key 提供一个默认值,
|
||||
这个值和 key 作为一对键值对被插入到字典中,并作为本方法的返回值返回。
|
||||
如果调用 default_factory 时抛出了异常,这个异常会原封不动地向外层传递。
|
||||
在无法找到所需键值时,本方法会被 dict 中的 __getitem__() 方法调用。
|
||||
无论本方法返回了值还是抛出了异常,都会被 __getitem__() 传递。
|
||||
注意,__missing__() 不会 被 __getitem__() 以外的其他方法调用。
|
||||
意味着 get() 会像正常的 dict 那样返回 None,而不是使用 default_factory。
|
||||
"""
|
||||
from collections import defaultdict
|
||||
|
||||
"""
|
||||
2、示例介绍
|
||||
使用 list 作为 default_factory,很轻松地将(键-值对组成的)序列转换为(键-列表组成的)字典
|
||||
"""
|
||||
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
|
||||
d = defaultdict(list)
|
||||
for k, v in s:
|
||||
d[k].append(v)
|
||||
print(sorted(d.items()))
|
||||
|
||||
"""
|
||||
当每个键第一次遇见时,它还没有在字典里面,所以自动创建该条目,即调用default_factory方法,
|
||||
返回一个空的 list。 list.append() 操作添加值到这个新的列表里。当再次存取该键时,就正常操作,list.append()
|
||||
添加另一个值到列表中。这个计数比它的等价方法dict.setdefault()要快速和简单:
|
||||
"""
|
||||
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
|
||||
d = {}
|
||||
for k, v in s:
|
||||
d.setdefault(k, []).append(v)
|
||||
print(sorted(d.items()))
|
||||
# 设置 default_factory为int,使defaultdict用于计数(类似其他语言中的 bag或multiset):
|
||||
s = 'mississippi'
|
||||
d = defaultdict(int)
|
||||
for k in s:
|
||||
d[k] += 1
|
||||
print(sorted(d.items()))
|
||||
|
||||
# 设置 default_factory 为 set 使 defaultdict 用于构建 set 集合:
|
||||
s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
|
||||
d = defaultdict(set)
|
||||
for k, v in s:
|
||||
d[k].add(v)
|
||||
print(sorted(d.items()))
|
||||
print(d['aaa'])
|
||||
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
|
||||
"""
|
||||
deque
|
||||
双端队列,可以快速的从另外一侧追加和推出对象,deque是一个双向链表,
|
||||
针对list连续的数据结构插入和删除进行优化。它提供了两端都可以操作的序列,
|
||||
这表示在序列的前后你都可以执行添加或删除操作。双向队列(deque)对象支持以下方法:
|
||||
"""
|
||||
from collections import deque
|
||||
|
||||
"""
|
||||
1、append()
|
||||
添加 x 到右端。
|
||||
"""
|
||||
d = deque('ghi')
|
||||
d.append('j')
|
||||
print(d)
|
||||
|
||||
"""
|
||||
2、appendleft()
|
||||
添加 x 到左端。
|
||||
"""
|
||||
d.appendleft('f')
|
||||
print(d)
|
||||
|
||||
"""
|
||||
3、clear()
|
||||
移除所有元素,使其长度为0.
|
||||
"""
|
||||
d = deque('ghi')
|
||||
d.clear()
|
||||
print(d)
|
||||
|
||||
"""
|
||||
4、copy()
|
||||
创建一份浅拷贝。
|
||||
"""
|
||||
d = deque('xiaoweuge')
|
||||
y = d.copy()
|
||||
print(y)
|
||||
|
||||
"""
|
||||
5、count()
|
||||
计算 deque 中元素等于 x 的个数。
|
||||
"""
|
||||
d = deque('xiaoweuge-shuai')
|
||||
print(d.count('a'))
|
||||
|
||||
"""
|
||||
6、extend()
|
||||
扩展deque的右侧,通过添加iterable参数中的元素。
|
||||
"""
|
||||
a = deque('abc')
|
||||
b = deque('cd')
|
||||
a.extend(b)
|
||||
print(a)
|
||||
|
||||
#与append 的区别
|
||||
a = deque('abc')
|
||||
b = deque('cd')
|
||||
a.append(b)
|
||||
print(a)
|
||||
|
||||
"""
|
||||
7、extendleft()
|
||||
扩展deque的左侧,通过添加iterable参数中的元素。注意,左添加时,在结果中iterable参数中的顺序将被反过来添加。
|
||||
"""
|
||||
a = deque('abc')
|
||||
b = deque('cd')
|
||||
a.extendleft(b)
|
||||
print(a)
|
||||
|
||||
"""
|
||||
8、index()
|
||||
返回 x 在 deque 中的位置(在索引 start 之后,索引 stop 之前)。 返回第一个匹配项,如果未找到则引发 ValueError。
|
||||
"""
|
||||
d = deque('xiaoweuge')
|
||||
print(d.index('w'))
|
||||
|
||||
"""
|
||||
9、insert()
|
||||
在位置 i 插入 x 。
|
||||
如果插入会导致一个限长 deque 超出长度 maxlen 的话,就引发一个 IndexError。
|
||||
"""
|
||||
a = deque('abc')
|
||||
a.insert(1, 'X')
|
||||
print(a)
|
||||
|
||||
"""
|
||||
10、pop()
|
||||
移去并且返回一个元素,deque 最右侧的那一个。 如果没有元素的话,就引发一个 IndexError。
|
||||
"""
|
||||
d = deque('abc')
|
||||
print(d.pop())
|
||||
|
||||
"""
|
||||
11、popleft()
|
||||
移去并且返回一个元素,deque 最左侧的那一个。 如果没有元素的话,就引发 IndexError。
|
||||
"""
|
||||
d = deque('abc')
|
||||
print(d.popleft())
|
||||
|
||||
"""
|
||||
12、remove(value)
|
||||
移除找到的第一个 value。 如果没有的话就引发 ValueError。
|
||||
"""
|
||||
a = deque('abca')
|
||||
a.remove('a')
|
||||
print(a)
|
||||
|
||||
"""
|
||||
13、reverse()
|
||||
将deque逆序排列。返回 None 。
|
||||
"""
|
||||
#逆序排列
|
||||
d = deque('ghi') # 创建一个deque
|
||||
print(list(reversed(d)))
|
||||
|
||||
"""
|
||||
14、rotate(n=1)
|
||||
向右循环移动 n 步。 如果 n 是负数,就向左循环。
|
||||
如果deque不是空的,向右循环移动一步就等价于 d.appendleft(d.pop()) , 向左循环一步就等价于 d.append(d.popleft()) 。
|
||||
"""
|
||||
# 向右边挤一挤
|
||||
d = deque('ghijkl')
|
||||
d.rotate(1)
|
||||
print(d)
|
||||
|
||||
# 向左边挤一挤
|
||||
d.rotate(-1)
|
||||
print(d)
|
||||
|
||||
#看一个更明显的
|
||||
x = deque('12345')
|
||||
x.rotate()
|
||||
print(x)
|
||||
|
||||
d = deque(['12',' av', 'cd'])
|
||||
d.rotate(1)
|
||||
print(d)
|
||||
|
||||
"""
|
||||
15、maxlen
|
||||
Deque的最大尺寸,如果没有限定的话就是 None 。
|
||||
"""
|
||||
d=deque(maxlen=10)
|
||||
for i in range(20):
|
||||
d.append(i)
|
||||
print(d)
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
"""
|
||||
可命名元组-namedtuple
|
||||
生成可以使用名字来访问元素内容的tuple子类,命名元组赋予每个位置一个含义,提供可读性和自文档性。
|
||||
它们可以用于任何普通元组,并添加了通过名字获取值的能力,通过索引值也是可以的。
|
||||
1、参数介绍
|
||||
namedtuple(typename,field_names,*,verbose=False, rename=False, module=None)
|
||||
1)typename:该参数指定所创建的tuple子类的类名,相当于用户定义了一个新类。
|
||||
2)field_names:该参数是一个字符串序列,如 ['x','y']。此外,field_names 也可直接使用单个字符串代表所有字段名,多个字段名用空格、逗号隔开,如 'x y' 或 'x,y'。任何有效的 Python 标识符都可作为字段名(不能以下画线开头)。有效的标识符可由字母、数字、下画线组成,但不能以数字、下面线开头,也不能是关键字(如 return、global、pass、raise 等)。
|
||||
3)rename:如果将该参数设为 True,那么无效的字段名将会被自动替换为位置名。例如指定 ['abc','def','ghi','abc'],它将会被替换为 ['abc', '_1','ghi','_3'],这是因为 def 字段名是关键字,而 abc 字段名重复了。
|
||||
4)verbose:如果该参数被设为 True,那么当该子类被创建后,该类定义就被立即打印出来。
|
||||
5)module:如果设置了该参数,那么该类将位于该模块下,因此该自定义类的 __module__ 属性将被设为该参数值。
|
||||
"""
|
||||
# 定义命名元组类:Point
|
||||
Point = namedtuple('Point', ['x', 'y'])
|
||||
# 初始化Point对象,即可用位置参数,也可用命名参数
|
||||
p = Point(11, y=22)
|
||||
# 像普通元组一样用根据索引访问元素
|
||||
print(p[0] + p[1])
|
||||
|
||||
#执行元组解包,按元素的位置解包
|
||||
a, b = p
|
||||
print(a, b)
|
||||
|
||||
#根据字段名访问各元素
|
||||
print(p.x + p.y)
|
||||
print(p)
|
||||
|
||||
"""
|
||||
备注: 在Python中,带有前导下划线的方法通常被认为是“私有的”。
|
||||
但是,namedtuple提供的其他方法(如._asdict()、._make()、._replace()等)是公开的。
|
||||
除了继承元组的方法,命名元组还支持三个额外的方法和两个属性。为了防止字段名冲突,方法和属性以下划线开始。
|
||||
"""
|
||||
"""
|
||||
_make(iterable)
|
||||
类方法从存在的序列或迭代实例创建一个新实例。
|
||||
"""
|
||||
t = [14, 55]
|
||||
print(Point._make(t))
|
||||
|
||||
"""
|
||||
_asdict()
|
||||
返回一个新的dict ,它将字段名称映射到它们对应的值:
|
||||
"""
|
||||
p = Point(x=11, y=22)
|
||||
print(p._asdict())
|
||||
|
||||
"""
|
||||
_replace(**kwargs)
|
||||
返回一个新的命名元组实例,并将指定域替换为新的值
|
||||
"""
|
||||
p = Point(x=11, y=22)
|
||||
p._replace(x=33)
|
||||
print(p._replace(x=33))
|
||||
|
||||
"""
|
||||
两个属性
|
||||
_fields
|
||||
字符串元组列出了字段名。用于提醒和从现有元组创建一个新的命名元组类型。
|
||||
"""
|
||||
print(p._fields)
|
||||
|
||||
Color = namedtuple('Color', 'red green blue')
|
||||
Pixel = namedtuple('Pixel', Point._fields + Color._fields)
|
||||
print(Pixel._fields)
|
||||
|
||||
"""
|
||||
_field_defaults
|
||||
字典将字段名称映射到默认值。
|
||||
"""
|
||||
|
||||
Account = namedtuple('Account', ['type', 'balance'], defaults=[0])
|
||||
print(Account._field_defaults)
|
||||
print(Account('premium'))
|
||||
|
||||
"""
|
||||
getattr()
|
||||
要获取这个名字域的值,使用 getattr() 函数 :
|
||||
"""
|
||||
print(getattr(p, 'x'))
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
|
||||
import cv2
|
||||
import numpy as np
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
rainbows = [
|
||||
[0, 0, 255],
|
||||
[255, 0, 0],
|
||||
[211, 0, 148],
|
||||
[0, 127, 0],
|
||||
[0, 69, 255],
|
||||
[0, 255, 0],
|
||||
[255, 0, 255],
|
||||
[0, 0, 127],
|
||||
[127, 0, 255],
|
||||
[255, 129, 0],
|
||||
[139, 139, 0],
|
||||
[255, 255, 0],
|
||||
[127, 255, 0],
|
||||
[0, 127, 255],
|
||||
[0, 255, 127],
|
||||
[255, 127, 255],
|
||||
[8, 101, 139],
|
||||
[171, 130, 255],
|
||||
[139, 112, 74],
|
||||
[205, 205, 180]]
|
||||
# rainbows = [[0, 0, 255],
|
||||
# [211, 0, 148],
|
||||
# [0, 69, 255],
|
||||
# [133, 21, 199],
|
||||
# [0, 100, 0],
|
||||
# [34, 139, 34],
|
||||
# [8, 101, 139],
|
||||
# [11, 134, 184],
|
||||
# [92, 92, 205],
|
||||
# [147, 20, 255],
|
||||
# [255, 0, 255],
|
||||
# [96, 48, 176],
|
||||
# [205, 205, 105],
|
||||
# [139, 139, 102],
|
||||
# [255, 245, 0],
|
||||
# [170, 205, 102],
|
||||
# [155, 205, 155],
|
||||
# [0, 205, 0],
|
||||
# [79, 79, 47],
|
||||
# [105, 105, 105],
|
||||
# [112, 25, 25],
|
||||
# [205, 0, 0],
|
||||
# ]
|
||||
|
||||
|
||||
def get_label_array(color=None, label=None, font=None, fontSize=40):
|
||||
x, y, width, height = font.getbbox(label)
|
||||
text_image = np.zeros((height, width, 3), dtype=np.uint8)
|
||||
text_image = Image.fromarray(text_image)
|
||||
draw = ImageDraw.Draw(text_image)
|
||||
draw.rectangle((0, 0, width, height), fill=tuple(color))
|
||||
draw.text((0, -3), label, fill=(255, 255, 255), font=font)
|
||||
im_array = np.asarray(text_image)
|
||||
scale = fontSize / height
|
||||
im_array = cv2.resize(im_array, (0, 0), fx=scale, fy=scale)
|
||||
return im_array
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
font = ImageFont.truetype('platech.ttf', 40, encoding='utf-8')
|
||||
im_arrays = []
|
||||
for color in rainbows:
|
||||
im_array = get_label_array(color=color, label="植被", font=font, fontSize=40)
|
||||
im_arrays.append(im_array)
|
||||
frame_merge = np.hstack(tuple(im_arrays))
|
||||
cv2.imshow('frame1', frame_merge)
|
||||
cv2.waitKey(10000000)
|
||||
Binary file not shown.
|
|
@ -0,0 +1,63 @@
|
|||
import platform
|
||||
import subprocess
|
||||
import fileinput
|
||||
|
||||
|
||||
def get_mac_cpu_speed():
|
||||
commond = 'system_profiler SPHardwareDataType | grep "Processor Speed" | cut -d ":" -f2'
|
||||
proc = subprocess.Popen([commond], shell=True, stdout=subprocess.PIPE)
|
||||
output = proc.communicate()[0]
|
||||
output = output.decode() # bytes 转str
|
||||
speed = output.lstrip().rstrip('\n')
|
||||
return speed
|
||||
|
||||
|
||||
def get_linux_cpu_speed():
|
||||
for line in fileinput.input('/proc/cpuinfo'):
|
||||
if 'MHz' in line:
|
||||
value = line.split(':')[1].strip()
|
||||
value = float(value)
|
||||
speed = round(value / 1024, 1)
|
||||
return "{speed} GHz".format(speed=speed)
|
||||
|
||||
|
||||
def get_windows_cpu_speed():
|
||||
import winreg
|
||||
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"HARDWARE\DESCRIPTION\System\CentralProcessor\0")
|
||||
speed, type = winreg.QueryValueEx(key, "~MHz")
|
||||
speed = round(float(speed)/1024, 1)
|
||||
return "{speed} GHz".format(speed=speed)
|
||||
|
||||
|
||||
def get_cpu_speed():
|
||||
osname = platform.system() # 获取操作系统的名称
|
||||
speed = ''
|
||||
if osname == "Darwin":
|
||||
speed = get_mac_cpu_speed()
|
||||
if osname == "Linux":
|
||||
speed = get_linux_cpu_speed()
|
||||
if osname in ["Windows", "Win32"]:
|
||||
speed = get_windows_cpu_speed()
|
||||
|
||||
return speed
|
||||
|
||||
# print(get_cpu_speed())
|
||||
|
||||
import psutil
|
||||
# CPU逻辑数量
|
||||
# print(psutil.cpu_count())
|
||||
# CPU物理核心
|
||||
# print(psutil.cpu_count(logical=False))
|
||||
# print(psutil.cpu_percent(interval=1, percpu=True))
|
||||
#
|
||||
# print(psutil.virtual_memory())
|
||||
# print(psutil.virtual_memory().percent)#获取内存使用率
|
||||
# print(psutil.swap_memory())
|
||||
# print(psutil.disk_partitions()) # 磁盘分区信息
|
||||
# print(psutil.disk_usage('/')) # 磁盘使用情况
|
||||
# print(psutil.disk_io_counters()) # 磁盘IO
|
||||
|
||||
|
||||
print(len(psutil.pids()))
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
import time
|
||||
from pathlib import Path
|
||||
|
||||
import GPUtil
|
||||
import cv2
|
||||
import numpy as np
|
||||
import torch
|
||||
from PIL import ImageFont, Image, ImageDraw
|
||||
|
||||
|
||||
# print(Path(__file__)) # 表示当前脚本文件的路径
|
||||
# print(Path(__file__).parent) # 表示当前路径的父级目录
|
||||
|
||||
|
||||
# import time
|
||||
# from contextlib import contextmanager
|
||||
#
|
||||
# @contextmanager
|
||||
# def timer():
|
||||
# start_time = time.time()
|
||||
# yield
|
||||
# end_time = time.time()
|
||||
# print('Time elapsed:', end_time - start_time)
|
||||
# # 使用上下文管理器
|
||||
# with timer():
|
||||
# time.sleep(1)
|
||||
|
||||
# print(torch.cuda.is_available())
|
||||
# print(GPUtil.getGPUs()[0].name)
|
||||
|
||||
# def get_first_gpu_name():
|
||||
# gps = GPUtil.getGPUs()
|
||||
# if gps is None or len(gps) == 0:
|
||||
# raise Exception("未获取到gpu资源, 先检测服务器是否已经配置GPU资源!")
|
||||
# return gps[0].name
|
||||
# gpu_name = get_first_gpu_name()
|
||||
# aa = [g for g in ['3090', '2080', '4090', 'A10'] if g in gpu_name]
|
||||
# print(aa)
|
||||
#
|
||||
# import tensorrt as trt
|
||||
# # 定义反序列化引擎文件的函数
|
||||
# def deserialize_engine_from_file(engine_file_path):
|
||||
# runtime = trt.Runtime(trt.Logger())
|
||||
# engine = None
|
||||
# with open(engine_file_path, "rb") as f:
|
||||
# while True:
|
||||
# data = f.read(1024 * 1024)
|
||||
# if not data:
|
||||
# break
|
||||
# tmp_engine = runtime.deserialize_cuda_engine(data)
|
||||
# if engine is None:
|
||||
# engine = tmp_engine
|
||||
# else:
|
||||
# for i in range(tmp_engine.num_bindings):
|
||||
# engine.set_binding_shape(i, tmp_engine.get_binding_shape(i))
|
||||
# return engine
|
||||
# engine_file_path = "/path/to/engine_file.engine"
|
||||
# s = time.time()
|
||||
# engine = deserialize_engine_from_file(engine_file_path)
|
||||
# print("1 加载trt文件时间", time.time() - s)
|
||||
# s1 = time.time()
|
||||
# with open(engine_file_path, "rb") as f1, trt.Runtime(trt.Logger(trt.Logger.ERROR)) as runtime:
|
||||
# model = runtime.deserialize_cuda_engine(f1.read())
|
||||
# print("2 加载trt文件时间", time.time() - s1)
|
||||
|
||||
def get_label_array(color=None, label=None, outfontsize=None, fontpath="conf/platech.ttf"):
|
||||
# Plots one bounding box on image 'im' using PIL
|
||||
fontsize = outfontsize
|
||||
font = ImageFont.truetype(fontpath, fontsize, encoding='utf-8')
|
||||
x,y,txt_width, txt_height = font.getbbox(label)
|
||||
print(x,y,txt_width, txt_height)
|
||||
im = np.zeros((txt_height, txt_width, 3), dtype=np.uint8)
|
||||
im = Image.fromarray(im)
|
||||
draw = ImageDraw.Draw(im)
|
||||
draw.rectangle([0, 0, txt_width, txt_height], fill=tuple(color))
|
||||
draw.text((0, -3), label, fill=(255, 255, 255), font=font)
|
||||
im_array = np.asarray(im)
|
||||
# if outfontsize:
|
||||
# scaley = outfontsize / txt_height
|
||||
# im_array = cv2.resize(im_array, (0, 0), fx=scaley, fy=scaley)
|
||||
return im_array
|
||||
|
||||
|
||||
aaa = time.time()
|
||||
im_array = get_label_array(color=(0, 255, 0), label="排口", outfontsize=40, fontpath="platech.ttf")
|
||||
print(time.time() - aaa)
|
||||
cv2.imshow("frame", im_array)
|
||||
cv2.waitKey(0)
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
|
||||
from sklearn import linear_model
|
||||
|
||||
# x = [[20, 3],
|
||||
# [23, 7],
|
||||
# [31, 10],
|
||||
# [42, 13],
|
||||
# [50, 7],
|
||||
# [60, 5]]
|
||||
# y = [0, 1, 1, 1, 0, 0]
|
||||
# lr = linear_model.LogisticRegression()
|
||||
# lr.fit(x, y)
|
||||
# testX = [[28, 8]]
|
||||
# label = lr.predict(testX)
|
||||
# print("predicted label = ", label)
|
||||
#
|
||||
# prob = lr.predict_proba(testX)
|
||||
# print("probability = ", prob)
|
||||
|
||||
import tensorflow as tf
|
||||
tf.compat.v1.disable_eager_execution()
|
||||
hello = tf.constant("hello, world!")
|
||||
sess = tf.compat.v1.Session()
|
||||
result = sess.run(hello)
|
||||
sess.close()
|
||||
print(result)
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
import copy
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from multiprocessing import Queue, Process
|
||||
|
||||
from loguru import logger
|
||||
import subprocess as sp
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
from aip import AipImageClassify
|
||||
from enums.BaiduSdkEnum import BAIDUERRORDATA, VehicleEnumVALUE
|
||||
from enums.ExceptionEnum import ExceptionType
|
||||
from enums.ModelTypeEnum import ModelType
|
||||
from exception.CustomerException import ServiceException
|
||||
|
||||
|
||||
def get_recording_video_info(url):
|
||||
try:
|
||||
video_info = 'ffprobe -show_format -show_streams -of json %s' % url
|
||||
p = sp.Popen(video_info, stdout=sp.PIPE, stderr=sp.PIPE, shell=True)
|
||||
out, err = p.communicate(timeout=17)
|
||||
if p.returncode != 0:
|
||||
raise Exception("未获取视频信息!!!!!")
|
||||
probe = json.loads(out.decode('utf-8'))
|
||||
if probe is None or probe.get("streams") is None:
|
||||
raise Exception("未获取视频信息!!!!!:")
|
||||
video_stream = next((stream for stream in probe['streams'] if stream.get('codec_type') == 'video'), None)
|
||||
if video_stream is None:
|
||||
raise Exception("未获取视频信息!!!!!")
|
||||
width = video_stream.get('width')
|
||||
height = video_stream.get('height')
|
||||
nb_frames = video_stream.get('nb_frames')
|
||||
fps = video_stream.get('r_frame_rate')
|
||||
up, down = str(fps).split('/')
|
||||
fps = int(eval(up) / eval(down))
|
||||
return (width, height, nb_frames, fps)
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
client = AipImageClassify(str(31096670), 'Dam3O4tgPRN3qh4OYE82dbg7', '1PGZ9LAXRR5zcT5MN9rHcW8kLBIS5DAa')
|
||||
def vehicleDetect(client, iamge, options={}):
|
||||
reply_num = 0
|
||||
reply_value = None
|
||||
while True:
|
||||
try:
|
||||
options["show"] = "true"
|
||||
res_image = client.vehicleDetect(iamge,options)
|
||||
error_code = res_image.get("error_code")
|
||||
if error_code:
|
||||
enum = BAIDUERRORDATA.get(error_code)
|
||||
# 如果异常编码未知, 返回空值
|
||||
if enum is None:
|
||||
logger.error("百度云车辆检测异常!error_code:{}", error_code)
|
||||
return None
|
||||
# 重试指定次数后,还是异常,输出统一内部异常
|
||||
if enum.value[3] == 0:
|
||||
if reply_value is None:
|
||||
reply_value = 10
|
||||
logger.error("百度云车辆检测异常!error_code:{}, error_msg:{}, reply_num:{}", enum.value[0], enum.value[2], reply_num)
|
||||
raise Exception()
|
||||
# 重试指定次数后,还是异常,输出对应的异常
|
||||
if enum.value[3] == 1:
|
||||
if reply_value is None:
|
||||
reply_value = 10
|
||||
raise ServiceException(str(enum.value[0]), enum.value[2])
|
||||
# 重试指定次数后,还是异常,输出空
|
||||
if enum.value[3] == 2:
|
||||
if reply_value is None:
|
||||
reply_value = 10
|
||||
if reply_num >= reply_value:
|
||||
return None
|
||||
return res_image
|
||||
except ServiceException as s:
|
||||
time.sleep(0.2)
|
||||
reply_num += 1
|
||||
if reply_num > reply_value:
|
||||
logger.exception("车辆检测识别失败: {}", s.msg)
|
||||
raise ServiceException(e.code, e.msg)
|
||||
except Exception as e:
|
||||
logger.exception("车辆检测失败: {}, 当前重试次数:{}", e, reply_num)
|
||||
time.sleep(0.2)
|
||||
reply_num += 1
|
||||
if reply_num > reply_value:
|
||||
logger.exception("车辆检测识别失败: {}", e)
|
||||
raise ServiceException(ExceptionType.SERVICE_INNER_EXCEPTION.value[0],
|
||||
ExceptionType.SERVICE_INNER_EXCEPTION.value[1])
|
||||
|
||||
def mark(content, info, img, color):
|
||||
score = info.get("probability")
|
||||
if score is None:
|
||||
score = info.get("location").get("score")
|
||||
text = "%s: %.2f]" % (content, score)
|
||||
text_xy = (info.get("location").get("left"), info.get("location").get("top") - 25)
|
||||
img_lu = (info.get("location").get("left"), info.get("location").get("top"))
|
||||
img_rd = (info.get("location").get("left") + info.get("location").get("width"),
|
||||
info.get("location").get("top") + info.get("location").get("height"))
|
||||
cv2.putText(img, text, text_xy, cv2.FONT_HERSHEY_SIMPLEX, 1.0, color, 2, cv2.LINE_AA)
|
||||
count = 1
|
||||
if img.shape[1] > 1600:
|
||||
count = 2
|
||||
cv2.rectangle(img, img_lu, img_rd, color, count)
|
||||
return img
|
||||
|
||||
def pull_stream(url, queue, nb_frames):
|
||||
command = ['ffmpeg -re -y -i ' + url +' -f rawvideo -pix_fmt bgr24 -an -']
|
||||
pull_p = sp.Popen(command, stdout=sp.PIPE, shell=True)
|
||||
aa = 0
|
||||
try:
|
||||
while True:
|
||||
if queue.qsize() == 200:
|
||||
time.sleep(1)
|
||||
continue
|
||||
in_bytes = pull_p.stdout.read(width*height*3)
|
||||
if in_bytes is not None and len(in_bytes) > 0:
|
||||
img = np.frombuffer(in_bytes, np.uint8).reshape([height, width, 3])
|
||||
queue.put({"status": "1", "img": img})
|
||||
aa+=1
|
||||
else:
|
||||
if aa -10 > nb_frames:
|
||||
queue.put({"status": "2"})
|
||||
pull_p.terminate()
|
||||
pull_p.wait()
|
||||
break;
|
||||
except Exception as e:
|
||||
logger.exception("拉流异常: {}", e)
|
||||
finally:
|
||||
pull_p.terminate()
|
||||
pull_p.wait()
|
||||
|
||||
def getQueue(queue):
|
||||
eBody = None
|
||||
try:
|
||||
eBody = queue.get(block=False)
|
||||
return eBody
|
||||
except Exception as e:
|
||||
pass
|
||||
return eBody
|
||||
|
||||
def buildFrame(queue, senlin_mod, client, width, height, nb_frames, fps):
|
||||
frames = []
|
||||
status = None
|
||||
for i in range(queue.qsize()):
|
||||
frame_result = getQueue(queue)
|
||||
if frame_result is None:
|
||||
time.sleep(0.01)
|
||||
continue
|
||||
if frame_result.get("status") == '1':
|
||||
frames.append((frame_result.get("img"), senlin_mod, client, width, height, nb_frames, fps))
|
||||
else:
|
||||
status = frame_result.get("status")
|
||||
return frames, status
|
||||
|
||||
def process(frame):
|
||||
try:
|
||||
p_result, timeOut = frame[1].process(copy.deepcopy(frame[0]), frame[3])
|
||||
or_result, or_image = cv2.imencode(".jpg", frame[0])
|
||||
result = vehicleDetect(frame[2], or_image)
|
||||
if result is not None:
|
||||
vehicleInfo = result.get("vehicle_info")
|
||||
if vehicleInfo is not None and len(vehicleInfo) > 0:
|
||||
for i, info in enumerate(vehicleInfo):
|
||||
value = VehicleEnumVALUE.get(info.get("type"))
|
||||
if value is None:
|
||||
logger.error("车辆识别出现未支持的目标类型!type:{}", info.get("type"))
|
||||
raise ServiceException(ExceptionType.SERVICE_INNER_EXCEPTION.value[0],
|
||||
ExceptionType.SERVICE_INNER_EXCEPTION.value[1])
|
||||
p_result[1] = mark(value.value[1], info, p_result[1], (255, 0, 255))
|
||||
frame_merge = np.hstack((frame[0], p_result[1]))
|
||||
return frame_merge
|
||||
except Exception as e:
|
||||
logger.exception("模型分析异常: {}", e)
|
||||
return None
|
||||
|
||||
queue = Queue(200)
|
||||
url ='/home/th/tuo_heng/dev/11.mp4'
|
||||
width, height, nb_frames, fps = get_recording_video_info(url)
|
||||
my_process = Process(target = pull_stream, args=(url, queue, nb_frames))
|
||||
#启动子进程
|
||||
my_process.start()
|
||||
|
||||
|
||||
|
||||
current_path = os.path.abspath(os.path.dirname(__file__))
|
||||
import GPUtil
|
||||
senlin_mod = Model(str(GPUtil.getAvailable()[0]), [2,3,4], logger, "11111", ModelType.FOREST_FARM_MODEL)
|
||||
or_video_file = cv2.VideoWriter("aaa.mp4", cv2.VideoWriter_fourcc(*'mp4v'), fps,
|
||||
(int(width) * 2, int(height)))
|
||||
|
||||
|
||||
with ThreadPoolExecutor(max_workers=3) as t:
|
||||
task_frame = None
|
||||
while True:
|
||||
frames = []
|
||||
status = None
|
||||
if task_frame is not None:
|
||||
frames, status = task_frame.result()
|
||||
task_frame = t.submit(buildFrame, queue, senlin_mod, client, width, height, nb_frames, fps)
|
||||
if len(frames) == 0 and status is None:
|
||||
time.sleep(0.02)
|
||||
continue
|
||||
if frames is not None and len(frames) > 0:
|
||||
for result in t.map(process, frames):
|
||||
if result is not None:
|
||||
or_video_file.write(result)
|
||||
if status is None:
|
||||
continue
|
||||
if status.get("status") == "2":
|
||||
t.shutdown(wait=False)
|
||||
or_video_file.release()
|
||||
|
||||
t.shutdown(wait=False)
|
||||
or_video_file.release()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
import asyncio
|
||||
import copy
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from multiprocessing import Queue, Process
|
||||
|
||||
from loguru import logger
|
||||
import subprocess as sp
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
from aip import AipImageClassify
|
||||
import sys
|
||||
from enums.BaiduSdkEnum import BAIDUERRORDATA, VehicleEnumVALUE
|
||||
from enums.ExceptionEnum import ExceptionType
|
||||
from enums.ModelTypeEnum import ModelType
|
||||
from exception.CustomerException import ServiceException
|
||||
from util.ModelUtils import Model
|
||||
|
||||
|
||||
def get_recording_video_info(url):
|
||||
try:
|
||||
video_info = 'ffprobe -show_format -show_streams -of json %s' % url
|
||||
p = sp.Popen(video_info, stdout=sp.PIPE, stderr=sp.PIPE, shell=True)
|
||||
out, err = p.communicate(timeout=17)
|
||||
if p.returncode != 0:
|
||||
raise Exception("未获取视频信息!!!!!")
|
||||
probe = json.loads(out.decode('utf-8'))
|
||||
if probe is None or probe.get("streams") is None:
|
||||
raise Exception("未获取视频信息!!!!!:")
|
||||
video_stream = next((stream for stream in probe['streams'] if stream.get('codec_type') == 'video'), None)
|
||||
if video_stream is None:
|
||||
raise Exception("未获取视频信息!!!!!")
|
||||
width = video_stream.get('width')
|
||||
height = video_stream.get('height')
|
||||
nb_frames = video_stream.get('nb_frames')
|
||||
fps = video_stream.get('r_frame_rate')
|
||||
up, down = str(fps).split('/')
|
||||
fps = int(eval(up) / eval(down))
|
||||
return (width, height, nb_frames, fps)
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
client = AipImageClassify(str(31096670), 'Dam3O4tgPRN3qh4OYE82dbg7', '1PGZ9LAXRR5zcT5MN9rHcW8kLBIS5DAa')
|
||||
def vehicleDetect(client, iamge, options={}):
|
||||
reply_num = 0
|
||||
reply_value = None
|
||||
while True:
|
||||
try:
|
||||
options["show"] = "true"
|
||||
res_image = client.vehicleDetect(iamge,options)
|
||||
error_code = res_image.get("error_code")
|
||||
if error_code:
|
||||
enum = BAIDUERRORDATA.get(error_code)
|
||||
# 如果异常编码未知, 返回空值
|
||||
if enum is None:
|
||||
logger.error("百度云车辆检测异常!error_code:{}", error_code)
|
||||
return None
|
||||
# 重试指定次数后,还是异常,输出统一内部异常
|
||||
if enum.value[3] == 0:
|
||||
if reply_value is None:
|
||||
reply_value = 10
|
||||
logger.error("百度云车辆检测异常!error_code:{}, error_msg:{}, reply_num:{}", enum.value[0], enum.value[2], reply_num)
|
||||
raise Exception()
|
||||
# 重试指定次数后,还是异常,输出对应的异常
|
||||
if enum.value[3] == 1:
|
||||
if reply_value is None:
|
||||
reply_value = 10
|
||||
raise ServiceException(str(enum.value[0]), enum.value[2])
|
||||
# 重试指定次数后,还是异常,输出空
|
||||
if enum.value[3] == 2:
|
||||
if reply_value is None:
|
||||
reply_value = 10
|
||||
if reply_num >= reply_value:
|
||||
return None
|
||||
return res_image
|
||||
except ServiceException as s:
|
||||
time.sleep(0.2)
|
||||
reply_num += 1
|
||||
if reply_num > reply_value:
|
||||
logger.exception("车辆检测识别失败: {}", s.msg)
|
||||
raise ServiceException(e.code, e.msg)
|
||||
except Exception as e:
|
||||
logger.exception("车辆检测失败: {}, 当前重试次数:{}", e, reply_num)
|
||||
time.sleep(0.2)
|
||||
reply_num += 1
|
||||
if reply_num > reply_value:
|
||||
logger.exception("车辆检测识别失败: {}", e)
|
||||
raise ServiceException(ExceptionType.SERVICE_INNER_EXCEPTION.value[0],
|
||||
ExceptionType.SERVICE_INNER_EXCEPTION.value[1])
|
||||
|
||||
def mark(content, info, img, color):
|
||||
score = info.get("probability")
|
||||
if score is None:
|
||||
score = info.get("location").get("score")
|
||||
text = "%s: %.2f" % (content, score)
|
||||
text_xy = (info.get("location").get("left"), info.get("location").get("top") - 25)
|
||||
img_lu = (info.get("location").get("left"), info.get("location").get("top"))
|
||||
img_rd = (info.get("location").get("left") + info.get("location").get("width"),
|
||||
info.get("location").get("top") + info.get("location").get("height"))
|
||||
cv2.putText(img, text, text_xy, cv2.FONT_HERSHEY_SIMPLEX, 1.0, color, 2, cv2.LINE_AA)
|
||||
count = 1
|
||||
if img.shape[1] > 1600:
|
||||
count = 2
|
||||
cv2.rectangle(img, img_lu, img_rd, color, count)
|
||||
return img
|
||||
|
||||
async def mode_handler(img, width):
|
||||
return senlin_mod.process(copy.deepcopy(img), width)
|
||||
|
||||
async def modprocess(img, width):
|
||||
p_result, timeOut = await mode_handler(img, width)
|
||||
return p_result, timeOut
|
||||
|
||||
|
||||
async def car_handler(img, width):
|
||||
return car_mod.process(copy.deepcopy(img), width)
|
||||
|
||||
async def carprocess(img, width):
|
||||
p_result, timeOut = await car_handler(img, width)
|
||||
return p_result, timeOut
|
||||
|
||||
|
||||
async def baidu_handler(img, client):
|
||||
or_result, or_image = cv2.imencode(".jpg", img)
|
||||
return vehicleDetect(client, or_image)
|
||||
|
||||
async def baiduprocess(img, client):
|
||||
result = await baidu_handler(img, client)
|
||||
return result
|
||||
|
||||
|
||||
|
||||
url ='/home/th/tuo_heng/dev/11.mp4'
|
||||
width, height, nb_frames, fps = get_recording_video_info(url)
|
||||
|
||||
current_path = os.path.abspath(os.path.dirname(__file__))
|
||||
import GPUtil
|
||||
senlin_mod = Model(str(GPUtil.getAvailable()[0]), [2,3,4], logger, "11112", ModelType.FOREST_FARM_MODEL)
|
||||
car_mod = Model(str(GPUtil.getAvailable()[0]), [0], logger, "11112", ModelType.VEHICLE_MODEL)
|
||||
or_video_file = cv2.VideoWriter("aaa2.mp4", cv2.VideoWriter_fourcc(*'mp4v'), fps,
|
||||
(int(width) * 2, int(height)))
|
||||
|
||||
command = ['ffmpeg -re -y -i ' + url +' -f rawvideo -pix_fmt bgr24 -an -']
|
||||
pull_p = sp.Popen(command, stdout=sp.PIPE, shell=True)
|
||||
num = 0
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
try:
|
||||
while True:
|
||||
print(num, nb_frames)
|
||||
in_bytes = pull_p.stdout.read(width*height*3)
|
||||
if in_bytes is not None and len(in_bytes) > 0:
|
||||
img = np.frombuffer(in_bytes, np.uint8).reshape([height, width, 3])
|
||||
# r = loop.run_until_complete(asyncio.gather(modprocess(img, width), carprocess(img, width)))
|
||||
p_result, timeOut = senlin_mod.process(copy.deepcopy(img), width)
|
||||
p_result1, timeOut1 = car_mod.process(copy.deepcopy(p_result[1]), width)
|
||||
# r = loop.run_until_complete(asyncio.gather(modprocess(img, width), baiduprocess(img, client)))
|
||||
# p_result, timeOut = r[0]
|
||||
# result = r[1]
|
||||
# p_result, timeOut = senlin_mod.process(copy.deepcopy(img), width)
|
||||
|
||||
# if result is not None:
|
||||
# vehicleInfo = result.get("vehicle_info")
|
||||
# if vehicleInfo is not None and len(vehicleInfo) > 0:
|
||||
# for i, info in enumerate(vehicleInfo):
|
||||
# value = VehicleEnumVALUE.get(info.get("type"))
|
||||
# if value is None:
|
||||
# logger.error("车辆识别出现未支持的目标类型!type:{}", info.get("type"))
|
||||
# raise ServiceException(ExceptionType.SERVICE_INNER_EXCEPTION.value[0],
|
||||
# ExceptionType.SERVICE_INNER_EXCEPTION.value[1])
|
||||
# p_result[1] = mark(value.value[1], info, p_result[1], (255, 0, 255))
|
||||
frame_merge = np.hstack((img, p_result1[1]))
|
||||
or_video_file.write(frame_merge)
|
||||
num+=1
|
||||
else:
|
||||
if num -10 > nb_frames:
|
||||
break;
|
||||
finally:
|
||||
or_video_file.release()
|
||||
pull_p.terminate()
|
||||
pull_p.wait()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import multiprocessing as mp
|
||||
import time
|
||||
from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
|
||||
from multiprocessing import Queue, shared_memory
|
||||
|
||||
import tensorrt as trt
|
||||
|
||||
# multiprocessing.set_start_method('spawn')
|
||||
Detweights = "/home/th/tuo_heng/dev/AIlib2/weights/river2/yolov5_2080Ti_fp16.engine"
|
||||
with open(Detweights, "rb") as f:
|
||||
model = f.read()
|
||||
Segweights = "/home/th/tuo_heng/dev/AIlib2/weights/river2/stdc_360X640_2080Ti_fp16.engine"
|
||||
with open(Segweights, "rb") as f:
|
||||
segmodel = f.read()
|
||||
print(type(model), type(segmodel))
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import multiprocessing as mp
|
||||
import time
|
||||
from concurrent.futures import ProcessPoolExecutor
|
||||
from multiprocessing import Queue, shared_memory
|
||||
|
||||
import tensorrt as trt
|
||||
|
||||
# multiprocessing.set_start_method('spawn')
|
||||
Detweights = "/home/th/tuo_heng/dev/AIlib2/weights/river2/yolov5_2080Ti_fp16.engine"
|
||||
start = time.time()
|
||||
with open(Detweights, "rb") as f, trt.Runtime(trt.Logger(trt.Logger.ERROR)) as runtime:
|
||||
model = runtime.deserialize_cuda_engine(f.read())
|
||||
print(time.time() - start)
|
||||
start1 = time.time()
|
||||
Segweights = "/home/th/tuo_heng/dev/AIlib2/weights/river2/stdc_360X640_2080Ti_fp16.engine"
|
||||
with open(Segweights, "rb") as f, trt.Runtime(trt.Logger(trt.Logger.ERROR)) as runtime:
|
||||
segmodel = runtime.deserialize_cuda_engine(f.read())
|
||||
print(time.time() - start1)
|
||||
|
||||
def aa(buf):
|
||||
print(id(buf[0]), id(buf[1]))
|
||||
shm = shared_memory.SharedMemory(name='share', create=True, size=10000)
|
||||
buf = shm.buf
|
||||
buf = model
|
||||
buf[1] = segmodel
|
||||
print(id(model), id(segmodel))
|
||||
p = mp.Process(target=aa, args=(buf,))
|
||||
p1 = mp.Process(target=aa, args=(buf,))
|
||||
p.start()
|
||||
p1.start()
|
||||
time.sleep(10)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue