一、cv_bridge
cv_bridge是将ROS中的图像信息转化为OpenCV的图像信息,从而使用OpenCV进行图像处理。
二、创建功能包
$ 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机器人开发实践》
总有一个遗忘的过程,记录一下为以后查找方便。