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()