You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

277 lines
16KB

  1. # -*- coding: utf-8 -*-
  2. from concurrent.futures import ThreadPoolExecutor
  3. from threading import Thread
  4. from time import sleep, time
  5. from traceback import format_exc
  6. from loguru import logger
  7. import cv2
  8. from entity.FeedBack import message_feedback
  9. from enums.ExceptionEnum import ExceptionType
  10. from exception.CustomerException import ServiceException
  11. from util.AliyunSdk import AliyunOssSdk
  12. from util import TimeUtils
  13. from enums.AnalysisStatusEnum import AnalysisStatus
  14. from util.PlotsUtils import draw_painting_joint
  15. from util.QueUtil import put_queue, get_no_block_queue, clear_queue
  16. class FileUpload(Thread):
  17. __slots__ = ('_fb_queue', '_context', '_image_queue', '_analyse_type', '_msg')
  18. def __init__(self, *args):
  19. super().__init__()
  20. self._fb_queue, self._context, self._msg, self._image_queue, self._analyse_type = args
  21. class ImageFileUpload(FileUpload):
  22. __slots__ = ()
  23. @staticmethod
  24. def handle_image(frame_msg, frame_step):
  25. # (high_score_image["code"], all_frames, draw_config["font_config"])
  26. # high_score_image["code"][code][cls] = (frame, frame_index_list[i], cls_list)
  27. det_xywh, frame, current_frame, all_frames, font_config = frame_msg
  28. '''
  29. det_xywh:{
  30. 'code':{
  31. 1: [[detect_targets_code, box, score, label_array, color]]
  32. }
  33. }
  34. 模型编号:modeCode
  35. 检测目标:detectTargetCode
  36. '''
  37. model_info = []
  38. # 更加模型编码解析数据
  39. for code, det_list in det_xywh.items():
  40. if len(det_list) > 0:
  41. for cls, target_list in det_list.items():
  42. if len(target_list) > 0:
  43. aFrame = frame.copy()
  44. for target in target_list:
  45. draw_painting_joint(target[1], aFrame, target[3], target[2], target[4], font_config, target[5])
  46. model_info.append({"modelCode": str(code), "detectTargetCode": str(cls), "aFrame": aFrame})
  47. if len(model_info) > 0:
  48. image_result = {
  49. "or_frame": frame,
  50. "model_info": model_info,
  51. "current_frame": current_frame,
  52. "last_frame": current_frame + frame_step
  53. }
  54. return image_result
  55. return None
  56. def run(self):
  57. msg, context = self._msg, self._context
  58. service = context["service"]
  59. base_dir, env, request_id = context["base_dir"], context["env"], msg["request_id"]
  60. logger.info("启动图片上传线程, requestId: {}", request_id)
  61. image_queue, fb_queue, analyse_type = self._image_queue, self._fb_queue, self._analyse_type
  62. service_timeout = int(service["timeout"])
  63. frame_step = int(service["filter"]["frame_step"]) + 120
  64. try:
  65. with ThreadPoolExecutor(max_workers=2) as t:
  66. # 初始化oss客户端
  67. aliyunOssSdk = AliyunOssSdk(base_dir, env, request_id)
  68. start_time = time()
  69. while True:
  70. try:
  71. if time() - start_time > service_timeout:
  72. logger.error("图片上线线程运行超时, requestId: {}", request_id)
  73. raise ServiceException(ExceptionType.TASK_EXCUTE_TIMEOUT.value[0],
  74. ExceptionType.TASK_EXCUTE_TIMEOUT.value[1])
  75. # 获取队列中的消息
  76. image_msg = get_no_block_queue(image_queue)
  77. if image_msg is not None:
  78. if image_msg[0] == 2:
  79. if 'stop' == image_msg[1]:
  80. logger.info("开始停止图片上传线程, requestId:{}", request_id)
  81. break
  82. if image_msg[0] == 1:
  83. image_result = self.handle_image(image_msg[1], frame_step)
  84. if image_result is not None:
  85. task = []
  86. or_image = cv2.imencode(".jpg", image_result["or_frame"])[1]
  87. or_image_name = build_image_name(image_result["current_frame"],
  88. image_result["last_frame"],
  89. analyse_type,
  90. "OR", "0", "0", request_id)
  91. or_future = t.submit(aliyunOssSdk.put_object, or_image_name, or_image.tobytes())
  92. task.append(or_future)
  93. model_info_list = image_result["model_info"]
  94. msg_list = []
  95. for model_info in model_info_list:
  96. ai_image = cv2.imencode(".jpg", model_info["aFrame"])[1]
  97. ai_image_name = build_image_name(image_result["current_frame"],
  98. image_result["last_frame"],
  99. analyse_type,
  100. "AI",
  101. model_info["modelCode"],
  102. model_info["detectTargetCode"],
  103. request_id)
  104. ai_future = t.submit(aliyunOssSdk.put_object, ai_image_name,
  105. ai_image.tobytes())
  106. task.append(ai_future)
  107. msg_list.append(message_feedback(request_id,
  108. AnalysisStatus.RUNNING.value,
  109. analyse_type, "", "", "",
  110. or_image_name,
  111. ai_image_name,
  112. model_info['modelCode'],
  113. model_info['detectTargetCode']))
  114. for tk in task:
  115. tk.result()
  116. for msg in msg_list:
  117. put_queue(fb_queue, msg, timeout=2, is_ex=False)
  118. del task, msg_list
  119. else:
  120. sleep(1)
  121. del image_msg
  122. except Exception:
  123. logger.error("图片上传异常:{}, requestId:{}", format_exc(), request_id)
  124. finally:
  125. logger.info("停止图片上传线程0, requestId:{}", request_id)
  126. clear_queue(image_queue)
  127. logger.info("停止图片上传线程1, requestId:{}", request_id)
  128. def build_image_name(*args):
  129. """
  130. {requestId}/{time_now}_frame-{current_frame}-{last_frame}_type_{random_num}-{mode_type}" \
  131. "-{modeCode}-{target}_{image_type}.jpg
  132. """
  133. current_frame, last_frame, mode_type, image_type, modeCode, target, request_id = args
  134. random_num = TimeUtils.now_date_to_str(TimeUtils.YMDHMSF)
  135. time_now = TimeUtils.now_date_to_str("%Y-%m-%d-%H-%M-%S")
  136. return "%s/%s_frame-%s-%s_type_%s-%s-%s-%s_%s.jpg" % (request_id, time_now, current_frame, last_frame,
  137. random_num, mode_type, modeCode, target, image_type)
  138. class ImageTypeImageFileUpload(Thread):
  139. __slots__ = ('_fb_queue', '_context', '_image_queue', '_analyse_type', '_msg')
  140. def __init__(self, *args):
  141. super().__init__()
  142. self._fb_queue, self._context, self._msg, self._image_queue, self._analyse_type = args
  143. @staticmethod
  144. def handle_image(det_xywh, copy_frame, font_config):
  145. """
  146. det_xywh:{
  147. 'code':{
  148. 1: [[detect_targets_code, box, score, label_array, color]]
  149. }
  150. }
  151. 模型编号:modeCode
  152. 检测目标:detectTargetCode
  153. """
  154. model_info = []
  155. # 更加模型编码解析数据
  156. for code, det_info in det_xywh.items():
  157. if det_info is not None and len(det_info) > 0:
  158. for cls, target_list in det_info.items():
  159. if target_list is not None and len(target_list) > 0:
  160. aiFrame = copy_frame.copy()
  161. for target in target_list:
  162. draw_painting_joint(target[1], aiFrame, target[3], target[2], target[4], font_config)
  163. model_info.append({
  164. "modelCode": str(code),
  165. "detectTargetCode": str(cls),
  166. "frame": aiFrame
  167. })
  168. if len(model_info) > 0:
  169. image_result = {
  170. "or_frame": copy_frame,
  171. "model_info": model_info,
  172. "current_frame": 0,
  173. "last_frame": 0
  174. }
  175. return image_result
  176. return None
  177. def run(self):
  178. context, msg = self._context, self._msg
  179. base_dir, env, request_id = context["base_dir"], context["env"], msg["request_id"]
  180. logger.info("启动图片识别图片上传线程, requestId: {}", request_id)
  181. image_queue, fb_queue, analyse_type = self._image_queue, self._fb_queue, self._analyse_type
  182. service_timeout = int(context["service"]["timeout"])
  183. with ThreadPoolExecutor(max_workers=2) as t:
  184. try:
  185. # 初始化oss客户端
  186. aliyunOssSdk = AliyunOssSdk(base_dir, env, request_id)
  187. start_time = time()
  188. while True:
  189. try:
  190. if time() - start_time > service_timeout:
  191. logger.error("拉流进程运行超时, requestId: {}", request_id)
  192. break
  193. # 获取队列中的消息
  194. image_msg = image_queue.get()
  195. if image_msg is not None:
  196. if image_msg[0] == 2:
  197. if 'stop' == image_msg[1]:
  198. logger.info("开始停止图片上传线程, requestId:{}", request_id)
  199. break
  200. if image_msg[0] == 1:
  201. task, msg_list = [], []
  202. det_xywh, image_url, copy_frame, font_config, result = image_msg[1]
  203. if det_xywh is None:
  204. ai_image_name = build_image_name(0, 0, analyse_type, "AI", result.get("modelCode"),
  205. result.get("type"), request_id)
  206. ai_future = t.submit(aliyunOssSdk.put_object, ai_image_name, copy_frame)
  207. task.append(ai_future)
  208. msg_list.append(message_feedback(request_id,
  209. AnalysisStatus.RUNNING.value,
  210. analyse_type, "", "", "",
  211. image_url,
  212. ai_image_name,
  213. result.get("modelCode"),
  214. result.get("type"),
  215. analyse_results=result))
  216. else:
  217. image_result = self.handle_image(det_xywh, copy_frame, font_config)
  218. if image_result:
  219. # 图片帧数编码
  220. if image_url is None:
  221. or_result, or_image = cv2.imencode(".jpg", image_result.get("or_frame"))
  222. image_url = build_image_name(image_result.get("current_frame"),
  223. image_result.get("last_frame"),
  224. analyse_type,
  225. "OR", "0", "O", request_id)
  226. or_future = t.submit(aliyunOssSdk.put_object, image_url,
  227. or_image.tobytes())
  228. task.append(or_future)
  229. model_info_list = image_result.get("model_info")
  230. for model_info in model_info_list:
  231. ai_result, ai_image = cv2.imencode(".jpg", model_info.get("frame"))
  232. ai_image_name = build_image_name(image_result.get("current_frame"),
  233. image_result.get("last_frame"),
  234. analyse_type,
  235. "AI",
  236. model_info.get("modelCode"),
  237. model_info.get("detectTargetCode"),
  238. request_id)
  239. ai_future = t.submit(aliyunOssSdk.put_object, ai_image_name,
  240. ai_image.tobytes())
  241. task.append(ai_future)
  242. msg_list.append(message_feedback(request_id,
  243. AnalysisStatus.RUNNING.value,
  244. analyse_type, "", "", "",
  245. image_url,
  246. ai_image_name,
  247. model_info.get('modelCode'),
  248. model_info.get('detectTargetCode'),
  249. analyse_results=result))
  250. for thread_result in task:
  251. thread_result.result()
  252. for msg in msg_list:
  253. put_queue(fb_queue, msg, timeout=2, is_ex=False)
  254. else:
  255. sleep(1)
  256. except Exception as e:
  257. logger.error("图片上传异常:{}, requestId:{}", format_exc(), request_id)
  258. finally:
  259. clear_queue(image_queue)
  260. logger.info("停止图片识别图片上传线程, requestId:{}", request_id)