3、 ROS+Opencv基础3.1、概述3.2、单目相机/树莓派CSI相机3.2.1、启动单目相机/树莓派CSI相机3.2.2、启动彩色图像反转3.3、Jetson CSI相机3.3.1、启动Jetson CSI相机3.2.2、启动彩色图像反转
Wiki:http://wiki.ros.org/cv_bridge/
教学:http://wiki.ros.org/cv_bridge/Tutorials
源码:https://github.com/ros-perception/vision_opencv.git
功能包位置:~/yahboomcar_ws/src/yahboomcar_visual
ROS在安装的过程中就已经集成了Opencv3.0以上的版本,所以安装配置几乎不需要过多考虑,ROS 以自己的sensor_msgs/Image消息格式传递图像,无法直接进行图像处理,但是提供的【CvBridge】可以完美转换和被转换图像数据格式。【CvBridge】是一个 ROS 库,相当于ROS和Opencv之间的桥梁。
Opencv和ROS图像数据转换如下图所示:

虽然安装配置不需要过多考虑,但是使用环境还是需要配置的,主要是【package.xml】和【CMakeLists.txt】这两个文件。该功能包不仅仅是使用【CvBridge】,还需要【Opencv】和【PCL】,所以一起配置完毕。
添加如下内容
xxxxxxxxxx <build_depend>sensor_msgs</build_depend> <build_export_depend>sensor_msgs</build_export_depend> <exec_depend>sensor_msgs</exec_depend>
<build_depend>std_msgs</build_depend> <build_export_depend>std_msgs</build_export_depend> <exec_depend>std_msgs</exec_depend> <build_depend>cv_bridge</build_depend> <build_export_depend>cv_bridge</build_export_depend> <exec_depend>cv_bridge</exec_depend> <exec_depend>image_transport</exec_depend>【cv_bridge】:图像转换依赖包。
该文件配置内容较多,具体内容请查看源文件。
xxxxxxxxxxroslaunch usb_cam usb_cam-test.launch
查看话题
xxxxxxxxxxrostopic list
可以看到话题很多,本节常用的就几个
| 话题名 | 数据类型 |
|---|---|
| /usb_cam/image_raw | sensor_msgs/Image |
| /usb_cam/image_raw/compressedDepth | sensor_msgs/CompressedImage |
| /usb_cam/image_raw/compressed | sensor_msgs/CompressedImage |
查看话题的编码格式:rostopic echo +【topic】+encoding,例如
xxxxxxxxxxrostopic echo /usb_cam/image_raw/encoding
话题后面带有【compressed】或【compressedDepth】属于压缩过的话题,ROS在图像传输时,由于网络、主控运行速度、主控运行内存、视频流数据庞大等因素可能会导致数据丢包,获取不到话题。所以没办法,我只能订阅压缩过的话题。同时打开两个图像订阅不同话题测试,如果设备性能很好,网络也很好的话,看不出什么变化,否则,会发现图像压缩后的话题会流畅很多。
查看图片
xxxxxxxxxxrqt_image_view

xxxxxxxxxxroslaunch yahboomcar_visual usb_cam_flip.launch 
图像查看
xxxxxxxxxxrqt_image_view

这里创建了两个订阅者和两个发布者,一个处理一般图像数据,一个处理压缩图像数据。
1)创建订阅者
订阅的话题是【"/usb_cam/image_raw"】,数据类型【Image】,回调函数【topic()】。
订阅的话题是【"/usb_cam/image_raw/compressed"】,数据类型【CompressedImage】,回调函数【compressed_topic()】。
2)创建发布者
发布的话题是【"/usb_cam/image_flip"】,数据类型【Image】,队列大小【10】。
发布的话题是【"/usb_cam/image_flip/compressed"】,数据类型【CompressedImage】,队列大小【10】。
xxxxxxxxxxsub_img = rospy.Subscriber("/usb_cam/image_raw", Image, topic)pub_img = rospy.Publisher("/usb_cam/image_flip", Image, queue_size=10)sub_comimg = rospy.Subscriber("/usb_cam/image_raw/compressed", CompressedImage, compressed_topic)pub_comimg = rospy.Publisher("/usb_cam/image_flip/compressed", CompressedImage, queue_size=10)3)回调函数
xxxxxxxxxx# 正常图像传输处理def topic(msg): if not isinstance(msg, Image): return bridge = CvBridge() frame = bridge.imgmsg_to_cv2(msg, "bgr8") # Opencv处理图像 frame = cv.resize(frame, (640, 480)) frame = cv.flip(frame, 1) # opencv mat -> ros msg msg = bridge.cv2_to_imgmsg(frame, "bgr8") # 图像处理完毕,直接发布 pub_img.publish(msg)
# 压缩图像传输处理def compressed_topic(msg): if not isinstance(msg, CompressedImage): return bridge = CvBridge() frame = bridge.compressed_imgmsg_to_cv2(msg, "bgr8") # Opencv处理图像 frame = cv.resize(frame, (640, 480)) frame = cv.flip(frame, 1) # Create CompressedIamge msg = CompressedImage() msg.header.stamp = rospy.Time.now() # 图像数据转换 msg.data = np.array(cv.imencode('.jpg', frame)[1]).tostring() # 图像处理完毕,直接发布 pub_comimg.publish(msg)xxxxxxxxxxroslaunch yahboomcar_visual yahboom_csi.launch
查看话题
xxxxxxxxxxrostopic list
可以看到话题很多,本节常用的就几个
| 话题名 | 数据类型 |
|---|---|
| /csi_cam_0/image_raw | sensor_msgs/Image |
| /csi_cam_0/image_raw/compressed | sensor_msgs/CompressedImage |
查看话题的编码格式:rostopic echo +【topic】+encoding,例如
xxxxxxxxxxrostopic echo /csi_cam_0/image_raw/encoding
话题后面带有【compressed】或【compressedDepth】属于压缩过的话题,ROS在图像传输时,由于网络、主控运行速度、主控运行内存、视频流数据庞大等因素可能会导致数据丢包,获取不到话题。所以没办法,我只能订阅压缩过的话题。同时打开两个图像订阅不同话题测试,如果设备性能很好,网络也很好的话,看不出什么变化,否则,会发现图像压缩后的话题会流畅很多。
查看图片
xxxxxxxxxxrqt_image_view

xxxxxxxxxxroslaunch yahboomcar_visual usb_cam_flip.launch 
图像查看
xxxxxxxxxxrqt_image_view

这里创建了两个订阅者和两个发布者,一个处理一般图像数据,一个处理压缩图像数据。
1)创建订阅者
订阅的话题是【"/csi_cam_0/image_raw"】,数据类型【Image】,回调函数【topic()】。
订阅的话题是【"/csi_cam_0/image_raw/compressed"】,数据类型【CompressedImage】,回调函数【compressed_topic()】。
2)创建发布者
发布的话题是【"/csi_cam_0/image_flip"】,数据类型【Image】,队列大小【10】。
发布的话题是【"/csi_cam_0/image_flip/compressed"】,数据类型【CompressedImage】,队列大小【10】。
xxxxxxxxxxsub_img = rospy.Subscriber("/csi_cam_0/image_raw", Image, topic)pub_img = rospy.Publisher("/csi_cam_0/image_flip", Image, queue_size=10)sub_comimg = rospy.Subscriber("/csi_cam_0/image_raw/compressed", CompressedImage, compressed_topic)pub_comimg = rospy.Publisher("/csi_cam_0/image_flip/compressed", CompressedImage, queue_size=10)3)回调函数
# 正常图像传输处理def topic(msg): if not isinstance(msg, Image): return bridge = CvBridge() frame = bridge.imgmsg_to_cv2(msg, "bgr8") # Opencv处理图像 frame = cv.resize(frame, (640, 480)) frame = cv.flip(frame, 1) # opencv mat -> ros msg msg = bridge.cv2_to_imgmsg(frame, "bgr8") # 图像处理完毕,直接发布 pub_img.publish(msg)
# 压缩图像传输处理def compressed_topic(msg): if not isinstance(msg, CompressedImage): return bridge = CvBridge() frame = bridge.compressed_imgmsg_to_cv2(msg, "bgr8") # Opencv处理图像 frame = cv.resize(frame, (640, 480)) frame = cv.flip(frame, 1) # Create CompressedIamge msg = CompressedImage() msg.header.stamp = rospy.Time.now() # 图像数据转换 msg.data = np.array(cv.imencode('.jpg', frame)[1]).tostring() # 图像处理完毕,直接发布 pub_comimg.publish(msg)