IP 摄像机捕获 RTSP 流大延迟 OPENCV

2023-12-02

我正在尝试在 IP 摄像机上进行一些处理,效果很好,但我发现现实世界和视频捕获之间存在大约 7~10 秒的延迟。

我正在使用 rtsp://@ip:port/live ext

该相机有一个网络界面(IE / ActiveX),可以以非常低的延迟显示图像。 (约200~300毫秒)。

我测试了这个code当我将视频输入那里时,它工作得很好,没有延迟,当我使用带有 RTSP 协议的相机 IP 或无人机时,软工作延迟为 7~10 秒。

注意:我设置了分辨率(1080,720),并且使用了 GPU NVIDIA Qaudro1000,它运行良好,这就是我认为问题与处理或硬件无关,而是与代码有关。

编辑:它可能与 VideoCapture 缓冲区有关。有没有办法让它使用最新的图像?

edit2:我在 VLC 上得到了很好的延迟结果,仅延迟 300 毫秒

谢谢你!

您可以在下面看到我正在使用的代码:

import cv2
import time

import argparse
import numpy as np
from PIL import Image
from utils.anchor_generator import generate_anchors
from utils.anchor_decode import decode_bbox
from utils.nms import single_class_non_max_suppression
from load_model.pytorch_loader import load_pytorch_model, pytorch_inference

# model = load_pytorch_model('models/face_mask_detection.pth');
model = load_pytorch_model('models/model360.pth');
# anchor configuration
#feature_map_sizes = [[33, 33], [17, 17], [9, 9], [5, 5], [3, 3]]
feature_map_sizes = [[45, 45], [23, 23], [12, 12], [6, 6], [4, 4]]
anchor_sizes = [[0.04, 0.056], [0.08, 0.11], [0.16, 0.22], [0.32, 0.45], [0.64, 0.72]]
anchor_ratios = [[1, 0.62, 0.42]] * 5

# generate anchors
anchors = generate_anchors(feature_map_sizes, anchor_sizes, anchor_ratios)

# for inference , the batch size is 1, the model output shape is [1, N, 4],
# so we expand dim for anchors to [1, anchor_num, 4]
anchors_exp = np.expand_dims(anchors, axis=0)

id2class = {0: 'Mask', 1: 'NoMask'}


def inference(image,
              conf_thresh=0.5,
              iou_thresh=0.4,
              target_shape=(160, 160),
              draw_result=True,
              show_result=True
              ):
    '''
    Main function of detection inference
    :param image: 3D numpy array of image
    :param conf_thresh: the min threshold of classification probabity.
    :param iou_thresh: the IOU threshold of NMS
    :param target_shape: the model input size.
    :param draw_result: whether to daw bounding box to the image.
    :param show_result: whether to display the image.
    :return:
    '''
    # image = np.copy(image)
    output_info = []
    height, width, _ = image.shape
    image_resized = cv2.resize(image, target_shape)
    image_np = image_resized / 255.0  # 归一化到0~1
    image_exp = np.expand_dims(image_np, axis=0)

    image_transposed = image_exp.transpose((0, 3, 1, 2))

    y_bboxes_output, y_cls_output = pytorch_inference(model, image_transposed)
    # remove the batch dimension, for batch is always 1 for inference.
    y_bboxes = decode_bbox(anchors_exp, y_bboxes_output)[0]
    y_cls = y_cls_output[0]
    # To speed up, do single class NMS, not multiple classes NMS.
    bbox_max_scores = np.max(y_cls, axis=1)
    bbox_max_score_classes = np.argmax(y_cls, axis=1)

    # keep_idx is the alive bounding box after nms.
    keep_idxs = single_class_non_max_suppression(y_bboxes,
                                                 bbox_max_scores,
                                                 conf_thresh=conf_thresh,
                                                 iou_thresh=iou_thresh,
                                                 )

    for idx in keep_idxs:
        conf = float(bbox_max_scores[idx])
        class_id = bbox_max_score_classes[idx]
        bbox = y_bboxes[idx]
        # clip the coordinate, avoid the value exceed the image boundary.
        xmin = max(0, int(bbox[0] * width))
        ymin = max(0, int(bbox[1] * height))
        xmax = min(int(bbox[2] * width), width)
        ymax = min(int(bbox[3] * height), height)

        if draw_result:
            if class_id == 0:
                color = (0, 255, 0)
            else:
                color = (255, 0, 0)
            cv2.rectangle(image, (xmin, ymin), (xmax, ymax), color, 2)
            cv2.putText(image, "%s: %.2f" % (id2class[class_id], conf), (xmin + 2, ymin - 2),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.8, color)
        output_info.append([class_id, conf, xmin, ymin, xmax, ymax])

    if show_result:
        Image.fromarray(image).show()
    return output_info


def run_on_video(video_path, output_video_name, conf_thresh):
    cap = cv2.VideoCapture(video_path)
    height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
    width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
    fps = cap.get(cv2.CAP_PROP_FPS)
    fourcc = cv2.VideoWriter_fourcc(*'XVID')
    # writer = cv2.VideoWriter(output_video_name, fourcc, int(fps), (int(width), int(height)))
    total_frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)
    if not cap.isOpened():
        raise ValueError("Video open failed.")
        return
    status = True
    idx = 0
    while status:
        start_stamp = time.time()
        status, img_raw = cap.read()
        img_raw = cv2.cvtColor(img_raw, cv2.COLOR_BGR2RGB)
        read_frame_stamp = time.time()
        if (status):
            inference(img_raw,
                      conf_thresh,
                      iou_thresh=0.5,
                      target_shape=(360, 360),
                      draw_result=True,
                      show_result=False)
            cv2.imshow('image', img_raw[:, :, ::-1])
            cv2.waitKey(1)
            inference_stamp = time.time()
            # writer.write(img_raw)
            write_frame_stamp = time.time()
            idx += 1
            print("%d of %d" % (idx, total_frames))
            print("read_frame:%f, infer time:%f, write time:%f" % (read_frame_stamp - start_stamp,
                                                                   inference_stamp - read_frame_stamp,
                                                                   write_frame_stamp - inference_stamp))
    # writer.release()


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Face Mask Detection")
    parser.add_argument('--img-mode', type=int, default=1, help='set 1 to run on image, 0 to run on video.')
    parser.add_argument('--img-path', type=str, help='path to your image.')
    parser.add_argument('--video-path', type=str, default='0', help='path to your video, `0` means to use camera.')
    # parser.add_argument('--hdf5', type=str, help='keras hdf5 file')
    args = parser.parse_args()
    if args.img_mode:
        imgPath = args.img_path
        img = cv2.imread(imgPath)
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        inference(img, show_result=True, target_shape=(360, 360))
    else:
        video_path = args.video_path
        if args.video_path == '0':
            video_path = 0
        run_on_video(video_path, '', conf_thresh=0.5)

我不知道为什么 OpenCV 这么慢。我想要一些技巧来加快捕获速度。


问题出在 Opencv RTSP 流实现中。

要从流中获取垫子,您需要初始化编解码器并为其提供几个压缩帧数据包。编解码器内部有一个帧缓冲区。它的工作方式为 FIFO(先输入后输出)。您调用 avcodec_send_packet(),然后调用 avcodec_receive_frame()。返回的帧被包装到 mat 对象中并返回给您。 首先几个数据包初始化缓冲区并且不生成任何图片。

(更多信息在这里https://ffmpeg.org/doxygen/3.3/group__lavc__encdec.html )

不要指望 Python 中 opencv 上的 RTSP 具有低延迟。 在我的例子中,我能找到减少延迟的唯一方法是使用 FFMPEG 示例并用 C++ 重写它。

增加 I 帧的数量可能会有所帮助(剧透:不多) 附注我使用 RTSP 流的一些示例:https://www.youtube.com/channel/UCOK7D73tj7Dl4ZyXE-J0UNA

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

IP 摄像机捕获 RTSP 流大延迟 OPENCV 的相关文章

随机推荐

  • 未声明的标识符 - 不确定为什么

    我刚学C 我写了以下内容 void main void unsigned int curr dat 0 The current dat file to use unsigned char ch 0 Key entered at keyboa
  • 在 CMake 中列出 include_directories

    我有一个 cmake 构建 其中我正在搜索一堆依赖项 即我有很多实例 FIND PACKAGE SomePackage if SOMEPACKAGE FOUND include directories SOMEPACKAGE INCLUDE
  • 在 PostgreSQL 中使用 1 个查询选择特定行的最佳方法?

    我有一个 Java 应用程序 要求我在给定特定条件的情况下查找特定记录 例如 我有一张桌子 id song artist record label 1 Never Gonna Give You Up Rick Astley Rickroll
  • highcharts:在可见时而不是在页面加载时触发动画

    我有一个页面分为几个部分 可以通过锚点访问 有没有办法让 highcharts 动画在其特定部分变得可见而不是在页面加载时触发 http jsfiddle net YFMSb 2 图表位于 技能 下 因此希望在调出页面的该部分时出现初始动画
  • 如何使 bootstrap-multiselect 不可见我的默认值?

    我正在使用引导多选插件使处理下拉菜单更容易 但是 我在尝试默认隐藏菜单时遇到了问题 基本上 我有一个复选框 当选中此复选框时 我会显示下拉菜单 当取消选中它时 菜单应该隐藏 默认情况下该复选框未选中 因此我希望默认情况下也隐藏菜单 我尝试使
  • 如何确定Azure中应用程序服务计划CPU百分比90%的原因?

    我试图了解最大 CPU 百分比 内存利用率的原因应用服务计划但无法在天蓝色门户中找到任何简单的方法 在我的应用程序服务计划中 创建了 20 个应用程序服务 在 20 个应用程序服务中 我仅将 2 3 个应用程序服务用于用户界面 其他应用程序
  • 如何在 R 中执行 SQL 脚本时使用动态值

    我的 R 工作流程现在涉及处理大量查询 RPostgreSQL图书馆 我真的想让代码将来变得易于维护和管理 我开始从不同的地方加载大型查询 SQL files this有帮助 并且效果很好 然后我开始使用插值 that有帮助 这意味着我可以
  • 如何在 Apache 中使用 pcntl_fork() ?

    这是我的代码 里面index php 只是一个例子 pid pcntl fork if pid 1 die failed to fork else if pid nothing to do else putDataIntoWebServic
  • android mediaplayer - 播放一次铃声

    我尝试使用 MediaPlayer 类播放一次设备铃声 我必须使用 MediaPlayer 因为我将铃声与应用程序中的其他音频源一起使用 所以我尝试以下方法来播放随机铃声 但我无法阻止它循环 它继续播放 是否可以使用 MediaPlayer
  • 为什么不能将“使用静态”功能与私有枚举一起使用?还有其他选择吗?

    我有一个使用私有枚举的类 我想使用 C 6 使用静态 功能 如下所示 using static ConsoleForSimpleTests Foo MyEnum namespace ConsoleForSimpleTests public
  • 如何使用 XSSF (Apache POI 3.8) 调整图表大小?

    我想知道是否有办法使用 Apache POI XSSF 调整图表大小 目前我正在使用 Excel 模板 该模板具有一个图表 当使用 nameRanges 插入更多数据时 该图表会发生变化 一切正常 我面临的唯一麻烦是 图表始终保持相同的大小
  • 更改 Android 中的通知意图

    我有一项服务显示一条通知 我希望该通知能够在用户每次按下该通知时转到我的应用程序的特定活动 通常它是用户显示的最后一个 但并非总是如此 如果该活动之前已启动 则应返回该活动 如果没有 则应在应用程序的任务内打开该活动 并将其添加到活动任务中
  • 用对象动态填充 ArrayList

    我有抽象类 Human 它由其他两个类 Student 和 Worker 扩展 我正在尝试填写两个数组列表 Student 类型的 ArrayList 和 Worker 类型的 ArrayList 是动态的 public abstract
  • http 到 https 重定向 (tomcat/jboss)

    我们希望将访问应用程序的 http url 的所有流量重定向到 https 为此 我们在deploy jboss web deployer conf 目录中的 web xml 中设置以下值
  • 在perl中将元素添加到xml文件

    我有一个 xml 文件 如下所示
  • 收集器分组按java 8

    考虑这两个类 学科类别 class Subject long id String category String description public Subject long id String category String descr
  • 用于更改 Word 文档中的字体的脚本

    我有一个 Word 2007 文件 我想将 Courier New 字体的所有用法更改为 Lucida 控制台字体 我需要一个脚本来查找以该字体格式化的所有单词并将其更改为新字体 我怎样才能做到这一点 在Word中 您可以自己录制宏 然后打
  • 如何在ajax调用中传递特殊字符

    如何在ajax调用中传递特殊字符变量i并在spring控制器中获取值 如果文件name jsuduu function deleeteimg var filename filenm text alert filename var filen
  • 将除少数 IP 地址之外的所有请求重定向到子目录

    这个问题试图结合从以前的一些答案中获得的知识 所以不要标记为重复 除非答案满足即将给出的所有标准 这就是我想做的 我需要暂时将 htaccess 访问者重定向到我的网站的克隆副本 以便我可以对现有网站进行修改 因此 我有以下需求 1 所有用
  • IP 摄像机捕获 RTSP 流大延迟 OPENCV

    我正在尝试在 IP 摄像机上进行一些处理 效果很好 但我发现现实世界和视频捕获之间存在大约 7 10 秒的延迟 我正在使用 rtsp ip port live ext 该相机有一个网络界面 IE ActiveX 可以以非常低的延迟显示图像