安装ffmepg并添加到环境变量中,流媒体使用m7s
运行效果 SSD:检测在10ms左右,yolov5在100ms左右
app.py
#!/usr/local/bin/python3 # encodin: utf-8 import subprocess import threading import time import cv2 import os from OpenVinoYoloV5Detector import OpenVinoYoloV5Detector from OpenVinoSSDDetector import OpenVinoSSDDetector class RTSCapture(cv2.VideoCapture): _cur_frame = None _reading = False _frame1 = None # 视频播放质量 值越大越模糊 # _quality = 2.5 # 1;1.5;2;2.5 # _interval_check = 1000 # 检测间隔 0 不跳帧 1秒10帧 _quality = 1 _interval_check = 0 _recvtime = 0 @staticmethod def get_even(num): if (num % 2) != 0: num = num + 1 return num @staticmethod def create(srcstream, dststream): rtscap = RTSCapture(srcstream) rtscap.frame_receiver = threading.Thread(target=rtscap.recv_frame, daemon=True) rtscap.frame_processer = threading.Thread(target=rtscap.prcoess_frame, daemon=True) rtscap.frame_sender = threading.Thread(target=rtscap.send_frame, daemon=True) fps = int(rtscap.get(cv2.CAP_PROP_FPS)) rtscap.width = rtscap.get_even(int(rtscap.get(cv2.CAP_PROP_FRAME_WIDTH) / rtscap._quality)) rtscap.height = rtscap.get_even(int(rtscap.get(cv2.CAP_PROP_FRAME_HEIGHT) / rtscap._quality)) rtscap.command = ['G:\\ZLMediaKit_Release\\ffmpeg.exe', '-y', '-f', 'rawvideo', '-vcodec', 'rawvideo', '-pix_fmt', 'bgr24', '-s', "{}x{}".format(rtscap.width, rtscap.height), '-r', str(fps), '-i', '-', '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-preset', 'ultrafast', '-f', 'rtsp', # flv rtsp '-rtsp_transport', 'udp', # 使用TCP推流,linux中一定要有这行 dststream] # 管道配置 rtscap._reading = True # 加载算法 rtscap.box_color = (0, 255, 0) # yolov5 # conf = { # # "weight_file": "weights/yolov5n_openvino_model/yolov5n.xml", # "weight_file": "weights/yolov5n_openvino_model/yolov5n.xml", # "device": "CPU" # } # rtscap.detector = OpenVinoYoloV5Detector(IN_conf=conf) #ssd conf = { "model_xml": "./weights/ssdlite_mobilenet_v2/FP16/ssdlite_mobilenet_v2.xml", "model_bin": "./weights/ssdlite_mobilenet_v2/FP16/ssdlite_mobilenet_v2.bin", "device": "CPU" } rtscap.detector = OpenVinoSSDDetector(IN_conf=conf) return rtscap def get_milsecond(self): t = time.time() return (int(round(t * 1000))) def isOK(self): status = self.isOpened() and self._reading return status def recv_frame(self): while self.isOK(): time.sleep(0.01) ok, frame = self.read() if not ok: break self._cur_frame = frame #self.p.stdin.write(frame.tostring()) self._reading = False def prcoess_frame(self): while self.isOK(): time.sleep(0.01) try: ok, frame = self.read_latest_frame() if not ok: continue # 算法解析 # 跳帧检测 if self.get_milsecond() - self._recvtime > self._interval_check: starttime = self.get_milsecond() detect_num, detect_data = self.detector.detect(frame) if len(detect_data): for m in detect_data: classname = m.get('class_name') score = m.get('score') location = m.get('location') box_l, box_t = int(location.get('x1')), int(location.get('y1')) box_r, box_b = int(location.get('x2')), int(location.get('y2')) frame = cv2.rectangle(frame, (box_l, box_t), (box_r, box_b), self.box_color, 2) frame = cv2.putText(frame, classname, (box_l, box_t + 15), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2) self._recvtime = self.get_milsecond() endtime = self.get_milsecond(); print('检测耗时:' + str(endtime - starttime)) self._frame1 = cv2.resize(frame, (self.width, self.height)) # 图像压缩 #self.p.stdin.write(frame1.tostring()) except Exception as e: ss = str(e) def send_frame(self): timeout = 3 self.p = subprocess.Popen(self.command, shell=False, stdin=subprocess.PIPE) while self.isOK(): time.sleep(0.01) try: if self._frame1 is not None: self.p.stdin.write(self._frame1.tostring()) except Exception as e: ss = str(e) def read2(self): frame = self._cur_frame self._cur_frame = None return frame is not None, frame def start_read(self): self.frame_receiver.start() self.frame_processer.start() self.frame_sender.start() self.read_latest_frame = self.read2 if self._reading else self.read def stop_read(self): self._reading = False if self.frame_receiver.is_alive(): self.frame_receiver.join() if self.frame_processer.is_alive(): self.frame_processer.join() if self.frame_sender.is_alive(): self.frame_sender.join() if __name__ == '__main__': url = src = '0' if src.isdigit(): url = int(src) rtscap1 = RTSCapture.create(url, "rtsp://127.0.0.1:554/live/test0") # test.mp4 0 rtscap1.start_read() os.system('pause')