OpenCV库(Open Source Computer Vision
Library)是一个基于BSD许可发行的跨平台开源计算机视觉库,可以运行在Linux、Windows和mac OS等操作系统上。OpenCV由一系列C函数和少量C++类构成,同时提供C++、Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法,而且对非商业应用和商业应用都是免费的。同时OpenCV可以直接访问硬件摄像头,并且还提供一个简单的GUI系统——highgui。
ROS 安装OpenCV
基于OpenCV库,我们可以快速开发机器视觉方面的应用,而且ROS中已经集成了OpenCV库和相关的接口功能包,使用以下命令即可安装:
sudo apt-get install ros-kinetic-vision-opencv libopencv-dev python-opencv
在ROS中使用OpenCV
ROS为开发者提供了与OpenCV的接口功能包——cv_bridge。如图7-13所示,开发者可以通过该功能包将ROS中的图像数据转换成OpenCV格式的图像,并且调用OpenCV库进行各种图像处理;或者将OpenCV处理过后的数据转换成ROS图像,通过话题进行发布,实现各节点之间的图像传输。
下面通过一个简单的例子了解如何使用cv_bridge完成ROS与OpenCV之间的图像转换。在该例程中,一个ROS节点订阅摄像头驱动发布的图像消息,然后将其转换成OpenCV的图像格式进行显示,最后再将该OpenCV格式的图像转换成ROS图像消息进行发布并显示。
通过以下命令启动该例程:
roslaunch robot_vision usb_cam.launch
rosrun robot_vision cv_bridge_test.py
rqt_image_view
例程运行的效果如图所示,图中左边是通过cv_bridge将ROS图像转换成OpenCV图像数 据之后的显示效果,使用OpenCV库在图像左上角绘制了一个红色的圆;
图中右边是将OpenCV图像数据再次通过cv_bridge转换成ROS图像后的显示效果,左右两幅图像应该完全一致。
实现该例程的源码robot_vision/scripts/cv_bridge_test.py的内容如下:
import rospy
import cv2
from cv_bridge import CvBridge, CvBridgeError
from sensor_msgs.msg import Image
class image_converter:
def __init__(self):
# 创建cv_bridge,声明图像的发布者和订阅者
self.image_pub = rospy.Publisher("cv_bridge_image", Image, queue_size=1)
self.bridge = CvBridge()
self.image_sub = rospy.Subscriber("/usb_cam/image_raw", Image, self.callback)
def callback(self,data):
# 使用cv_bridge将ROS的图像数据转换成OpenCV的图像格式
try:
cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")
except CvBridgeError as e:
print e
# 在opencv的显示窗口中绘制一个圆作为标记
(rows,cols,channels) = cv_image.shape
if cols > 60 and rows > 60 :
cv2.circle(cv_image, (60, 60), 30, (0,0,255), -1)
# 显示OpenCV格式的图像
cv2.imshow("Image window", cv_image)
cv2.waitKey(3)
# 再将OpenCV格式的数据转换成ROS image格式的数据发布
try:
self.image_pub.publish(self.bridge.cv2_to_imgmsg(cv_image, "bgr8"))
except CvBridgeError as e:
print e
if __name__ == '__main__':
try:
# 初始化ROS节点
rospy.init_node("cv_bridge_test")
rospy.loginfo("Starting cv_bridge_test node")
image_converter()
rospy.spin()
except KeyboardInterrupt:
print "Shutting down cv_bridge_test node."
cv2.destroyAllWindows()
分析以上例程代码的关键部分:
import cv2
from cv_bridge import CvBridge, CvBridgeError
要调用OpenCV,必须先导入OpenCV模块,另外还应导入cv_bridge所需要的一些模块。
self.image_pub = rospy.Publisher("cv_bridge_image", Image, queue_size=1)
self.bridge = CvBridge()
self.image_sub = rospy.Subscriber("/usb_cam/image_raw", Image, self.callback)
定义一个Subscriber接收原始图像消息,再定义一个Publisher发布OpenCV处理后的图像消息,还要定义一个CvBridge的句柄,便于调用相关的转换接口。
try:
cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")
except CvBridgeError as e:
print e
imgmsg_to_cv2()接口的功能就是将ROS图像消息转换成OpenCV图像数据,该接口有两个输入参数:第一个参数指向图像消息流,第二个参数用来定义转换的图像数据格式。
try:
self.image_pub.publish(self.bridge.cv2_to_imgmsg(cv_image, "bgr8"))
except CvBridgeError as e:
print e
cv2_to_imgmsg()接口的功能是将OpenCV格式的图像数据转换成ROS图像消息,该接口同样要求输入图像数据流和数据格式这两个参数。
从这个例程来看,ROS中调用OpenCV的方法并不复杂
,主要熟悉imgmsg_to_cv2()、cv2_to_imgmsg()
这两个接口函数的使用方法就可以了。