☰
jetson-inference 图像处理指南:基于 CUDA 的图像格式转换与前后处理 API 详解
2026/9/25 2:13:05 网站建设 项目流程
  • 人工智能
  • 计算机视觉
  • 深度学习
  • 微调

【免费下载链接】jetson-inference

Hello AI World guide to deploying deep-learning inference networks and deep vision primitives with TensorRT and NVIDIA Jetson.

项目地址:https://gitcode.com/gh_mirrors/je/jetson-inference
点击查看免费下载

导读

本文是 jetson-inference 项目附录(docs/aux-image.md)的完整技术指南,系统讲解由 jetson-utils 库提供的、运行在 GPU 上的图像格式定义、内存分配与拷贝、Python 图像胶囊对象(cudaImage)以及与 Numpy / PyTorch / CuPy 等生态的零拷贝互操作,并逐一剖析颜色转换(cudaConvertColor)、缩放(cudaResize)、裁剪(cudaCrop)、归一化(cudaNormalize)、叠加(cudaOverlay)与绘制图形(cudaDraw)等 CUDA 图像处理例程。读完本文,你将能在 Jetson 平台上用 Python 或 C++ 直接操作 GPU 图像内存,为深度学习推理管线编写高效的前处理与后处理代码。

适用前提:本文涉及的jetson_utilsPython 模块与 CUDA 例程,均随 jetson-inference 一起构建安装;C++ 头文件位于jetson-utils子库中(cuda/cudaMappedMemory.h、cuda/cudaColorspace.h等)。视频采集与输出、图像加载保存的更多背景请先阅读 Camera Streaming and Multimedia 指南。

一、图像格式体系(Image Formats)

虽然 视频流接口 与 DNN 对象(如 imageNet、detectNet、segNet)都期望输入 RGB/RGBA 格式的图像,但 jetson-utils 针对传感器采集与底层 I/O 还定义了多种其他格式:

类别格式字符串imageFormat枚举值数据类型位深(每像素有效位数)
RGB/RGBArgb8IMAGE_RGB8uchar324
rgba8IMAGE_RGBA8uchar432
rgb32fIMAGE_RGB32Ffloat396
rgba32fIMAGE_RGBA32Ffloat4128
BGR/BGRAbgr8IMAGE_BGR8uchar324
bgra8IMAGE_BGRA8uchar432
bgr32fIMAGE_BGR32Ffloat396
bgra32fIMAGE_BGRA32Ffloat4128
YUV(4:2:2)yuyvIMAGE_YUYVuint816
yuy2IMAGE_YUY2uint816
yvyuIMAGE_YVYUuint816
uyvyIMAGE_UYVYuint816
YUV(4:2:0)i420IMAGE_I420uint812
yv12IMAGE_YV12uint812
nv12IMAGE_NV12uint812
Bayerbayer-bggrIMAGE_BAYER_BGGRuint88
bayer-gbrgIMAGE_BAYER_GBRGuint88
bayer-grbgIMAGE_BAYER_GRBGuint88
bayer-rggbIMAGE_BAYER_RGGBuint88
Grayscalegray8IMAGE_GRAY8uint88
gray32fIMAGE_GRAY32Ffloat32

要点说明:

  • YUV 格式的详细规范可参考 fourcc 标准(YV12/NV12 等常见于 H.264/HEVC 编解码流水线,YUYV/UYVY 常见于 V4L2 摄像头采集)。
  • C++ 注意:uchar3/uchar4/float3/float4这些向量类型只能用于 RGB/RGBA 格式。若你用这些类型表示 BGR/BGRA 数据,某些处理函数会把它误判为 RGB/RGBA,除非显式指定正确的 imageFormat 枚举。
  • 格式之间的转换请使用下文 颜色转换 的cudaConvertColor()。

二、GPU 内存分配(Image Allocation)

当需要为中间/输出图像(即处理过程中的工作内存)分配 GPU 显存时:

  • C++:使用cudaAllocMapped()(头文件jetson-utils/cudaMappedMemory.h)。
  • Python:使用jetson_utils.cudaImage对象或jetson_utils.cudaAllocMapped()。
  • 注意:videoSource输入流会自动分配自己的 GPU 内存并返回最新图像,因此采集场景无需自行分配。

由cudaAllocMapped()分配的内存位于CPU/GPU 共享内存空间(即 ZeroCopy 内存),CPU 与 GPU 均可直接访问,无需在两者之间执行内存拷贝。

同步要求:若 GPU 处理完成后想从 CPU 访问图像,必须先调用cudaDeviceSynchronize()等待 GPU 完成。C++ 中释放内存用cudaFreeHost();Python 中内存由垃圾回收器自动释放,也可用del显式释放。

Python 分配 / 同步 / 释放

from jetson_utils import cudaImage, cudaDeviceSynchronize # 分配一张 1920x1080 的 rgb8 图像 img = cudaImage(width=1920, height=1080, format='rgb8') # 在 GPU 上进行一些处理 ... # 等待 GPU 处理完成 cudaDeviceSynchronize() # Python 会自动释放内存,也可以用 'del' 显式释放 del img

C++ 分配 / 同步 / 释放

#include <jetson-utils/cudaMappedMemory.h> void* img = NULL; // 分配一张 1920x1080 的 rgb8 图像 if( !cudaAllocMapped(&img, 1920, 1080, IMAGE_RGB8) ) return false; // 内存错误 // 在 GPU 上进行一些处理 ... // 等待 GPU 处理完成 CUDA(cudaDeviceSynchronize()); // 释放内存 CUDA(cudaFreeHost(img));

C++ 类型化指针的简化写法

如果指针已声明为uchar3/uchar4/float3/float4类型,可省略显式的 imageFormat 枚举,与上面的分配在功能上等价:

uchar3* img = NULL; // 可以是 uchar3(rgb8)、uchar4(rgba8)、float3(rgb32f)、float4(rgba32f) if( !cudaAllocMapped(&img, 1920, 1080) ) return false;

注意:使用这些向量类型时,图像会被假定为对应的 RGB/RGBA 色彩空间;若实际存放的是 BGR/BGRA 数据,务必显式传入正确的图像格式。

三、图像拷贝(Copying Images)

cudaMemcpy()用于在同一格式、同一尺寸的图像之间拷贝内存。它是 CUDA 标准函数,Python 端jetson_utils也提供了等价版本:

Python

from jetson_utils import cudaMemcpy, cudaImage, loadImage # 加载图像并分配目标内存 img_a = loadImage("my_image.jpg") img_b = cudaImage(like=img_a) # 等价于显式指定 width, height, format # 拷贝图像(参数顺序:dst, src) cudaMemcpy(img_b, img_a) # 也可以使用快捷方式,返回一份副本 img_c = cudaMemcpy(img_a)

C++

#include <jetson-utils/cudaMappedMemory.h> #include <jetson-utils/imageIO.h> uchar3* img_a = NULL; uchar3* img_b = NULL; int width = 0; int height = 0; // 加载示例图像 if( !loadImage("my_image.jpg", &img_a, &width, &height) ) return false; // 加载错误 // 分配目标内存 if( !cudaAllocMapped(&img_b, width, height) ) return false; // 内存错误 // 拷贝图像(dst, src) if( CUDA_FAILED(cudaMemcpy(img_b, img_a, width * height * sizeof(uchar3), cudaMemcpyDeviceToDevice)) ) return false; // memcpy 错误

四、Python 图像胶囊对象(cudaImage)

在 Python 中分配图像,或用videoSource.Capture()从视频流采集图像时,返回的是一个自包含的内存胶囊对象(类型jetson_utils.cudaImage),可在不拷贝底层内存的情况下随处传递。

cudaImage对象具有以下成员:

<cudaImage object> .ptr # 内存地址(一般不直接使用) .size # 字节大小 .shape # (height, width, channels) 元组 .width # 像素宽度 .height # 像素高度 .channels # 颜色通道数 .format # 格式字符串 .mapped # 是否为 ZeroCopy 内存 .timestamp # 时间戳(纳秒)

因此可以直接写img.width、img.height等来访问图像属性。

4.1 数组接口总览

为实现与其他库的零拷贝互操作,可从 Python 通过多种方式访问cudaImage内存:

  • 直接从 Python 下标索引图像(4.2 节)
  • Numpy__array__接口、cudaToNumpy()/cudaFromNumpy()(4.3 节)
  • Numba__cuda_array_interface__(适用于 PyTorch、CuPy、PyCUDA、VPI 等,4.4 节)
  • 直接共享内存指针.ptr(4.5 节)

这些机制的核心设计是:底层内存被映射并与其他库共享,从而避免内存拷贝。

4.2 从 Python 直接访问像素数据

cudaImage支持下标索引,可直接在 CPU 上读写像素:

for y in range(img.height): for x in range(img.width): pixel = img[y,x] # 返回元组,RGB 格式为 (r,g,b),RGBA 格式为 (r,g,b,a) img[y,x] = pixel # 用元组设置像素(元组长度必须匹配通道数)

注意:下标索引仅在mapped=True(默认值)分配的cudaImage上可用;否则数据无法从 CPU 访问,会抛出异常。

索引元组支持以下形式:

  • img[y,x]:注意(y,x)的顺序,与 Numpy 一致;
  • img[y,x,channel]:只访问某个通道(0 红、1 绿、2 蓝、3 透明);
  • img[y*img.width+x]:扁平一维索引,访问该像素的全部通道。

性能提醒:虽然支持逐像素下标访问,但对大图像逐像素索引会显著拖慢应用,不建议在 Python 中这样做;在 GPU 实现不可用的情况下,更好的选择是改用 Numpy。

4.3 与 Numpy 数组互操作

cudaImage实现了 Numpy 的__array__接口协议,因此可以直接用在很多 Numpy 函数中,无需来回拷贝:

import numpy as np from jetson_utils import cudaImage cuda_img = cudaImage(320, 240, 'rgb32f') array = np.ones(cuda_img.shape, np.float32) print(np.add(cuda_img, array))

注意:Numpy 运行在 CPU 上,因此cudaImage应以mapped=True(默认)分配,使其内存对 CPU/GPU 同时可访问。Numpy 对它的任何修改都会反映到底层cudaImage内存中。

需要留意的是:应使用独立的 Numpy 例程(如numpy.mean(array))而非 ndarray 类方法(如array.mean())。因为cudaImage只导出__array__接口用于访问内存,并未实现 Numpy 的类方法。要使用全套 ndarray 方法,见下面的cudaToNumpy()。

4.3.1 转换为 Numpy 数组(cudaToNumpy)

调用cudaToNumpy()可显式获得一个映射到cudaImage的numpy.ndarray:

import numpy as np from jetson_utils import cudaImage, cudaToNumpy cuda_img = cudaImage(320, 240, 'rgb32f') array = cudaToNumpy(cuda_img) print(array.mean())

底层内存不会被拷贝,Numpy 直接访问它——因此若通过 Numpy 就地修改数据,底层cudaImage也会同步变化。

与 OpenCV 联用时注意:OpenCV 期望 BGR 色彩空间,因此应先调用cudaConvertColor()把图像从 RGB 转为 BGR。

4.3.2 从 Numpy 数组转入(cudaFromNumpy)

若你有一个 Numpy ndarray(例如由 OpenCV 提供),它只能从 CPU 访问。可用cudaFromNumpy()把它拷贝到 GPU(进入共享的 CPU/GPU 映射内存):

import numpy as np from jetson_utils import cudaFromNumpy array = np.zeros((240, 320, 3), dtype=np.float32) cuda_img = cudaFromNumpy(array)

同理,OpenCV 图像是 BGR 色彩空间,之后应调用cudaConvertColor()从 BGR 转为 RGB。

仓库内的相关示例:segnet 后处理工具 python/examples/segnet_utils.py 中就通过cudaAllocMapped()分配 overlay/mask 缓冲、并用cudaToNumpy()把gray8类别掩膜映射为 Numpy 数组供逐类统计使用;python/examples/README.md 也专门提示了 numpy 互操作示例的用法。

4.4 CUDA 数组接口

cudaImage还实现了 Numba 的__cuda_array_interface__,为使用 GPU 内存的库(PyTorch、CuPy、PyCUDA、VPI 等)提供零拷贝互操作。与 Numpy__array__类似,它可透明地把cudaImage传入 Numba/PyTorch/CuPy/PyCUDA 函数,内存被共享,无拷贝与额外开销。

以 CuPy 为例:

import cupy from jetson_utils import cudaImage cuda_img = cudaImage(640, 480, 'rgb8') cupy_array = cupy.ones((480, 640, 3)) print(cupy.add(cuda_img, cupy_array))

cudaImage同时也实现了 PyCUDA 的gpudata接口,可像 PyCUDAGPUArray一样使用。

与 PyTorch 张量共享内存:

import torch from jetson_utils import cudaImage # 分配 cuda 内存 cuda_img = cudaImage(640, 480, 'rgb8') # 通过 __cuda_array_interface__ 映射为 torch 张量 tensor = torch.as_tensor(cuda_img, device='cuda')

这使cudaImage的 GPU 内存可被 PyTorch GPU 张量直接使用而不发生拷贝——PyTorch 对张量内容的任何修改都会反映到cudaImage中。注意必须指定device='cuda',PyTorch 才会执行零拷贝映射;可通过比对cudaImage与 PyTorch 张量的数据指针是否一致来验证。

4.5 共享内存指针

对不支持上述接口的库,cudaImage通过.ptr属性暴露底层内存的原始数据指针,可在不拷贝的情况下导入其他数据结构。反过来,cudaImage构造器也接受ptr参数指向外部分配的缓冲区——此时cudaImage共享该内存而不是自行分配。

把已有的 PyTorch GPU 张量映射到cudaImage:

import torch from jetson_utils import cudaImage # 分配 NCHW 布局(颜色跨步)的 GPU 张量 tensor = torch.rand(1, 3, 480, 640, dtype=torch.float32, device='cuda') # 转置为 NHWC 布局(颜色交织) tensor = tensor.to(memory_format=torch.channels_last) # 或 tensor.permute(0, 3, 2, 1) # 用同一底层内存映射为 cudaImage(任何修改都会反映到 PyTorch 张量) cuda_img = cudaImage(ptr=tensor.data_ptr(), width=tensor.shape[-1], height=tensor.shape[-2], format='rgb32f')

注意:务必区分 NCHW 通道布局(颜色跨步)与 NHWC 布局(颜色交织),cudaImage期望的是后者。

当外部指针被映射进cudaImage时,默认情况下cudaImage不取得底层内存的所有权,释放时不会 free 它(如需改变,可在构造器中设置freeOnDelete=True)。库之间的同步应由使用者自行处理(例如避免 PyTorch 与cudaImage同时访问同一内存)。

五、颜色转换(Color Conversion)

cudaConvertColor()(头文件jetson-utils/cudaColorspace.h)用 GPU 在图像格式与色彩空间之间进行转换。例如:RGB 转 BGR(或反之)、YUV 转 RGB、RGB 转灰度等;也可以改变数据类型与通道数(如 RGB8 转 RGBA32F)。可转换的格式详见 图像格式体系。

转换限制

  • YUV 格式不支持 BGR/BGRA 与灰度(仅支持 RGB/RGBA);
  • YUV 的 NV12、YUYV、YVYU、UYVY 只能转为RGB/RGBA(不能反向);
  • Bayer 格式只能转为 RGB8(uchar3)与 RGBA8(uchar4)。

Python 示例

import jetson_utils # 加载输入图像(默认格式 rgb8,也可指定 rgba8/rgb32f/rgba32f) imgInput = jetson_utils.loadImage('my_image.jpg', format='rgb8') # 按输入同尺寸分配 rgba32f 输出 imgOutput = jetson_utils.cudaAllocMapped(width=imgInput.width, height=imgInput.height, format='rgba32f') # 从 rgb8 转为 rgba32f(转换格式取自图像胶囊对象) jetson_utils.cudaConvertColor(imgInput, imgOutput)

C++ 示例

#include <jetson-utils/cudaColorspace.h> #include <jetson-utils/cudaMappedMemory.h> #include <jetson-utils/imageIO.h> uchar3* imgInput = NULL; // 输入 rgb8(uchar3) float4* imgOutput = NULL; // 输出 rgba32f(float4) int width = 0; int height = 0; // 以 rgb8(uchar3)加载图像 if( !loadImage("my_image.jpg", &imgInput, &width, &height) ) return false; // 按同尺寸分配 rgba32f(float4)输出 if( !cudaAllocMapped(&imgOutput, width, height) ) return false; // 从 rgb8 转为 rgba32f if( CUDA_FAILED(cudaConvertColor(imgInput, IMAGE_RGB8, imgOutput, IMAGE_RGBA32F, width, height)) ) return false; // 发生错误或转换不受支持

从源码结构看,cudaConvertColor与cudaResize、cudaNormalize等例程共同组成了 DNN 前处理的基础设施——例如 c/imageNet.cpp 的imageNet::PreProcess()在把图像送入 TensorRT 引擎前,就通过归一化/通道变换把输入图像转换到网络期望的张量范围与布局,足见这些 CUDA 例程在推理流水线中的枢纽地位。

六、缩放(Resizing)

cudaResize()(头文件jetson-utils/cudaResize.h)用 GPU 将图像缩放(可降采样或升采样)到不同尺寸。以下示例把图像缩小一半:

Python

import jetson_utils # 加载输入图像 imgInput = jetson_utils.loadImage('my_image.jpg') # 分配输入一半尺寸的输出 imgOutput = jetson_utils.cudaAllocMapped(width=imgInput.width * 0.5, height=imgInput.height * 0.5, format=imgInput.format) # 缩放图像(尺寸取自图像胶囊对象) jetson_utils.cudaResize(imgInput, imgOutput)

C++

#include <jetson-utils/cudaResize.h> #include <jetson-utils/cudaMappedMemory.h> #include <jetson-utils/imageIO.h> // 加载输入图像 uchar3* imgInput = NULL; int inputWidth = 0; int inputHeight = 0; if( !loadImage("my_image.jpg", &imgInput, &inputWidth, &inputHeight) ) return false; // 分配输入一半尺寸的输出 uchar3* imgOutput = NULL; int outputWidth = inputWidth * 0.5f; int outputHeight = inputHeight * 0.5f; if( !cudaAllocMapped(&imgOutput, outputWidth, outputHeight) ) return false; // 缩放图像 if( CUDA_FAILED(cudaResize(imgInput, inputWidth, inputHeight, imgOutput, outputWidth, outputHeight)) ) return false;

仓库实际用例:换背景示例 python/examples/backgroundnet.py 中先cudaResize()把替换背景图缩放到与输入一致,再cudaMemcpy()拷贝进输出缓冲,最后cudaOverlay()合成,完整串起了缩放+拷贝+叠加三个 CUDA 例程。

七、裁剪(Cropping)

cudaCrop()(头文件jetson-utils/cudaCrop.h)用 GPU 把图像裁剪到指定的兴趣区域(ROI)。以下示例围绕图像中心裁剪一半区域。

ROI 矩形的坐标形式为(left, top, right, bottom)。

Python

import jetson_utils # 加载输入图像 imgInput = jetson_utils.loadImage('my_image.jpg') # 计算边框像素量(围绕中心裁剪一半) crop_factor = 0.5 crop_border = ((1.0 - crop_factor) * 0.5 * imgInput.width, (1.0 - crop_factor) * 0.5 * imgInput.height) # 计算 ROI 为 (left, top, right, bottom) crop_roi = (crop_border[0], crop_border[1], imgInput.width - crop_border[0], imgInput.height - crop_border[1]) # 分配裁剪尺寸的输出图像 imgOutput = jetson_utils.cudaAllocMapped(width=imgInput.width * crop_factor, height=imgInput.height * crop_factor, format=imgInput.format) # 裁剪到 ROI jetson_utils.cudaCrop(imgInput, imgOutput, crop_roi)

C++

#include <jetson-utils/cudaCrop.h> #include <jetson-utils/cudaMappedMemory.h> #include <jetson-utils/imageIO.h> // 加载输入图像 uchar3* imgInput = NULL; int inputWidth = 0; int inputHeight = 0; if( !loadImage("my_image.jpg", &imgInput, &inputWidth, &inputHeight) ) return false; // 计算边框像素量(围绕中心裁剪一半) const float crop_factor = 0.5; const int2 crop_border = make_int2((1.0f - crop_factor) * 0.5f * inputWidth, (1.0f - crop_factor) * 0.5f * inputHeight); // 计算 ROI 为 (left, top, right, bottom) const int4 crop_roi = make_int4(crop_border.x, crop_border.y, inputWidth - crop_border.x, inputHeight - crop_border.y); // 分配输入一半尺寸的输出 uchar3* imgOutput = NULL; if( !cudaAllocMapped(&imgOutput, inputWidth * crop_factor, inputHeight * crop_factor) ) return false; // 裁剪图像 if( CUDA_FAILED(cudaCrop(imgInput, imgOutput, crop_roi, inputWidth, inputHeight)) ) return false;

仓库实际用例:快照裁剪示例 python/examples/detectnet-snap.py 先用cudaAllocMapped()按检测框 ROI 的宽高分配快照缓冲,再cudaCrop()裁出目标区域、cudaDeviceSynchronize()同步后saveImage()落盘,演示了“检测框 ROI → GPU 裁剪 → 保存”的完整链路。

八、归一化(Normalization)

cudaNormalize()(头文件jetson-utils/cudaNormalize.h)用 GPU 改变像素强度范围。例如把[0,1]范围的像素值转为[0,255];像素值的另一个常见范围是[-1,1]。

注意:jetson-inference 与 jetson-utils 中的其他函数都期望像素值在[0,255]范围,因此通常不需要用cudaNormalize();但当你在处理来自其他来源/去向的数据时它就会派上用场。

以下示例把图像从[0,255]归一化到[0,1]:

Python

import jetson_utils # 加载输入图像(像素范围为 0-255) imgInput = jetson_utils.loadImage('my_image.jpg') # 分配与输入同尺寸的输出 imgOutput = jetson_utils.cudaAllocMapped(width=imgInput.width, height=imgInput.height, format=imgInput.format) # 把图像从 [0,255] 归一化到 [0,1] jetson_utils.cudaNormalize(imgInput, (0,255), imgOutput, (0,1))

C++

#include <jetson-utils/cudaNormalize.h> #include <jetson-utils/cudaMappedMemory.h> #include <jetson-utils/imageIO.h> uchar3* imgInput = NULL; uchar3* imgOutput = NULL; int width = 0; int height = 0; // 加载输入图像(像素范围为 0-255) if( !loadImage("my_image.jpg", &imgInput, &width, &height) ) return false; // 分配与输入同尺寸的输出 if( !cudaAllocMapped(&imgOutput, width, height) ) return false; // 把图像从 [0,255] 归一化到 [0,1] CUDA(cudaNormalize(imgInput, make_float2(0,255), imgOutput, make_float2(0,1), width, height));

九、叠加(Overlay)

cudaOverlay()(头文件jetson-utils/cudaOverlay.h)用 GPU 把一张输入图像合成到输出图像的指定位置。叠加操作通常按顺序调用,从而把多张图像拼成一张合成图。

以下示例加载两张图像并把它们并排合成到一张输出图中:

Python

import jetson_utils # 加载输入图像 imgInputA = jetson_utils.loadImage('my_image_a.jpg') imgInputB = jetson_utils.loadImage('my_image_b.jpg') # 分配能并排容纳两张输入的输出 imgOutput = jetson_utils.cudaAllocMapped(width=imgInputA.width + imgInputB.width, height=max(imgInputA.height, imgInputB.height), format=imgInputA.format) # 合成两张图像(最后两个参数是输出图像中的 x,y 坐标) jetson_utils.cudaOverlay(imgInputA, imgOutput, 0, 0) jetson_utils.cudaOverlay(imgInputB, imgOutput, imgInputA.width, 0)

C++

#include <jetson-utils/cudaOverlay.h> #include <jetson-utils/cudaMappedMemory.h> #include <jetson-utils/imageIO.h> #include <algorithm> // for std::max() uchar3* imgInputA = NULL; uchar3* imgInputB = NULL; uchar3* imgOutput = NULL; int2 dimsA = make_int2(0,0); int2 dimsB = make_int2(0,0); // 加载输入图像 if( !loadImage("my_image_a.jpg", &imgInputA, &dimsA.x, &dimsA.y) ) return false; if( !loadImage("my_image_b.jpg", &imgInputB, &dimsB.x, &dimsB.y) ) return false; // 分配能并排容纳两张输入的输出 const int2 dimsOutput = make_int2(dimsA.x + dimsB.x, std::max(dimsA.y, dimsB.y)); if( !cudaAllocMapped(&imgOutput, dimsOutput.x, dimsOutput.y) ) return false; // 合成两张图像(最后两个参数是输出图像中的 x,y 坐标) CUDA(cudaOverlay(imgInputA, dimsA, imgOutput, dimsOutput, 0, 0)); CUDA(cudaOverlay(imgInputB, dimsB, imgOutput, dimsOutput, dimsA.x, 0));

仓库实际用例:cudaOverlay是推理可视化中最常用的合成原语——python/examples/segnet.py 把类别叠加层与类别掩膜并排合成到复合图;examples/segnet/segnet.cpp 与 examples/depthnet/depthnet.cpp 在 C++ 端把原始输入与深度/掩膜结果并排拼合,便于直接观察网络输出效果。

十、绘制图形(Drawing Shapes)

jetson-utils/cudaDraw.h定义了若干绘制基本图形(圆、线、矩形)的函数。

Python

# 加载输入图像 input = jetson_utils.loadImage("my_image.jpg") # cudaDrawCircle(input, (cx,cy), radius, (r,g,b,a), output=None) jetson_utils.cudaDrawCircle(input, (50,50), 25, (0,255,127,200)) # cudaDrawRect(input, (left,top,right,bottom), (r,g,b,a), output=None) jetson_utils.cudaDrawRect(input, (200,25,350,250), (255,127,0,200)) # cudaDrawLine(input, (x1,y1), (x2,y2), (r,g,b,a), line_width, output=None) jetson_utils.cudaDrawLine(input, (25,150), (325,15), (255,0,200,200), 10)

注意:若不指定可选的output图像,操作将在input图像上就地执行。

C++

#include <jetson-utils/cudaDraw.h> #include <jetson-utils/imageIO.h> uchar3* img = NULL; int width = 0; int height = 0; // 加载示例图像 if( !loadImage("my_image.jpg", &img, &width, &height) ) return false; // 加载错误 // 具体定义见 cudaDraw.h CUDA(cudaDrawCircle(img, width, height, 50, 50, 25, make_float4(0,255,127,200))); CUDA(cudaDrawRect(img, width, height, 200, 25, 350, 250, make_float4(255,127,0,200))); CUDA(cudaDrawLine(img, width, height, 25, 150, 325, 15, make_float4(255,0,200,200), 10));

十一、在推理管线中组合使用

把上述 API 串起来,就能搭建完整的“采集/加载 → 预处理 → 推理 → 可视化/保存”流水线。仓库中已有多条可供直接参照的完整链路:

  • 换背景流水线python/examples/backgroundnet.py:cudaAllocMapped分配缓冲 →cudaResize缩放替换背景 →cudaMemcpy拷贝 →cudaOverlay合成前景与背景;
  • 检测快照流水线python/examples/detectnet-snap.py:cudaAllocMapped按 ROI 分配 →cudaCrop裁出目标 →cudaDeviceSynchronize同步 →saveImage保存;
  • 分割可视化流水线python/examples/segnet.py 与 python/examples/depthnet.py:cudaOverlay并排合成输入/掩膜/深度图,cudaDeviceSynchronize保证帧同步。

所有这些例程都遵循同一模式:分配共享内存 → GPU 处理 → 同步 → 释放。把握好 ZeroCopy 内存的特性(CPU/GPU 直接共享、免拷贝但需同步),再配合cudaImage与 Numpy/PyTorch 等生态的零拷贝接口,即可在 Jetson 上写出高效、可维护的图像处理与推理前后处理代码。相关示例与测试可进一步参考 python/examples、examples 以及 jetson-utils 子库中的cuda/头文件。

延伸阅读

  • Camera Streaming and Multimedia:视频采集/输出、图像加载保存的前置知识;
  • jetson-inference 主指南:Hello AI World 推理部署整体流程;
  • Deep Learning Nodes for ROS/ROS2(ROS 目录 ros):把图像处理与推理接入 ROS 生态。
  • 人工智能
  • 计算机视觉
  • 深度学习
  • 微调

【免费下载链接】jetson-inference

Hello AI World guide to deploying deep-learning inference networks and deep vision primitives with TensorRT and NVIDIA Jetson.

项目地址:https://gitcode.com/gh_mirrors/je/jetson-inference
点击查看免费下载

相关推荐

上一篇:终极指南:如何使用虎符台全面战争MOD管理器轻松管理游戏模组
下一篇:思源黑体TTF字体全方位应用指南(2024最新版)

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询