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.

222 lines
8.5KB

  1. import copy
  2. import json
  3. import os
  4. import time
  5. from concurrent.futures import ThreadPoolExecutor
  6. from multiprocessing import Queue, Process
  7. from loguru import logger
  8. import subprocess as sp
  9. import cv2
  10. import numpy as np
  11. from aip import AipImageClassify
  12. from enums.BaiduSdkEnum import BAIDUERRORDATA, VehicleEnumVALUE
  13. from enums.ExceptionEnum import ExceptionType
  14. from enums.ModelTypeEnum import ModelType
  15. from exception.CustomerException import ServiceException
  16. def get_recording_video_info(url):
  17. try:
  18. video_info = 'ffprobe -show_format -show_streams -of json %s' % url
  19. p = sp.Popen(video_info, stdout=sp.PIPE, stderr=sp.PIPE, shell=True)
  20. out, err = p.communicate(timeout=17)
  21. if p.returncode != 0:
  22. raise Exception("未获取视频信息!!!!!")
  23. probe = json.loads(out.decode('utf-8'))
  24. if probe is None or probe.get("streams") is None:
  25. raise Exception("未获取视频信息!!!!!:")
  26. video_stream = next((stream for stream in probe['streams'] if stream.get('codec_type') == 'video'), None)
  27. if video_stream is None:
  28. raise Exception("未获取视频信息!!!!!")
  29. width = video_stream.get('width')
  30. height = video_stream.get('height')
  31. nb_frames = video_stream.get('nb_frames')
  32. fps = video_stream.get('r_frame_rate')
  33. up, down = str(fps).split('/')
  34. fps = int(eval(up) / eval(down))
  35. return (width, height, nb_frames, fps)
  36. except Exception as e:
  37. raise e
  38. client = AipImageClassify(str(31096670), 'Dam3O4tgPRN3qh4OYE82dbg7', '1PGZ9LAXRR5zcT5MN9rHcW8kLBIS5DAa')
  39. def vehicleDetect(client, iamge, options={}):
  40. reply_num = 0
  41. reply_value = None
  42. while True:
  43. try:
  44. options["show"] = "true"
  45. res_image = client.vehicleDetect(iamge,options)
  46. error_code = res_image.get("error_code")
  47. if error_code:
  48. enum = BAIDUERRORDATA.get(error_code)
  49. # 如果异常编码未知, 返回空值
  50. if enum is None:
  51. logger.error("百度云车辆检测异常!error_code:{}", error_code)
  52. return None
  53. # 重试指定次数后,还是异常,输出统一内部异常
  54. if enum.value[3] == 0:
  55. if reply_value is None:
  56. reply_value = 10
  57. logger.error("百度云车辆检测异常!error_code:{}, error_msg:{}, reply_num:{}", enum.value[0], enum.value[2], reply_num)
  58. raise Exception()
  59. # 重试指定次数后,还是异常,输出对应的异常
  60. if enum.value[3] == 1:
  61. if reply_value is None:
  62. reply_value = 10
  63. raise ServiceException(str(enum.value[0]), enum.value[2])
  64. # 重试指定次数后,还是异常,输出空
  65. if enum.value[3] == 2:
  66. if reply_value is None:
  67. reply_value = 10
  68. if reply_num >= reply_value:
  69. return None
  70. return res_image
  71. except ServiceException as s:
  72. time.sleep(0.2)
  73. reply_num += 1
  74. if reply_num > reply_value:
  75. logger.exception("车辆检测识别失败: {}", s.msg)
  76. raise ServiceException(e.code, e.msg)
  77. except Exception as e:
  78. logger.exception("车辆检测失败: {}, 当前重试次数:{}", e, reply_num)
  79. time.sleep(0.2)
  80. reply_num += 1
  81. if reply_num > reply_value:
  82. logger.exception("车辆检测识别失败: {}", e)
  83. raise ServiceException(ExceptionType.SERVICE_INNER_EXCEPTION.value[0],
  84. ExceptionType.SERVICE_INNER_EXCEPTION.value[1])
  85. def mark(content, info, img, color):
  86. score = info.get("probability")
  87. if score is None:
  88. score = info.get("location").get("score")
  89. text = "%s: %.2f]" % (content, score)
  90. text_xy = (info.get("location").get("left"), info.get("location").get("top") - 25)
  91. img_lu = (info.get("location").get("left"), info.get("location").get("top"))
  92. img_rd = (info.get("location").get("left") + info.get("location").get("width"),
  93. info.get("location").get("top") + info.get("location").get("height"))
  94. cv2.putText(img, text, text_xy, cv2.FONT_HERSHEY_SIMPLEX, 1.0, color, 2, cv2.LINE_AA)
  95. count = 1
  96. if img.shape[1] > 1600:
  97. count = 2
  98. cv2.rectangle(img, img_lu, img_rd, color, count)
  99. return img
  100. def pull_stream(url, queue, nb_frames):
  101. command = ['ffmpeg -re -y -i ' + url +' -f rawvideo -pix_fmt bgr24 -an -']
  102. pull_p = sp.Popen(command, stdout=sp.PIPE, shell=True)
  103. aa = 0
  104. try:
  105. while True:
  106. if queue.qsize() == 200:
  107. time.sleep(1)
  108. continue
  109. in_bytes = pull_p.stdout.read(width*height*3)
  110. if in_bytes is not None and len(in_bytes) > 0:
  111. img = np.frombuffer(in_bytes, np.uint8).reshape([height, width, 3])
  112. queue.put({"status": "1", "img": img})
  113. aa+=1
  114. else:
  115. if aa -10 > nb_frames:
  116. queue.put({"status": "2"})
  117. pull_p.terminate()
  118. pull_p.wait()
  119. break;
  120. except Exception as e:
  121. logger.exception("拉流异常: {}", e)
  122. finally:
  123. pull_p.terminate()
  124. pull_p.wait()
  125. def getQueue(queue):
  126. eBody = None
  127. try:
  128. eBody = queue.get(block=False)
  129. return eBody
  130. except Exception as e:
  131. pass
  132. return eBody
  133. def buildFrame(queue, senlin_mod, client, width, height, nb_frames, fps):
  134. frames = []
  135. status = None
  136. for i in range(queue.qsize()):
  137. frame_result = getQueue(queue)
  138. if frame_result is None:
  139. time.sleep(0.01)
  140. continue
  141. if frame_result.get("status") == '1':
  142. frames.append((frame_result.get("img"), senlin_mod, client, width, height, nb_frames, fps))
  143. else:
  144. status = frame_result.get("status")
  145. return frames, status
  146. def process(frame):
  147. try:
  148. p_result, timeOut = frame[1].process(copy.deepcopy(frame[0]), frame[3])
  149. or_result, or_image = cv2.imencode(".jpg", frame[0])
  150. result = vehicleDetect(frame[2], or_image)
  151. if result is not None:
  152. vehicleInfo = result.get("vehicle_info")
  153. if vehicleInfo is not None and len(vehicleInfo) > 0:
  154. for i, info in enumerate(vehicleInfo):
  155. value = VehicleEnumVALUE.get(info.get("type"))
  156. if value is None:
  157. logger.error("车辆识别出现未支持的目标类型!type:{}", info.get("type"))
  158. raise ServiceException(ExceptionType.SERVICE_INNER_EXCEPTION.value[0],
  159. ExceptionType.SERVICE_INNER_EXCEPTION.value[1])
  160. p_result[1] = mark(value.value[1], info, p_result[1], (255, 0, 255))
  161. frame_merge = np.hstack((frame[0], p_result[1]))
  162. return frame_merge
  163. except Exception as e:
  164. logger.exception("模型分析异常: {}", e)
  165. return None
  166. queue = Queue(200)
  167. url ='/home/th/tuo_heng/dev/11.mp4'
  168. width, height, nb_frames, fps = get_recording_video_info(url)
  169. my_process = Process(target = pull_stream, args=(url, queue, nb_frames))
  170. #启动子进程
  171. my_process.start()
  172. current_path = os.path.abspath(os.path.dirname(__file__))
  173. import GPUtil
  174. senlin_mod = Model(str(GPUtil.getAvailable()[0]), [2,3,4], logger, "11111", ModelType.FOREST_FARM_MODEL)
  175. or_video_file = cv2.VideoWriter("aaa.mp4", cv2.VideoWriter_fourcc(*'mp4v'), fps,
  176. (int(width) * 2, int(height)))
  177. with ThreadPoolExecutor(max_workers=3) as t:
  178. task_frame = None
  179. while True:
  180. frames = []
  181. status = None
  182. if task_frame is not None:
  183. frames, status = task_frame.result()
  184. task_frame = t.submit(buildFrame, queue, senlin_mod, client, width, height, nb_frames, fps)
  185. if len(frames) == 0 and status is None:
  186. time.sleep(0.02)
  187. continue
  188. if frames is not None and len(frames) > 0:
  189. for result in t.map(process, frames):
  190. if result is not None:
  191. or_video_file.write(result)
  192. if status is None:
  193. continue
  194. if status.get("status") == "2":
  195. t.shutdown(wait=False)
  196. or_video_file.release()
  197. t.shutdown(wait=False)
  198. or_video_file.release()