当前位置: 首页 > news >正文

CPU-GPU预处理流程的核心和优化关键 格式流转

重点:预处理流程的核心和优化关键 &格式流转
AVFrame (YUV) -> CPU Mat (BGR, HWC) -> GpuMat (BGR, HWC) [ (Kernel 1: BGR->RGB) -> (Kernel 2: HWC->CHW) ]-> TensorRT 推理。

2. GPU处理流程详解

项目的理想数据流如下,旨在最小化CPU-GPU数据拷贝,实现高效处理:

  1. CPU 解码: FFmpeg 在CPU上解码视频文件,输出 AVFrame
  2. 数据上传 (CPU -> GPU): avframe_to_gpumat 函数将 AVFrame 数据上传到GPU显存,创建 cv::cuda::GpuMat。YUV to BGR.
  3. GPU 预处理: preprocess_gpumat 函数在GPU上完成所有预处理,包括:
      • 尺寸调整 (隐式)(cv::cuda::resize)
    • 颜色空间转换 (BGR -> RGB)
      *归一化 (e.g., / 255.0) (GpuMat::convertTo)
      *数据布局转换 (HWC -> CHW)
  4. GPU 推理: TensorRTEngine::infer 方法接收预处理后的 GpuMat,其指针直接送入TensorRT引擎。整个神经网络的计算全程在GPU上进行。
  5. GPU 输出: 推理结果(前景蒙版)直接生成在GPU显存中,并由一个 GpuMat 管理。

从第2步开始到第5步结束,数据始终保留在GPU上,形成了一个高效的 GPU内处理闭环

4. 后续实施计划

为了使项目能够运行,计划采取以下步骤补全代码:

  1. 创建 VideoProcessor: 新建 video_processor.h/.cpp,封装整体处理逻辑,简化 main 函数。
  2. 实现 ffmpeg_handler.cpp: 完善视频帧的读取和解码功能。
  3. 实现 opencv_cuda_utils/gpu_utils.cpp: 编码实现 avframe_to_gpumatpreprocess_gpumat 的具体逻辑。
  4. 实现 tensorrt_engine.cpp: 完成TensorRT引擎的加载、配置及 infer 方法的实现。
  5. 重构 main.cpp: 使用 VideoProcessor 类来驱动整个视频处理流程。

FFmpegHandler模块实现解码视频帧

@src/ffmpeg_handler/ffmpeg_handler.cpp中函数AVFrame* FFmpegHandler::readAVFrame()内部实现:输入本地视频文件,逐帧读取一个本地视频文件,输出解码后的视频帧 (AVFrame),请重新调整ffmpeg_handler.cpp与ffmpeg_handler.h

重点:预处理流程的核心和优化关键 &格式流转

AVFrame (YUV) -> CPU Mat (BGR, HWC) -> GpuMat (BGR, HWC) [ (Kernel 1: BGR->RGB) -> (Kernel 2: HWC->CHW) ]-> TensorRT 推理。

内核融合 (Kernel Fusion) (最高效)

这正是您在之前问题中提到的优化思路的延伸。我们可以编写一个全能的自定义CUDA Kernel,将多个操作合并为一次执行。

这个自定义Kernel将一次性完成:

  • 尺寸调整 (隐式)
  • 颜色空间转换 (BGR -> RGB)
  • 归一化 (e.g., / 255.0)
  • 数据布局转换 (HWC -> CHW)

执行流程:

  1. 上传: cv::Mat (CPU) -> cv::cuda::GpuMat (GPU, BGR, HWC),这一步不变。
  2. 调用全能的自定义Kernel: launch_preprocess_kernel(gpu_bgr_hwc, trt_input_buffer, model_input_size);
    • 输入: 原始尺寸的GpuMat。
    • 输出: 最终的、符合TensorRT要求的CHW浮点型数据指针。
    • Kernel内部逻辑:
      • CUDA线程根据它要写入的目标CHW缓冲区的(c, h, w)位置,反向计算出应该从源HWC GpuMat的哪个(x, y)坐标去采样。这个“反向计算”过程本身就包含了尺寸调整的逻辑(例如,通过简单的线性插值)。
      • 从源GpuMat的(y, x)位置读取 B, G, R 三个值。
      • 在写入目标缓冲区时,直接进行通道交换和归一化。例如,要写入R通道 (c=0),就读取源的B值,然后计算 (float)B / 255.0f,最后写入目标位置。
      • 这样,仅用一次Kernel启动就完成了所有转换。
http://www.dtcms.com/a/389724.html

相关文章:

  • 混元开源之力:spring-ai-hunyuan 项目功能升级与实战体验
  • 基于开源AI大模型、AI智能名片与S2B2C商城小程序的社群入群仪式设计研究
  • HookConsumerWidget 深入理解
  • Django多数据库实战:Mysql从逻辑隔离到跨库外键问题的解决方案
  • SQL Server索引优化:从原理到实战的完整指南
  • 前端-Vue自定义指令
  • 深度学习调参核心:PyTorch学习率调整策略全解析(一)(附系列PPT关键要点)
  • 如何在保证质量的前提下,快速完成一份 PPT?
  • AssemblyScript 入门教程(3)AssemblyScript 项目搭建与实战入门
  • React 实战进阶视频教程
  • 运维安全08 - 日志检测和 tcpdump (抓包) 的介绍以及使用
  • 感烟火灾探测器工程量计算
  • 数学真题分类刷题(前两章)
  • 基于文本与声学特征的渐冻症言语障碍严重程度分类研究
  • 基于语音合成的数据增强在独立说话人构音障碍严重程度分类中的应用
  • vscode 设置
  • vscode关闭coplit功能
  • ICML 2025|GAPrompt:用于3D视觉模型的几何感知点云提示
  • OCCI使用
  • 如何在命令列将.brd转成.siw
  • 贪心算法应用:欧拉路径(Fleury算法)详解
  • 第13章 时间处理
  • Python 抓包工具有哪些,抓包失败怎么办?(Python 抓包工具清单 + 常见失败原因与逐步排查)
  • 数据库模式演进的利器:Alembic 深度解析
  • 用 JMeter 打通“异步入队 + 网关限流”的高并发压测实践
  • Linux服务器从零开始-服务器安装配置
  • Python第三节基本数据类型详解与使用指南
  • 【indextts2】之四:ubuntu24.04 经常跑满12G 显存、音色与录制关系很大
  • 【学习笔记】稳定币的技术原理与信任逻辑
  • 为 Elasticsearch Ruby Client 引入 ES|QL 查询生成器