2. 使用CUDA加速的相机图像采集与显示
任务目标
在Jetson平台上通过CSI接口采集相机图像,利用CUDA对图像进行灰度化与边缘检测预处理,并将处理结果实时显示。本案例聚焦于采集→GPU预处理→显示的完整闭环,不涉及相机标定或高级视觉算法。
环境依赖
- 硬件:Jetson Nano/Xavier/Orin系列开发板,CSI相机(如IMX219)
- 软件:JetPack 4.6+(含CUDA 10.2+)、OpenCV 4.x(预编译版本已支持CUDA)、GStreamer
- 验证CUDA可用:
nvcc --version及python3 -c "import cv2; print(cv2.getBuildInformation())"中应包含CUDA支持
关键完整代码
以下代码使用Python + OpenCV的GStreamer后端从CSI相机采集帧,将帧上传至GPU,在GPU上完成灰度化和Canny边缘检测,然后下载回CPU并显示。核心加速逻辑由 cv2.cuda 模块实现。
import cv2
import numpy as np
# CSI相机GStreamer管道(适用于IMX219,30fps 1280x720)
GST_STR = (
"nvarguscamerasrc ! "
"video/x-raw(memory:NVMM), width=1280, height=720, format=NV12, framerate=30/1 ! "
"nvvidconv flip-method=2 ! "
"video/x-raw, format=BGRx ! "
"videoconvert ! video/x-raw, format=BGR ! appsink"
)
def process_frame_gpu(frame_bgr):
"""将BGR帧上传GPU,执行灰度化+Canny,返回处理后的CPU图像"""
# 上传到GPU
gpu_frame = cv2.cuda_GpuMat()
gpu_frame.upload(frame_bgr)
# 灰度化(GPU)
gpu_gray = cv2.cuda.cvtColor(gpu_frame, cv2.COLOR_BGR2GRAY)
# 高斯模糊降噪(GPU)
gpu_blur = cv2.cuda.GaussianBlur(gpu_gray, (5, 5), 1.0)
# Canny边缘检测(GPU)
gpu_edges = cv2.cuda.Canny(gpu_blur, 50, 150)
# 下载回CPU用于显示
edges_cpu = gpu_edges.download()
return edges_cpu
def main():
cap = cv2.VideoCapture(GST_STR, cv2.CAP_GSTREAMER)
if not cap.isOpened():
raise RuntimeError("无法打开CSI相机,请检查GStreamer管道与相机连接")
# 预热CUDA上下文
dummy = np.zeros((720, 1280, 3), dtype=np.uint8)
process_frame_gpu(dummy)
print("开始实时采集与CUDA加速处理,按 'q' 退出")
while True:
ret, frame = cap.read()
if not ret:
print("读取帧失败")
break
# GPU加速处理
edges = process_frame_gpu(frame)
# 拼接原图与边缘图并显示
combined = np.hstack((frame, cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)))
cv2.imshow("CSI Camera | CUDA Canny Edge", combined)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
运行方式
python3 csi_cuda_display.py
验证方法与通过条件
- 功能验证:程序启动后出现实时画面窗口,左侧为原始彩色图像,右侧为边缘检测结果(白线黑底)。移动相机视野中的物体,边缘轮廓应实时跟随变化,无明显延迟感。
- CUDA加速验证:在
process_frame_gpu函数内添加计时(time.time()),单帧GPU处理耗时(灰度+模糊+Canny)应小于10ms(Jetson Nano)或5ms(Xavier/Orin)。若耗时异常高,检查是否误用CPU版本函数。 - 退出机制:按键盘
q键程序正常退出,无报错。
常见问题
- 相机无法打开:确认CSI排线连接牢固,执行
ls /dev/video*查看是否存在video设备;尝试将flip-method=2改为0/1/3调整方向。 - CUDA函数不存在:若提示
cv2.cuda无Canny属性,说明OpenCV版本CUDA支持不完整,需重新编译OpenCV并开启WITH_CUDA=ON。 - 显示延迟高:
imshow本身为CPU操作,若需更低延迟可将显示部分也迁移至GPU(使用OpenGL互操作),但本案例范围不涉及。
预期输出示例:程序运行后窗口标题为 "CSI Camera | CUDA Canny Edge",左侧显示相机实时彩色画面,右侧显示对应的边缘二值图。按q键退出后终端无报错信息。