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
相关推荐
Mark_Aussie22 分钟前
MCP连接Agent:AI时代的TCP/IP
人工智能
攻城狮7号36 分钟前
大模型微调Fine-tuning:从概念到实践的全面解析
人工智能·python·前沿技术·fine-tuning·大模型微调
Oliverro1 小时前
EasyRTC嵌入式音视频通话SDK驱动智能硬件音视频应用新发展
人工智能·音视频
卡尔曼的BD SLAMer1 小时前
问题 | 当前计算机视觉迫切解决的问题
图像处理·人工智能·深度学习·计算机视觉·信息与通信
basketball6161 小时前
使用pytorch保存和加载预训练的模型方法
人工智能·pytorch·python
小彭律师2 小时前
基于深度学习的交通标志识别系统
人工智能·深度学习
灏瀚星空2 小时前
PyTorch 入门与核心概念详解:从基础到实战问题解决
人工智能·pytorch·python·深度学习·算法·机器学习
云钥科技2 小时前
GSENSE2020BSI sCMOS科学级相机主要参数及应用场景
人工智能
jerwey2 小时前
Diffusion Transformer(DiT)
人工智能·深度学习·transformer·dit
Timmer丿2 小时前
AI开发跃迁指南(第三章:第四维度1——Milvus、weaviate、redis等向量数据库介绍及对比选型)
数据库·人工智能·milvus