OpenCV库(Open Source Computer Vision Library)是一个基于BSD许可发行的跨平台开源计算机视觉库,可以运行在Linux、Windows和mac OS等操作系统上。OpenCV由一系列C函数和少量C++类构成,同时提供C++、Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法,而且对非商业应用和商业应用都是免费的。同时OpenCV可以直接访问硬件摄像头,并且还提供一个简单的GUI系统——highgui。   机器视觉功能包下载地址,包含了摄像头标定、OpenCV、人脸识别、物体跟踪、二维码识别和物体识别等:   //download.csdn.net/download/weixin_44827364/12147918 下面的代码在这个功能包里都有。   基于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图像,通过话题进行发布,实现各节点之间的图像传输。   微信图片_20210120155252   下面通过一个简单的例子了解如何使用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图像后的显示效果,左右两幅图像应该完全一致。   微信图片_20210120155326   左上角的红圈是OpenCV处理的,这个用来测试CvBridge可以完成来回图像数据的转换,两幅图应该是一样的,现在就证明ROS可以接收到OpenCV处理后的图像并以话题的方式发布。   实现该例程的源码robot_vision/scripts/cv_bridge_test.py的内容如下:  
#!/usr/bin/env python
# -*- coding: utf-8 -*-

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()这两个接口函数的使用方法就可以了。