【AprilTag】视觉定位实战 | 使用 ROS 驱动的 USB 摄像头进行相机标定与 AprilTag 识别

写在前面:
🌟 欢迎光临 清流君 的博客小天地,这里是我分享技术与心得的温馨角落。📝
个人主页清流君_CSDN博客,期待与您一同探索 移动机器人 领域的无限可能。

🔍 本文系 清流君 原创之作,荣幸在CSDN首发🐒
若您觉得内容有价值,还请评论告知一声,以便更多人受益。
转载请注明出处,尊重原创,从我做起。

👍 点赞、评论、收藏,三连走一波,让我们一起养成好习惯😜
在这里,您将收获的不只是技术干货,还有思维的火花

📚 系列专栏:【机器视觉】系列,带您深入浅出,探索机器视觉技术。🖊
愿我的分享能为您带来启迪,如有不足,敬请指正,让我们共同学习,交流进步!

🎭 人生如戏,我们并非能选择舞台和剧本,但我们可以选择如何演绎 🌟
感谢您的支持与关注,让我们一起在知识的海洋中砥砺前行~~~



引言

  上一篇博客介绍了虚拟机 Ubuntu18.04 安装 USB 摄像头 ROS 驱动 usb_cam 的最新方法,本篇博客讲解如何使用 ROS 驱动的 USB 摄像头进行相机标定与 AprilTag 识别。


一、准备工作

1.1 安装 usb_cam 驱动

  系统环境:Ubuntu18.04

  本教程是基于 usb_cam 包读取图像,因此需要提前安装 usb_cam 驱动,参见:

  【Ubuntu】虚拟机安装USB摄像头ROS驱动 usb_cam(最新方法)

1.2 安装相机标定功能包

  安装 camera_calibration 功能包:

sudo apt-get install ros-melodic-camera-calibration

1.3 准备标定板和 USB 摄像头

  准备一个已知尺寸的标定板,本实验使用的是 6 × 9 6\times9 6×9(列X行),边长为 1.8 c m 1.8cm 1.8cm 的棋盘标定板。

  一个通过 ROS 发布图像的单目 USB 摄像头。


二、相机标定

2.1 启动摄像头驱动节点

rosrun usb_cam usb_cam_node

2.2 确定相机编号

  确定使用的video_id,使用如下命令查看:

ls /dev/video*

  一般笔记本电脑自带的摄像头 id 0 0 0,外接的摄像头 id 1 1 1。然后根据需要修改usb_cam/src/usb_cam/launch/usb_cam-test.launch里面的<param name="video_device" value="/dev/video1" />

  尝试启动摄像头。

roslaunch usb_cam usb_cam-test.launch

  但是博主这样写会报错:

… logging to /home/qingliu/.ros/log/0976c44a-7583-11ef-82de-000c293e3ad5/roslaunch-qingliu-4538.log
Checking log directory for disk usage. This may take a while.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.
started roslaunch server http://localhost:44077/
SUMMARY
========
PARAMETERS

  • /image_view/autosize: True
  • /rosdistro: melodic
  • /rosversion: 1.14.13
  • /usb_cam/camera_frame_id: usb_cam
  • /usb_cam/color_format: yuv422p
  • /usb_cam/image_height: 480
  • /usb_cam/image_width: 640
  • /usb_cam/io_method: mmap
  • /usb_cam/pixel_format: yuyv
  • /usb_cam/video_device: /dev/video1

NODES
/image_view (image_view/image_view)
usb_cam (usb_cam/usb_cam_node)
ROS_MASTER_URI=http://localhost:11311
process[usb_cam-1]: started with pid [4558]
process[image_view-2]: started with pid [4559]
[ INFO] [1726639123.930729617]: Initializing nodelet with 4 worker threads.
[ INFO] [1726639124.024001715]: Using transport “raw”
[ INFO] [1726639124.046743699]: using default calibration URL
[ INFO] [1726639124.047399791]: camera calibration URL: file:///home/qingliu/.ros/camera_info/head_camera.yaml
[ INFO] [1726639124.047502595]: Unable to open camera calibration file [/home/qingliu/.ros/camera_info/head_camera.yaml]
[ WARN] [1726639124.047555944]: Camera calibration file /home/qingliu/.ros/camera_info/head_camera.yaml not found.
[ INFO] [1726639124.047608139]: Starting ‘head_camera’ (/dev/video1) at 640x480 via mmap (yuyv) at 30 FPS
[ERROR] [1726639124.047678525]: VIDIOC_G_FMT error 22, Invalid argument
[usb_cam-1] process has died [pid 4558, exit code 1, cmd /home/qingliu/catkin_ws/devel/lib/usb_cam/usb_cam_node __name:=usb_cam __log:=/home/qingliu/.ros/log/0976c44a-7583-11ef-82de-000c293e3ad5/usb_cam-1.log].
log file: /home/qingliu/.ros/log/0976c44a-7583-11ef-82de-000c293e3ad5/usb_cam-1*.log

解决方法

  修改文件~/catkin_ws/src/usb_cam/launch/usb_cam-test.launch

<param name="video_device" value="/dev/video0" />

  修改为 /dev/video0

2.3 查看启动的设备是否正确

查看启动的设备是否正确,若正确则关掉再打开驱动:

rosrun usb_cam usb_cam_node

查看图像是否发布, 列出 topic 确保相机正在通过ROS发布图像:

rostopic list 

这会显示所有已发布的 topic,检查是否有 image_raw topic。以下是本实验的相机topic:

/image_view/output
/image_view/parameter_descriptions
/image_view/parameter_updates
/usb_cam/camera_info
/usb_cam/image_raw
/usb_cam/image_raw/compressed
/usb_cam/image_raw/compressed/parameter_descriptions
/usb_cam/image_raw/compressed/parameter_updates
/usb_cam/image_raw/compressedDepth
/usb_cam/image_raw/compressedDepth/parameter_descriptions
/usb_cam/image_raw/compressedDepth/parameter_updates
/usb_cam/image_raw/theora
/usb_cam/image_raw/theora/parameter_descriptions
/usb_cam/image_raw/theora/parameter_updates

2.4 运行相机标定节点

运行 camera_calibration 标定节点:

rosrun camera_calibration cameracalibrator.py --size 5x8 --square 0.018 image:=/usb_cam/image_raw camera:=/usb_cam  --no-service-check

此命令运行标定结点的python脚本,其中 :

  • --size 5x8 为棋盘内部角点的个数,方格几列几行(需要减 1 1 1),比如我的标定板方格是 6 × 9 6\times 9 6×9,则 size 5 × 8 5\times 8 5×8
  • --square 0.018 为每个棋盘格的边长,单位默认为米( m m m)

  注意 7 × 9 7\times 9 7×9 中间不能用“ ∗ * ”,是字母“ x x x”。

  • image:=/usb_cam/image_raw 为当前订阅的图像来自名为/usb_cam/image_raw的 topic
  • camera:=/usb_cam 为摄像机名
  • 加上--no-service-check是因为一开始运行后出现下面的错误,参考官网加上此参数后就可正常显示。

(‘Waiting for service’, ‘/camera/set_camera_info’, ‘…’)
Service not found

  此操作将打开标定窗口,如下图所示:

在这里插入图片描述

2.5 移动标定板或摄像头

为了达到良好的标定效果,需要在摄像机周围移动标定板,并完成以下基本需求:

  • 移动标定板到画面的最左、右,最上、下方
  • 移动标定板到视野的最近和最远处
  • 移动标定板使其充满整个画面
  • 保持标定板倾斜状态并使其移动到画面的最左、右,最上、下方

右侧四个参数的含义:

  • 当标定板移动到画面的最左、右方时,此时,窗口的X会达到最小或满值
  • 同理,Y指示标定板的在画面的上下位置
  • Size表示标定板在视野中的距离,也可以理解为标定板离摄像头的远近
  • Skew为标定板在视野中的倾斜位置

  每次移动之后,保持标定板不动直到窗口出现高亮提示。

  直到条形变为绿色。当 CRLIBRATE 按钮亮起时,代表已经有足够的数据进行摄像头的标定,此时按下 CRLIBRATE 并等待一分钟左右,标定界面变成灰色,无法进行操作,属于正常情况。
在这里插入图片描述

2.6 得到标定结果

*** Added sample 1, p_x = 0.612, p_y = 0.460, p_size = 0.340, skew = 0.152
*** Added sample 2, p_x = 0.556, p_y = 0.498, p_size = 0.319, skew = 0.277
*** Added sample 3, p_x = 0.373, p_y = 0.579, p_size = 0.321, skew = 0.245
*** Added sample 4, p_x = 0.363, p_y = 0.353, p_size = 0.319, skew = 0.201
*** Added sample 5, p_x = 0.471, p_y = 0.309, p_size = 0.294, skew = 0.162
*** Added sample 6, p_x = 0.603, p_y = 0.319, p_size = 0.282, skew = 0.110
*** Added sample 7, p_x = 0.663, p_y = 0.296, p_size = 0.358, skew = 0.164
*** Added sample 8, p_x = 0.671, p_y = 0.199, p_size = 0.434, skew = 0.139
*** Added sample 9, p_x = 0.674, p_y = 0.144, p_size = 0.524, skew = 0.194
*** Added sample 10, p_x = 0.683, p_y = 0.026, p_size = 0.572, skew = 0.131
*** Added sample 11, p_x = 0.623, p_y = 0.086, p_size = 0.652, skew = 0.143
*** Added sample 12, p_x = 0.586, p_y = 0.262, p_size = 0.635, skew = 0.183
*** Added sample 13, p_x = 0.531, p_y = 0.403, p_size = 0.635, skew = 0.250
*** Added sample 14, p_x = 0.485, p_y = 0.223, p_size = 0.663, skew = 0.244
*** Added sample 15, p_x = 0.560, p_y = 0.329, p_size = 0.516, skew = 0.194
*** Added sample 16, p_x = 0.570, p_y = 0.489, p_size = 0.470, skew = 0.177
*** Added sample 17, p_x = 0.515, p_y = 0.515, p_size = 0.399, skew = 0.122
*** Added sample 18, p_x = 0.494, p_y = 0.618, p_size = 0.334, skew = 0.089
*** Added sample 19, p_x = 0.491, p_y = 0.516, p_size = 0.265, skew = 0.061
*** Added sample 20, p_x = 0.459, p_y = 0.414, p_size = 0.207, skew = 0.069
**** Calibrating ****
mono pinhole calibration…
*** Added sample 63, p_x = 0.568, p_y = 0.398, p_size = 0.252, skew = 0.181
*** Added sample 64, p_x = 0.449, p_y = 0.598, p_size = 0.242, skew = 0.006
*** Added sample 65, p_x = 0.382, p_y = 0.635, p_size = 0.218, skew = 0.080
D = [0.03868745150785007, -0.029877004108823855, -0.0007851867081518497, -0.0008866834766470662, 0.0]
K = [433.18386473568006, 0.0, 341.5023734989315, 0.0, 433.4953796121861, 244.3823670617905, 0.0, 0.0, 1.0]
R = [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]
P = [438.92010498046875, 0.0, 340.88175832247, 0.0, 0.0, 439.3984375, 243.95816827518865, 0.0, 0.0, 0.0, 1.0, 0.0]
None
# oST version 5.0 parameters

[image]

width 640

height 480

[narrow_stereo]

camera matrix
433.183865 0.000000 341.502373
0.000000 433.495380 244.382367
0.000000 0.000000 1.000000

distortion
0.038687 -0.029877 -0.000785 -0.000887 0.000000

rectification
1.000000 0.000000 0.000000
0.000000 1.000000 0.000000
0.000000 0.000000 1.000000

projection
438.920105 0.000000 340.881758 0.000000
0.000000 439.398438 243.958168 0.000000
0.000000 0.000000 1.000000 0.000000

其中,K为相机内参矩阵

  • distortion:畸变系数矩阵
  • camera matrix:摄像头的内部参数矩阵
  • distortion:畸变系数矩阵
  • rectification:矫正矩阵,一般为单位阵
  • projection:外部世界坐标到像平面的投影矩阵

2.7 保存保定数据

  点击 SAVE 按钮。

在这里插入图片描述
  点击 COMMIT 按钮将结果保存到默认文件夹,终端输出如下信息,说明标定结果已经保存在相应文件夹下。下次启动 usb_cam 节点时,会自动调用。

(‘Wrote calibration data to’, ‘/tmp/calibrationdata.tar.gz’)

在这里插入图片描述
  其中,ost.yaml 文件即为相机内参的标定文件。

  至此,相机标定完成!


三、对焦问题

3.1 启动摄像头存在的警告

  启动摄像头存在如下警告:

[ WARN] [1726642015.933315970]: unknown control ‘focus_auto’

3.2 对焦问题的可能原因

出现这个警告可能是有以下两种原因:

  • 因为参数设置不匹配,默认像素的宽和高跟摄像头不匹配。

  • 还有可能只是所使用的相机根本没有自动对焦功能。

因此不用管这个问题。


四、运行Apriltag_ros

4.1 安装 Apriltag 依赖

  首先安装 Apriltag 依赖,从GitHub克隆项目,然后编译并安装这个项目。

  使用 Git 版本控制系统从指定的GitHub仓库克隆 apriltag 项目到本地。这将创建一个名为 apriltag 的目录,其中包含该项目的所有源代码。在一个非ROS工作空间的文件里:

git clone https://github.com/AprilRobotics/apriltag.git # 这个不是ros的功能包

  改变当前工作目录到刚克隆下来的 apriltag 目录:

cd apriltag

  在 apriltag 目录下创建一个名为 build 的新目录,用于存放编译过程中产生的文件:

mkdir build

  将当前工作目录切换到新创建的 build 目录:

cd build

  运行 CMake 工具,它会读取上级目录(即 apriltag 目录)中的 CMakeLists.txt 文件,并生成适用于本机的 Makefile 和其他构建文件。.. 表示 CMake 应该在其父目录中查找 CMakeLists.txt 文件:

cmake ..

  使用Make工具根据 CMake 生成的 Makefile 编译项目。这将编译源代码并生成可执行文件或库:

make

  以管理员权限运行 Make,并将编译好的文件安装到系统的适当位置。将可执行文件、库文件和头文件复制到系统的 binlibinclude 目录:

sudo make install

4.2 安装 Apriltag_ros 功能包

  下面安装 Apriltag_ros 功能包,将源码放到工作空间路径下,如catkin_ws/src,然后编译即可。

cd catkin_ws/src
git clone https://github.com/AprilRobotics/apriltag_ros.git
cd ..
catkin_make

4.3 修改配置文件

  首先修改 ~/catkin_ws/src/apriltag_ros/apriltag_ros/launch/continuous_detection.launch 文件。

  apriltag_ros 需要订阅相机图像数据与相机信息,比如对于USB摄像头,在开启相机时会发布两个相关的 topic:

  • /usb_cam/camera_info
  • /usb_cam/image_raw

  因此需将 camera_namecamera_frame 的内容修改为订阅的 topic。

launch 文件内容修改如下:

<!-- 修改 -->
  <arg name="camera_name" default="/usb_cam" />
  <arg name="image_topic" default="image_raw" />
<!-- 添加 -->
  <arg name="camera_frame" default="/camera" />

完整launch文件内容如下:

<launch>
  <!-- set to value="gdbserver localhost:10000" for remote debugging -->
  <arg name="launch_prefix" default="" />

  <!-- configure camera input -->
  <arg name="camera_name" default="/usb_cam" />
  <arg name="image_topic" default="image_raw" />
  <arg name="camera_frame" default="/camera" />

  <arg name="queue_size" default="1" /> 

  <!-- apriltag_ros continuous detection node -->
  <node pkg="apriltag_ros" type="apriltag_ros_continuous_node" name="apriltag_ros_continuous_node" clear_params="true" output="screen" launch-prefix="$(arg launch_prefix)">
    <!-- Remap topics from those used in code to those on the ROS network -->
    <remap from="image_rect" to="$(arg camera_name)/$(arg image_topic)" />
    <remap from="camera_info" to="$(arg camera_name)/camera_info" />

    <param name="publish_tag_detections_image" type="bool" value="true" /><!-- default: false -->
    <param name="queue_size" type="int" value="$(arg queue_size)" />

    <!-- load parameters (incl. tag family, tags, etc.) -->
    <rosparam command="load" file="$(find apriltag_ros)/config/settings.yaml"/>
    <rosparam command="load" file="$(find apriltag_ros)/config/tags.yaml"/>
  </node>
</launch>

  修改 ~/catkin_ws/src/apriltag_ros/apriltag_ros/config/tags.yaml 文件,添加需要检测的二维码id与自己测量得到的二维码尺寸大小size(单位:米)。

standalone_tags:
  [
      {id: 1, size: 0.0515},
      {id: 2, size: 0.0515},
      {id: 3, size: 0.0515},
      {id: 4, size: 0.0515},
      {id: 5, size: 0.0515},
      {id: 6, size: 0.0515}    
  ]

注意
1、同一 ID 的 Apriltag 码不能在该配置文件中以不同的大小出现两次,也不能出现在一张图片的两个地方。这些都将在检测中产生歧义。

2、确保打印的 AprilTag 码至少包含 1 1 1 位宽的白色边框,AprilTag 算法会对周围的白色边框进行采样。

4.4 运行Apriltag_ros

刷新环境变量:

source ~/catkin_ws/devel/setup.bash

分别打开四个终端,运行如下命令行:

(1) 启动 USB 相机驱动

roslaunch usb_cam usb_cam-test.launch

(2) 运行 AprilTag_ros 算法

roslaunch apriltag_ros continuous_detection.launch

(3) RViz 可视化界面

rosrun rviz rviz

(4) 输出定位数据

rostopic echo /tag_detections

  正确运行识别到 AprilTag 的界面如下图所示:

在这里插入图片描述

  输出的定位数据如下:

在这里插入图片描述


五、总结

  本教程介绍了如何使用 ROS 进行相机标定和 Apriltag 识别。

  首先,安装了 usb_cam 驱动和 camera_calibration 功能包,并准备了一个 6 × 9 6\times9 6×9 的棋盘格标定板和一个单目 USB 摄像头。

  然后,启动了摄像头驱动节点,并调整了摄像头视频设备 id,以正确地接收摄像头图像。

  接下来,运行了相机标定节点,通过在摄像机周围移动标定板,完成了标定过程,并得到了相机的内参矩阵和畸变系数矩阵。

  最后,安装了 Apriltag_ros 功能包,并修改了配置文件以匹配摄像头和 Apriltag 尺寸。运行了 Apriltag 识别节点,并在 RViz 中可视化了检测结果。

  通过本教程,读者可掌握如何使用 ROS 进行相机标定和 Apriltag 识别,这对于机器人视觉系统至关重要。


参考资料

  1、【Ubuntu】虚拟机安装USB摄像头ROS驱动 usb_cam(最新方法)

  2、使用Apriltags实现定位、评估定位精度的全流程记录

  3、ROS下采用camera_calibration进行单目相机标定


后记:

🌟 感谢您耐心阅读这篇关于 使用 ROS 驱动的 USB 摄像头进行相机标定与 AprilTag 识别 的技术博客。 📚

🎯 如果您觉得这篇博客对您有所帮助,请不要吝啬您的点赞和评论 📢

🌟您的支持是我继续创作的动力。同时,别忘了收藏本篇博客,以便日后随时查阅。🚀

🚗 让我们一起期待更多的技术分享,共同探索移动机器人的无限可能!💡

🎭感谢您的支持与关注,让我们一起在知识的海洋中砥砺前行 🚀

评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清流君

感恩有您,共创未来,愿美好常伴

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值