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】:图像转换依赖包。
该文件配置内容较多,具体内容请查看源文件。
xxxxxxxxxx
roslaunch usb_cam usb_cam-test.launch
查看话题
xxxxxxxxxx
rostopic 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,例如
xxxxxxxxxx
rostopic echo /usb_cam/image_raw/encoding
话题后面带有【compressed】或【compressedDepth】属于压缩过的话题,ROS在图像传输时,由于网络、主控运行速度、主控运行内存、视频流数据庞大等因素可能会导致数据丢包,获取不到话题。所以没办法,我只能订阅压缩过的话题。同时打开两个图像订阅不同话题测试,如果设备性能很好,网络也很好的话,看不出什么变化,否则,会发现图像压缩后的话题会流畅很多。
查看图片
xxxxxxxxxx
rqt_image_view
xxxxxxxxxx
roslaunch yahboomcar_visual usb_cam_flip.launch
图像查看
xxxxxxxxxx
rqt_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】。
xxxxxxxxxx
sub_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)
xxxxxxxxxx
roslaunch yahboomcar_visual yahboom_csi.launch
查看话题
xxxxxxxxxx
rostopic list
可以看到话题很多,本节常用的就几个
话题名 | 数据类型 |
---|---|
/csi_cam_0/image_raw | sensor_msgs/Image |
/csi_cam_0/image_raw/compressed | sensor_msgs/CompressedImage |
查看话题的编码格式:rostopic echo +【topic】+encoding,例如
xxxxxxxxxx
rostopic echo /csi_cam_0/image_raw/encoding
话题后面带有【compressed】或【compressedDepth】属于压缩过的话题,ROS在图像传输时,由于网络、主控运行速度、主控运行内存、视频流数据庞大等因素可能会导致数据丢包,获取不到话题。所以没办法,我只能订阅压缩过的话题。同时打开两个图像订阅不同话题测试,如果设备性能很好,网络也很好的话,看不出什么变化,否则,会发现图像压缩后的话题会流畅很多。
查看图片
xxxxxxxxxx
rqt_image_view
xxxxxxxxxx
roslaunch yahboomcar_visual usb_cam_flip.launch
图像查看
xxxxxxxxxx
rqt_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】。
xxxxxxxxxx
sub_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)