Gradio全解20——Streaming:流式传输的多媒体应用(6)——RT-DETR模型构建视频流目标检测系统

Gradio全解20------Streaming:流式传输的多媒体应用(6)------RT-DETR模型构建视频流目标检测系统

  • 本篇摘要
  • [20. Streaming:流式传输的多媒体应用](#20. Streaming:流式传输的多媒体应用)
    • [20.6 RT-DETR模型构建视频流目标检测系统](#20.6 RT-DETR模型构建视频流目标检测系统)
      • [20.6.1 RT-DETR模型](#20.6.1 RT-DETR模型)
        • [1. 模型介绍](#1. 模型介绍)
        • [2. 使用示例](#2. 使用示例)
      • [20.6.2 系统配置](#20.6.2 系统配置)
      • [20.6.3 推理函数实现](#20.6.3 推理函数实现)
        • [1. 视频读取与处理](#1. 视频读取与处理)
        • [2. 推理循环实现](#2. 推理循环实现)
      • [20.6.4 Gradio演示界面实现](#20.6.4 Gradio演示界面实现)
    • 参考文献:

本章目录如下:

  1. 《Gradio全解20------Streaming:流式传输的多媒体应用(1)------Mistral-7B实现流式传输音频:魔力8号球》
  2. 《Gradio全解20------Streaming:流式传输的多媒体应用(2)------基于Mini-Omni模型构建对话式聊天机器人》
  3. 《Gradio全解20------Streaming:流式传输的多媒体应用(3)------实时语音识别技术(ASR)》
  4. 《Gradio全解20------Streaming:流式传输的多媒体应用(4)------基于Groq的带自动语音检测功能的多模态Gradio应用》
  5. 《Gradio全解20------Streaming:流式传输的多媒体应用(5)------基于YOLO与WebRTC的摄像头实时目标检测》
  6. 《Gradio全解20------Streaming:流式传输的多媒体应用(6)------RT-DETR模型构建视频流目标检测系统》

本篇摘要

本章讲述流式传输的应用,包括音频、图像和视频格式的流式传输。

20. Streaming:流式传输的多媒体应用

本章讲述流式传输的应用,包括音频、图像和视频格式的流式传输。音频应用包括流式传输音频、构建音频对话式聊天机器人、实时语音识别技术和自动语音检测功能;图像应用包括基于WebRTC的摄像头实时目标检测;视频应用包括构建视频流目标检测系统。

20.6 RT-DETR模型构建视频流目标检测系统

本指南将使用RT-DETR模型对用户上传视频进行实时目标检测,并借助Gradio 5.0全新视频流功能实现检测结果的实时传输。在开始之前,先了解下RT-DETR模型。

20.6.1 RT-DETR模型

RT-DETR(Real-Time DEtection TRansformer)模型在论文《DETRs Beat YOLOs on Real-time Object Detection》中提出,它是一种专注于实现实时性能同时保持高精度的目标检测模型。该模型基于Transformer架构(该架构在深度学习多个领域已展现出显著优势),通过对图像进行处理来识别并定位其中的多个目标。

1. 模型介绍

近年来,基于Transformer的端到端检测器(DETRs)已取得显著性能突破。然而,DETRs计算成本高的问题尚未得到有效解决,这限制了其实际应用,也阻碍了其充分发挥无需后处理的优势,如非极大值抑制NMS(non-maximum suppression)。论文《DETRs Beat YOLOs on Real-time Object Detection》首先分析了现代实时目标检测器中NMS对推理速度的影响,并建立了端到端速度基准。为避免NMS导致的推理延迟,论文提出了首个实时端到端目标检测器RT-DETR。

具体而言,RT-DETR模型在以下方面实现了突破:

  • 设计了高效混合编码器,通过解耦尺度内交互与跨尺度融合来高效处理多尺度特征;
  • 提出IoU感知查询选择机制,以优化目标查询的初始化;
  • 提出的检测器支持通过灵活调整解码器层数(无需重新训练)来调节推理速度,提升了实时检测器的实用性。

实验表明:

  • RT-DETR-L在COCO val2017上达到53.0% AP(Average Precision),T4 GPU上实现114 FPS(Frame Per Second);RT-DETR-X达到54.8% AP与74 FPS。同规模下,两项指标均超越所有YOLO检测器;
  • 此外,RT-DETR-R50以53.1% AP和108 FPS的表现,在精度上超越DINO-Deformable-DETR-R50达2.2% AP,速度提升约21倍。对比图如下:

RT-DETR系列的最新版本是RT-DETRv2模型,它在论文《RT-DETRv2: Improved Baseline with Bag-of-Freebies for Real-Time Detection Transformer 》中提出。RT-DETRv2通过以下改进优化了RT-DETR:引入可选择的多尺度特征提取,采用离散采样算子提升部署兼容性及改进训练策略(包括动态数据增强和尺度自适应超参数)。这些改进在保持实时性能的同时,显著增强了模型的灵活性和实用性。

2. 使用示例

RT-DETR系统首先采用预训练的卷积神经网络(基于原始代码中的ResNet-D改进架构)对输入图像进行处理,该网络会从模型最后三个层级提取多层次特征图。随后,通过混合编码器架构,将提取到的多尺度特征转换为序列化的图像特征表示,这种设计能有效保留不同尺度的空间信息。接着,使用配备了辅助预测头的解码器迭代优化目标查询,该过程可直接生成边界框,无需额外后续处理即可获取边界框的分类置信度(logits)和坐标。示例代码如下:

python 复制代码
import torch
import requests
from PIL import Image
from transformers import RTDetrForObjectDetection, RTDetrImageProcessor

url = 'http://images.cocodataset.org/val2017/000000039769.jpg'
image = Image.open(requests.get(url, stream=True).raw)
# RT-DETR
image_processor = RTDetrImageProcessor.from_pretrained("PekingU/rtdetr_r50vd")
model = RTDetrForObjectDetection.from_pretrained("PekingU/rtdetr_r50vd")
# RT-DETRv2
# image_processor = RTDetrImageProcessor.from_pretrained("PekingU/rtdetr_v2_r18vd")
# model = RTDetrV2ForObjectDetection.from_pretrained("PekingU/rtdetr_v2_r18vd")
inputs = image_processor(images=image, return_tensors="pt")
with torch.no_grad():
    outputs = model(**inputs)

results = image_processor.post_process_object_detection(outputs, target_sizes=torch.tensor([(image.height, image.width)]), threshold=0.3)
for result in results:
    for score, label_id, box in zip(result["scores"], result["labels"], result["boxes"]):
        score, label = score.item(), label_id.item()
        box = [round(i, 2) for i in box.tolist()]
        print(f"{model.config.id2label[label]}: {score:.2f} {box}")

输出如下:

bash 复制代码
sofa: 0.97 [0.14, 0.38, 640.13, 476.21]
cat: 0.96 [343.38, 24.28, 640.14, 371.5]
cat: 0.96 [13.23, 54.18, 318.98, 472.22]
remote: 0.95 [40.11, 73.44, 175.96, 118.48]
remote: 0.92 [333.73, 76.58, 369.97, 186.99]

以下是由Hugging Face官方及社区提供的资源列表,可以帮助我们快速入门RT-DETR:

更多成员函数及其它详细信息请参阅: Transformers - RT-DETRRT-DETRv2

20.6.2 系统配置

系统配置分为环境准备、模型获取及硬件加速三部分,如下:

  1. 环境准备:首先需安装以下系统依赖:
bash 复制代码
opencv-python
torch
transformers>=4.43.0
spaces
  1. 模型获取:从Hugging Face Hub下载预训练模型:
python 复制代码
from transformers import RTDetrForObjectDetection, RTDetrImageProcessor

image_processor = RTDetrImageProcessor.from_pretrained("PekingU/rtdetr_r50vd")
model = RTDetrForObjectDetection.from_pretrained("PekingU/rtdetr_r50vd").to("cuda")
  1. 硬件加速:将模型通过代码**to("cuda")**加载至GPU显存以加速推理。本系统将部署在Hugging Face Spaces平台,利用其免费的ZeroGPU集群资源运行推理任务。

20.6.3 推理函数实现

我们的推理函数首先接收一个视频和用户设定的置信度阈值,目标检测模型会识别视频中多个对象并为每个对象分配置信度分数;置信度越低,出现误检的可能性就越高,因此允许用户根据需求自行设置这个置信度阈值。然后,该函数将遍历视频中的每一帧,并对每帧运行RT-DETR模型;我们会为帧中每个检测到的对象绘制边界框,并将帧保存到新的输出视频中,函数将以两秒为片段逐步生成输出视频。

由于存在基于时间的配额限制,所以需要在ZeroGPU上尽可能降低推理时间。我们可以在运行模型前将输出视频的原始帧率减半,并将输入帧的尺寸缩小为原尺寸的一半来降低推理时间。以下是完整的推理函数代码:

python 复制代码
import spaces
import cv2
from PIL import Image
import torch
import time
import numpy as np
import uuid
from draw_boxes import draw_bounding_boxes

SUBSAMPLE = 2
@spaces.GPU
def stream_object_detection(video, conf_threshold):
    cap = cv2.VideoCapture(video)
    fps = int(cap.get(cv2.CAP_PROP_FPS))
    desired_fps = fps // SUBSAMPLE
    width  = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) // 2
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) // 2

    # Use UUID to create a unique video file
    output_video_name = f"output_{uuid.uuid4()}.mp4"
    # This means we will output mp4 videos
    video_codec = cv2.VideoWriter_fourcc(*"mp4v") # type: ignore    # Output Video
    output_video = cv2.VideoWriter(output_video_name, video_codec, desired_fps, (width, height)) # type: ignore

    iterating, frame = cap.read()
    n_frames = 0
    batch = []
    while iterating:
        frame = cv2.resize( frame, (0,0), fx=0.5, fy=0.5)
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        if n_frames % SUBSAMPLE == 0:
            batch.append(frame)
        if len(batch) == 2 * desired_fps:
            inputs = image_processor(images=batch, return_tensors="pt").to("cuda")
            with torch.no_grad():
                outputs = model(**inputs)

            boxes = image_processor.post_process_object_detection(
                outputs,
                target_sizes=torch.tensor([(height, width)] * len(batch)),
                threshold=conf_threshold)
            for i, (array, box) in enumerate(zip(batch, boxes)):
                pil_image = draw_bounding_boxes(Image.fromarray(array), box, model, conf_threshold)
                frame = np.array(pil_image)
                # Convert RGB to BGR
                frame = frame[:, :, ::-1].copy()
                output_video.write(frame)

            batch = []
            output_video.release()
            yield output_video_name
            output_video_name = f"output_{uuid.uuid4()}.mp4"
            output_video = cv2.VideoWriter(output_video_name, video_codec, desired_fps, (width, height)) # type: ignore

        iterating, frame = cap.read()
        n_frames += 1

下面逐段解析代码。

1. 视频读取与处理

本应用将使用OpenCV处理视频,因为它是Python中处理视频的行业标准。通过OpenCV的VideoCapture型变量cap读取输入视频,每次调用cap.read()都会获取视频的下一帧。

为了实现Gradio视频流传输,我们需要为每个输出视频"块(chunk)"生成不同的视频文件,这里使用output_video = cv2.VideoWriter(output_video_name, video_codec, desired_fps, (width, height))创建要写入的下一个视频文件。其中video_codec用于指定视频文件类型,目前仅支持"mp4"和"ts"格式的视频流传输。

2. 推理循环实现

对于视频中的每一帧,我们都会将其尺寸缩小一半。由于OpenCV以BGR格式读取文件,需要先转换为transformer预期的RGB格式,这正是while循环前两行代码所实现的功能。

我们每隔一帧采集一次,并将帧添加至批处理列表,从而使输出视频的帧率减半。当批处理视频内容累计达到两秒时,就会运行模型推理。选择两秒阈值是为了确保每批处理时间足够短,既能实现服务器上的视频流畅显示,又不需要进行过多独立的前向传播。同时需要注意的是,为了使Gradio视频流正常工作,批处理时长至少需要1秒。

运行模型的前向传播后,我们使用模型的post_process_object_detection方法将检测到的边界框缩放到输入帧的原始尺寸。通过自定义函数绘制边界框,之后需要将RGB格式转换回BGR格式才能写回输出视频。完成当前批处理后,我们会为下一批处理创建新的输出视频文件。其中绘制边界框函数draw_bounding_boxes源码如下:

python 复制代码
from PIL import ImageDraw, ImageFont  # type: ignore
import colorsys

def get_color(label):
    # Simple hash function to generate consistent colors for each label
    hash_value = hash(label)
    hue = (hash_value % 100) / 100.0
    saturation = 0.7
    value = 0.9
    rgb = colorsys.hsv_to_rgb(hue, saturation, value)
    return tuple(int(x * 255) for x in rgb)

def draw_bounding_boxes(image, results: dict, model, threshold=0.3):
    draw = ImageDraw.Draw(image)
    font = ImageFont.load_default()

    for score, label_id, box in zip(
        results["scores"], results["labels"], results["boxes"]
    ):
        if score > threshold:
            label = model.config.id2label[label_id.item()]
            box = [round(i, 2) for i in box.tolist()]
            color = get_color(label)
            # Draw bounding box
            draw.rectangle(box, outline=color, width=3) # type: ignore

            # Prepare text
            text = f"{label}: {score:.2f}"
            text_bbox = draw.textbbox((0, 0), text, font=font)
            text_width = text_bbox[2] - text_bbox[0]
            text_height = text_bbox[3] - text_bbox[1]
            # Draw text background
            draw.rectangle(
                [box[0], box[1] - text_height - 4, box[0] + text_width, box[1]], # type: ignore
                fill=color, # type: ignore
            )
            # Draw text
            draw.text((box[0], box[1] - text_height - 4), text, fill="white", font=font)

    return image

20.6.4 Gradio演示界面实现

该UI代码与标准Gradio应用基本一致,我们将采用经典的双栏布局,使用户可以并排查看输入和输出视频。要实现流式传输功能,必须在输出视频组件中设置streaming=True参数,另外参数autoplay虽然并非必需配置,但启用该选项可显著提升用户观感。

python 复制代码
import gradio as gr

with gr.Blocks() as app:
    gr.HTML(
        """
    <h1 style='text-align: center'>
    Video Object Detection with <a href='https://huggingface.co/PekingU/rtdetr_r101vd_coco_o365' target='_blank'>RT-DETR</a>
    </h1>
    """)
    with gr.Row():
        with gr.Column():
            video = gr.Video(label="Video Source")
            conf_threshold = gr.Slider(
                label="Confidence Threshold",
                minimum=0.0,
                maximum=1.0,
                step=0.05,
                value=0.30,
            )
        with gr.Column():
            output_video = gr.Video(label="Processed Video", streaming=True, autoplay=True)

    video.upload(
        fn=stream_object_detection,
        inputs=[video, conf_threshold],
        outputs=[output_video],
    )

最后,我们可以在此处查看在Hugging Face Spaces上托管的演示:gradio/rt-detr-object-detection。运行截图如下:

参考文献:

  1. Streaming AI Generated Audio
  2. Run Inference on servers
  3. Spaces ZeroGPU: Dynamic GPU Allocation for Spaces
相关推荐
NAGNIP2 分钟前
一文搞懂深度学习中的通用逼近定理!
人工智能·算法·面试
冬奇Lab1 小时前
一天一个开源项目(第36篇):EverMemOS - 跨 LLM 与平台的长时记忆 OS,让 Agent 会记忆更会推理
人工智能·开源·资讯
冬奇Lab1 小时前
OpenClaw 源码深度解析(一):Gateway——为什么需要一个"中枢"
人工智能·开源·源码阅读
AngelPP5 小时前
OpenClaw 架构深度解析:如何把 AI 助手搬到你的个人设备上
人工智能
宅小年5 小时前
Claude Code 换成了Kimi K2.5后,我再也回不去了
人工智能·ai编程·claude
九狼5 小时前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
ZFSS5 小时前
Kimi Chat Completion API 申请及使用
前端·人工智能
天翼云开发者社区7 小时前
春节复工福利就位!天翼云息壤2500万Tokens免费送,全品类大模型一键畅玩!
人工智能·算力服务·息壤
知识浅谈7 小时前
教你如何用 Gemini 将课本图片一键转为精美 PPT
人工智能
Ray Liang7 小时前
被低估的量化版模型,小身材也能干大事
人工智能·ai·ai助手·mindx