CSI单目及双目摄像头ROS2模块,适用于Jetson等ARM平台。主要用于ROS2中图像节点发布,使其能够像使用USB_CAM一样方便,提供单双目原始图像、压缩图像和深度图像(BM、SGBM算法),支持相机标定和校准。已经完成了docker版本更新,可以在ROS2 Humble版本下使用CSI双目摄像头,屏蔽主机环境问题导致的GStreamer版本冲突问题。
Note
当前实现参考了v4l2_camera
ros2 run v4l2_camera v4l2_camera_node --ros-args -p video_device:="/dev/video0" -p image_size:=[1280,720]似乎v4l2_camera对于CSI设备的支持不是很友好,为了能屏蔽主机版本冲突引起的CSI摄像头调起失败问题,于是我写了这个项目。
在utils工具包中,我实现了棋盘格打印、双目相机校准,可以自行选用。
在使用CSI摄像头前,请确认CSI摄像头已连接好,且图像显示正常。
# 查看当前摄像头设备
ll /dev/video*如下所示,说明系统中已经连接好了两个摄像头。
crw-rw----+ 1 root video 81, 0 Nov 22 05:10 /dev/video0
crw-rw----+ 1 root video 81, 4 Nov 22 05:10 /dev/video1Note
CSI摄像头连接不是很稳定,即便没有任何物理碰触,也有可能重开机后找不到设备。 如果发现程序突然打不开摄像头,可以先看看是不是系统里找不到摄像头了。
使用v4l2-ctl命令查看摄像头设备信息,如查看/dev/video0
# 查看简要信息
v4l2-ctl --device /dev/video0 --info
# 查看全部信息
v4l2-ctl --device /dev/video0 --all以下是使用v4l2-ctl --device /dev/video0 --info命令查看的设备简要信息,说明这是一个imx219芯片的CSI摄像头设备。
Driver Info:
Driver name : tegra-video
Card type : vi-output, imx219 10-0010
Bus info : platform:tegra-capture-vi:2
Driver version : 5.10.104
Capabilities : 0x84200001
Video Capture
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04200001
Video Capture
Streaming
Extended Pix Format
Media Driver Info:
Driver name : tegra-camrtc-ca
Model : NVIDIA Tegra Video Input Device
Serial :
Bus info :
Media version : 5.10.104
Hardware revision: 0x00000003 (3)
Driver version : 5.10.104
Interface Info:
ID : 0x0300001b
Type : V4L Video
Entity Info:
ID : 0x00000019 (25)
Name : vi-output, imx219 10-0010
Function : V4L2 I/O
Pad 0x0100001a : 0: Sink
Link 0x0200001f: from remote pad 0x1000006 of entity '13e40000.host1x:nvcsi@15a00000-': Data, EnabledTip
如果没有该工具,可通过以下命令安装:
sudo apt install v4l-utils 完成上述设备检测后,可以使用nvgstcapture-1.0命令调取摄像头图像。
# 开启第一摄像头
DISPLAY=:0.0 nvgstcapture-1.0 --sensor-id=0 # 开启第二摄像头
DISPLAY=:0.0 nvgstcapture-1.0 --sensor-id=1 部分CSI摄像头存在偏色问题,以下是imx219芯片CSI摄像头解决办法。
wget http://www.waveshare.net/w/upload/e/eb/Camera_overrides.tar.gz
tar zxvf Camera_overrides.tar.gz
sudo cp camera_overrides.isp /var/nvidia/nvcam/settings/
sudo chmod 664 /var/nvidia/nvcam/settings/camera_overrides.isp
sudo chown root:root /var/nvidia/nvcam/settings/camera_overrides.isp请确保在进行以下工作前已经安装好了ROS2以及相应的包,这里使用了ROS2的Foxy版本。
创建ros2工程目录,如~/ros_ws,用户可自行指定。
mkdir -p ~/ros_ws/src将工程下载到~/ros_ws/src目录下,并进行编译。
cd ~/ros_ws/src
git clone https://github.com/snowolf-zlex/CSI-Camera.git .
cd ~/ros_ws
rm -rf build install && colcon build --packages-select csi_cam_service如果编译出现异常情况,可以试试如下命令。
cd ~/ros_ws
rm -rf build install && colcon build --symlink-install --packages-select csi_cam_service加载项目环境:
cd ~/ros_ws
source install/setup.bash Tip
也可以修改~/.bashrc文件:
echo "source ~/ros_ws/install/setup.bash“ >> ~/.bashrcCSI单目摄像头节点共有3个图像话题:
- /mono_cam/image_raw: 原始图像
- /mono_cam/image_compressed: 压缩图像
- /mono_cam/camera_info: 摄像头设备信息
启动CSI单目摄像头,默认参数:
- video_device_id:=0
- image_size:=[640,480]
- fps:=30
- calibration_file_path:=? 支持通过外部相机标定文件校准镜头
ros2 run csi_cam_service mono_cam_node通过video_device_id参数指定单目摄像头设备ID,如使用/dev/video1。
ros2 run csi_cam_service mono_cam_node --ros-args -p video_device_id:=1这时就可以通过/mono_cam/image_raw访问到该摄像头数据,可以通过rviz2来查看图像。
CSI双目摄像头节点,共有3个图像话题:
- /stereo_cam/image_left_raw:默认
/dev/video0设备图像 - /stereo_cam/image_right_raw:默认
/dev/video1设备图像 - /stereo_cam/image_combine_raw:横向整合两个图像
- /stereo_cam/image_compressed:压缩图像(左侧摄像头)
- /stereo_cam/image_compressed_depth:压缩及深度图像
- /stereo_cam/camera_info:设备信息(左侧摄像头)
默认参数:
- video_device_id:=[0,1]
- image_size:=[640,480]
- fps:=30
- calibration_file_path:=[,] 支持通过外部相机标定文件校准镜头
- algorithm_type:=bm 提供深度算法支持,默认BM算法,还可以选择SGBM
ros2 run csi_cam_service stereo_cam_node 通过video_device_id参数指定双目摄像头设备ID,如,使用/dev/video1作为/stereo_cam/image_left,使用/dev/video0作为/stereo_cam/image_right。
Caution
video_device_id必须以成对数组出现,且不能有空格。
ros2 run csi_cam_service stereo_cam_node --ros-args -p video_device_id:=[1,0]这里提供了launch运行方式,将使用内置的相机标定文件(config中)进行校准,以便实现深度图像。
ros2 launch csi_cam_service stereo_cam.launch.py 通过以下命令可查看图像:
ros2 run rqt_image_view rqt_image_view使用BM算法默认参数获得深度图像(比耶),参数有待优化:
支持通过Docker部署并启动CSI双目摄像头深度测距环境,完全摆脱了主机软件包版本冲突导致的CSI无法正常调起的问题。
在根目录下,使用以下命令完成镜像构建:
./build.sh可以在docker容器中启动该项目,并在rviz2中订阅CSI双目摄像头话题数据。
由于CSI使用的是GStreamer,会有内存分配问题,如下所示。
Warning
(python3:6344): GStreamer-WARNING **: 11:52:06.411: Failed to load plugin '/usr/lib/aarch64-linux-gnu/gstreamer-1.0/libgstnvarguscamerasrc.so': /lib/aarch64-linux-gnu/libGLdispatch.so.0: cannot allocate memory in static TLS block
(python3:6344): GStreamer-WARNING **: 11:52:06.415: Failed to load plugin '/usr/lib/aarch64-linux-gnu/gstreamer-1.0/libgstnvvidconv.so': /lib/aarch64-linux-gnu/libGLdispatch.so.0: cannot allocate memory in static TLS block
修改~/.bashrc文件,使其预加载:
# 提前将库加载到内存
export LD_PRELOAD=/lib/aarch64-linux-gnu/libGLdispatch.so.0完成上述工作后,可以使用camera_calibration来做相机标定。
Important
这里使用了7x10 20mm的棋盘格标定盘。
- 实际上使用的是棋盘格内角,也就是6x9,这里很容易写错参数。
- 实际打印出来的棋盘格,由于打印机设备、纸张材料等因素干扰,实际上可能不是标定的尺寸,需要根据实际情况微调参数。
执行camera_calibration命令,来做单目相机标定。
# --approximate 0.1: 指定标定节点的时间间隔(以秒为单位),用于控制相邻帧之间的时间间隔。在这个命令中,标定节点将会尝试以0.1秒的间隔处理图像帧。
# --size 6x9: 棋盘格的大小。在这个命令中,棋盘格的大小为6行x9列。
# --square 0.020: 棋盘格每个方格的大小(以米为单位)。在这个命令中,每个方格的大小为0.020米。
# image:=/mono_cam/image_raw: 这里使用了单目相机节点和图像话题
ros2 run camera_calibration cameracalibrator --approximate 0.1 --size 6x9 --square 0.020 \
--ros-args --remap image:=/mono_cam/image_raw \
--ros-args --remap camera:=/custom_camera单目相机标定过程:
下面执行camera_calibration命令做双目相机标定。
# 这里使用了双目相机节点和图像话题
# left:=/stereo_cam/image_left_raw
# right:=/stereo_cam/image_right_raw
ros2 run camera_calibration cameracalibrator --approximate 0.1 --size 6x9 --square 0.020 \
--ros-args --remap left:=/stereo_cam/image_left_raw \
--ros-args --remap right:=/stereo_cam/image_right_raw \
--ros-args --remap left_camera:=/custom_camera/image_left \
--ros-args --remap right_camera:=/custom_camera/image_right 双目摄像头标定:
完成标定后,提取标定文件,并移动到需要的位置。
# 提取标定参数文件
mkdir -p ~/calibration
cd ~/calibration
mv /tmp/calibrationdata.tar.gz .
# 解压缩
tar vxzf calibrationdata.tar.gz
#这里能找到left.yaml 和 right.yaml两个文件,将其移动到需要位置即可
ll *.yaml本项目包含以下实用工具:
基于 NVIDIA Jetson 平台的摄像头采集、RTSP 推流、相机标定一体化工具包(独立于 ROS2 使用)。
功能特性:
- 多源视频输入(CSI/USB 摄像头、RTSP 流、视频文件)
- RTSP 推流输出
- 多摄像头布局显示
- 单目/双目相机标定
- 棋盘格标定盘生成
- Jupyter Notebook 交互式示例
项目结构:
utils/
├── __init__.py # 包初始化
├── toolkit.py # 命令行工具入口
├── camera.py # 摄像头核心模块
├── rtsp.py # RTSP 推流模块
├── calibrate.py # 相机标定模块
└── examples/ # Jupyter Notebook 示例
├── jupyter/ # Notebook 目录
│ ├── camera_preview.ipynb # 单摄像头预览
│ ├── multi_csi_preview.ipynb # 多 CSI 预览
│ └── yolo_rtsp.ipynb # YOLO + RTSP 推流
└── README.md # 示例说明
快速使用:
# 安装依赖
pip install -r requirements.txt
# 命令行工具
python utils/toolkit.py stream --source=csi://0
python utils/toolkit.py view --sources=0,1,2
python utils/toolkit.py calibrate mono --images-dir=./calib_images
python utils/toolkit.py chessboard --a4
# Jupyter Notebook 示例(推荐用于学习和开发)
jupyter lab
# 然后打开 utils/examples/jupyter/ 中的 Notebook📖 文档:



