第12章(2)——项目九:基于gr.Video+RT-DETR的流目标检测

第12章(2)------项目九:基于gr.Video+RT-DETR的流目标检测

    • [12.3 RT-DETR:实时端到端检测模型](#12.3 RT-DETR:实时端到端检测模型)
      • [12.3.1 模型技术、架构与最新版本](#12.3.1 模型技术、架构与最新版本)
      • [12.3.2 图像目标识别示例](#12.3.2 图像目标识别示例)
    • [12.4 项目九:基于gr.Video+RT-DETR的流目标检测](#12.4 项目九:基于gr.Video+RT-DETR的流目标检测)
      • [12.4.1 流目标检测函数及解读](#12.4.1 流目标检测函数及解读)
      • [12.4.2 绘制边界框及界面实现](#12.4.2 绘制边界框及界面实现)

12.3 RT-DETR:实时端到端检测模型

在使用gr.Video+RT-DETR模型构建视频流目标检测系统之前,先了解下RT-DETR模型。先讲解模型的技术与架构,然后着眼于训练细节与性能表现,接着介绍其最新版本RT-DETRv2,最后通过图像目标识别示例演示其用法及列出下一步的学习资源。

12.3.1 模型技术、架构与最新版本

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

近年来,基于Transformer的端到端检测器(DETRs)已取得显著性能突破。然而,DETRs计算成本高的问题尚未得到有效解决,这阻碍了其充分发挥无需后处理的优势,如非极大值抑制NMS(non-maximum suppression)。鉴于现代实时目标检测器中NMS对推理速度的延迟影响,原论文建立了端到端速度基准并提出了首个实时端到端目标检测器RT-DETR。具体而言,RT-DETR模型在以下方面实现了突破:

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

模型架构与目标 。模型架构如图12-4所示,RT-DETR系统首先采用预训练的卷积神经网络(基于原始代码中的ResNet-D改进架构)对输入图像进行预处理,然后将主干网络的特征输入最后三个阶段。其处理过程如下所述:

(1)第一阶段,高效混合编码器通过基于注意力机制的AIFI(Intra-scale Feature Interaction,尺度内特征交互)和基于CNN的CCFF(Cross-scale Feature Fusion,跨尺度特征融合),将多尺度特征转换为图像特征序列。

(2)第二阶段,不确定性最小化查询选择机制,会选取固定数量的编码器特征作为解码器查询的初始对象。

(3)第三阶段,带有辅助预测头的解码器通过迭代优化查询,生成目标类别与边界框。

图12-4

关于RT-DETR请参阅:PekingU/rtdetr_r101vd_coco_o365🖇️链接12-6

最新版本RT-DETRv2 。RT-DETR系列的最新版本是RT-DETRv2模型,它在论文《RT-DETRv2: Improved Baseline with Bag-of-Freebies for Real-Time Detection Transformer 》(🖇️链接12-7)中提出。RT-DETRv2模型介绍如下:

  • 改进优化:相较于RT-DETR,引入可选择的多尺度特征提取,采用离散采样算子提升部署兼容性,以及改进训练策略(包括动态数据增强和尺度自适应超参数)。这些改进在保持实时性能的同时,显著增强了模型的灵活性和实用性。
  • 训练过程:RT-DETRv2模型基于COCO train2017训练集进行训练,并在COCO val2017验证集进行性能验证,并采用标准AP指标以及APval50作为评估标准。
  • 应用场景:非常适合需要实时目标检测的多种应用场景,包括自动驾驶、监控系统、机器人技术和零售分析。其增强的灵活性和部署友好型设计,使其既适用于边缘设备也能满足大规模系统需求,确保动态真实环境中实现高精度与高速检测。

使用RT-DETRv2代码,只需导入RT-DETRv2并替换模型名称,如下所示:

py 复制代码
from transformers import RTDetrV2ForObjectDetection, RTDetrImageProcessor
image_processor = RTDetrImageProcessor.from_pretrained("PekingU/rtdetr_v2_r101vd")
model = RTDetrV2ForObjectDetection.from_pretrained("PekingU/rtdetr_v2_r101vd")

关于RT-DETRv2请参阅:PekingU/rtdetr_v2_r101vd🖇️链接12-8

12.3.2 图像目标识别示例

本节展示使用RT-DETR进行图标目标识别的代码,如代码12-8所示:
代码12-8

py 复制代码
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)
image_processor = RTDetrImageProcessor.from_pretrained("PekingU/rtdetr_r50vd")
inputs = image_processor(images=image, return_tensors="pt")
model = RTDetrForObjectDetection.from_pretrained("PekingU/rtdetr_r50vd")

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]
remote: 0.95 [40.11, 73.44, 175.96, 118.48]

可使用以下代码进行可视化:

py 复制代码
from PIL import ImageDraw
draw = ImageDraw.Draw(image)
for score, label, box in zip(results["scores"], results["labels"], results["boxes"]):
    box = [round(i, 2) for i in box.tolist()]
    x, y, x2, y2 = tuple(box)
    draw.rectangle((x, y, x2, y2), outline="red", width=1)
    draw.text((x, y), model.config.id2label[label.item()], fill="white")

12.4 项目九:基于gr.Video+RT-DETR的流目标检测

本节使用RT-DETR对用户上传视频进行实时目标检测,并借助Gradio视频流功能实现检测结果的实时传输。开始之前,先安装相关库并从Hub下载预训练模型:

py 复制代码
from transformers import RTDetrForObjectDetection, RTDetrImageProcessor
image_processor = RTDetrImageProcessor.from_pretrained("PekingU/rtdetr_r50vd")
model = RTDetrForObjectDetection.from_pretrained("PekingU/rtdetr_r50vd").to("cuda")

另外,将模型通过代码to("cuda")加载至GPU显存以加速推理。本项目可部署在Spaces平台,利用其免费的ZeroGPU集群加速运行推理任务。本项目Spaces地址:gradio/rt-detr-object-detection🖇️链接12-9

12.4.1 流目标检测函数及解读

以下是完整的推理函数代码,如代码12-9所示:
代码12-9

py 复制代码
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
    output_video_name = f"output_{uuid.uuid4()}.mp4"
    video_codec = cv2.VideoWriter_fourcc(*"mp4v") 
    output_video = cv2.VideoWriter(output_video_name, video_codec, desired_fps, (width, height)) 

    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) # RT-DETR模型检测对象
            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))
        iterating, frame = cap.read()
        n_frames += 1

代码实现目标检测功能,下面逐段解析代码:

  • 推理函数首先接收一个视频和用户设定的置信度阈值,目标检测模型会识别视频中多个对象并为每个对象分配置信度分数。
  • 本应用将使用OpenCV处理视频,因为它是Python中处理视频的行业标准。通过OpenCV的VideoCapture型变量cap读取输入视频,每次调用cap.read()都会获取视频的下一帧。
  • 由于存在基于时间的配额限制,所以需要在ZeroGPU上尽可能降低推理时间。将输出视频的原始帧率减半,并将尺寸缩小为原来一半以降低推理时间。
  • 为了实现Gradio视频流传输,需要为每个输出视频"块(chunk)"生成不同的视频文件,这里使用output_video = cv2.VideoWriter(output_video_name, video_codec, desired_fps, (width, height))创建要写入的下一个视频文件。其中video_codec用于指定视频文件类型,目前仅支持"mp4"和"ts"格式的视频流。
  • 对于视频中的每一帧,都会将其尺寸缩小一半。由于OpenCV以BGR格式读取文件,需要先转换为transformer预期的RGB格式。且每隔一帧采集一次,并将帧添加至批处理,从而使输出视频的帧率减半。当批处理视频内容累计达到两秒时,就会运行模型推理。选择两秒阈值(Gradio要求至少1秒)为了确保时间足够短,既能实现服务器上的视频流畅显示,又不需要进行过多独立的前向传播。
  • 利用函数image_processor,将batch中图像处理成模型可以接受的格式。然后遍历每一帧图像并运行RT-DETR模型以进行对象检测。运行模型的前向传播后,通过后处理方法将检测到的边界框缩放到输入帧的原始尺寸。
  • 通过自定义函数绘制边界框,draw_bounding_boxes会为帧中每个检测到的对象绘制边界框。之后需要将RGB格式转换回BGR格式,并将帧保存到新的输出视频中。完成当前批处理后,为下一批处理创建新的输出视频文件。

12.4.2 绘制边界框及界面实现

其中绘制边界框函数draw_bounding_boxes源码,如代码12-10所示:
代码12-10

py 复制代码
# draw_boxes.py
from PIL import ImageDraw, ImageFont
import colorsys

def get_color(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)
            # 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 with color blocks
            draw.rectangle(
                [box[0], box[1] - text_height - 4, box[0] + text_width, box[1]], 
                fill=color)
            draw.text((box[0], box[1] - text_height - 4), text, fill="white", font=font) 
    return image

该代码模块使用Pillow库(PIL)实现目标检测结果的可视化标注,主要功能有:

  • 函数draw_bounding_boxes用于在图像上绘制目标检测结果,包括边界框、带透明背景的类别标签及置信度分数。核心功能包含:过滤低置信度检测结果(默认阈值0.3)、绘制彩色边界框(宽度3像素)、添加带背景的文本标签(类别名+置信度)、自动计算文本位置使其位于框体上方。
  • 函数get_color为不同类别生成固定颜色。通过标签的哈希值计算HSV色彩,保证相同输入始终产生相同输出颜色。

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

(1)运行前,选装GPU版本的torch和torchvision,命令如下:

bash 复制代码
# 查看本机cuda版本命令:nvidia-smi
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128

(2)gr.Video的upload()可能不会自动触发(软件Bug),读者可替换为WebRTC。

设置Gradio界面代码如代码12-11所示:
代码12-11

py 复制代码
import gradio as gr
with gr.Blocks() as app:
    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():
            otv = gr.Video(label="Processed Video", streaming=True, autoplay=True)
    video.upload(fn=stream_object_detection,
        inputs=[video, conf_threshold], outputs=[otv])

最终运行界面如图12-5所示:

图12-5

相关推荐
tangjunjun-owen8 个月前
RT-DETRv2 中的坐标回归机制深度解析:为什么用 `sigmoid(inv_sigmoid(ref) + delta)` 而不是除以图像尺寸?
人工智能·loss·rt-detrv2
shao9185168 个月前
Gradio全解11——Streaming:流式传输的视频应用(5)——RT-DETR:实时端到端检测模型
人工智能·nms·objects365·rt-detr·rt-detrv2·高效混合编码器·iou交并比
shao9185161 年前
Gradio全解20——Streaming:流式传输的多媒体应用(6)——RT-DETR模型构建视频流目标检测系统
人工智能·gradio·streaming·rt-detr·视频流目标检测·rt-detrv2