【ros学习笔记】使用cv_bridge连接ROS和OpenCV

一、cv_bridge
cv_bridge是将ROS中的图像信息转化为OpenCV的图像信息,从而使用OpenCV进行图像处理。
【ros学习笔记】使用cv_bridge连接ROS和OpenCV_第1张图片
二、创建功能包

$ catkin_create_pkg ros_bridge_opencv cv_bridge image_transport roscpp sensor_msgs std_msgs rospy

三、配置CMakeList.txt文件

# 寻找OpenCV库
find_package(OpenCV REQUIRED)
# 添加头文件
include_directories(${OpenCV_INCLUDE_DIRS})
# 生成编译文件
add_executable(bridge src/bridge.cpp)
#链接OpenCV库
target_link_libraries(bridge ${OpenCV_LIBS})

四、在src中创建bridge.cpp

#include 
// 用image_transport软件包发布和订阅ROS中的图像
#include 
// 这两个头文件包含了CvBridge类以及与图像编码相关的函数
#include 
#include 
// 这两个头文件包含了OpenCV图像处理模块和GUI模块
#include 
#include 

static const std::string OPENCV_WINDOW = "Image window";

class ImageConverter
{
     
	ros::NodeHandle nh_;
	image_transport::ImageTransport it_;
	// 声明订阅者和发布者对象
	image_transport::Subscriber image_sub_;
	image_transport::Publisher image_pub_;

public:
	ImageConverter()
		: it_(nh_)
	{
     
		// Subscrive to input video feed and publish output video feed
		image_sub_ = it_.subscribe("/camera/rgb/image_raw", 1, &ImageConverter::imageCb, this);
		image_pub_ = it_.advertise("/image_converter/output_video", 1);

		cv::namedWindow(OPENCV_WINDOW);  
	}

	~ImageConverter() // 析构函数
	{
     
		cv::destroyWindow(OPENCV_WINDOW);
	}

	void imageCb(const sensor_msgs::ImageConstPtr& msg)
	{
     
		cv_bridge::CvImagePtr cv_ptr;
		try
		{
     
			cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
		}
		catch (cv_bridge::Exception& e)
		{
     
			ROS_ERROR("cv_bridge exception: %s", e.what());
			return;
		}
		
		// Draw as example circle on the video stream
		if (cv_ptr->image.rows > 60 && cv_ptr->image.cols > 60)
			cv::circle(cv_ptr->image, cv::Point(50, 50), 10, CV_RGB(255, 0, 0));
		
		// Update GUI Window
		cv::imshow(OPENCV_WINDOW, cv_ptr->image);
		cv::waitKey(3);

		// Output modified video stream
		image_pub_.publish(cv_ptr->toImageMsg());
	}
};

int main(int argc, char** argv)
{
     
	ros::init(argc, argv, "birdge");
	ImageConverter ic;
	ros::spin();
	return 0;
	
}
# 打开相机
$ roslaunch astra_launch astra.launch
# 在工作空间中编译
$ catkin_make
$ sorce devel/setup.bash
$ rosrun ros_bridge_opencv bridge

五、在scripts中创建一个opencv_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("/camera/rgb/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:
       bridge     print e

if __name__ == '__main__':
    try:
        # 初始化ros节点
        rospy.init_node("opencv_bridge_test")
        rospy.loginfo("Starting cv_bridge_test node")
        image_converter()
        rospy.spin()
    except KeyboardInterrupt:
        print "Shutting down cv_bridge_test node."
        cv2.destroyAllWindows()
# 打开相机
$ roslaunch astra_launch astra.launch
# 在工作空间中编译
$ catkin_make
$ sorce devel/setup.bash
$ rosrun ros_bridge_opencv opencv_bridge_test.py

在两种代码中订阅者的相机信息与驱动的相机有关,需要订阅自己相机信息的话题。

参考:
1、Converting between ROS images and OpenCV images (C++)
2、《ROS机器人开发实践》

总有一个遗忘的过程,记录一下为以后查找方便。

你可能感兴趣的:(c++,opencv,python)