openvino yolov5/ssd 实时推流目标检测在html上显示

安装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')

 

posted @ 2023-02-12 15:16  CHHC  阅读(270)  评论(0编辑  收藏  举报