ROS系统学习5---OpenCV的使用

xiaoxiao2025-07-25  36

在机器人系统中,视觉是非常重要的一部分(人的眼睛获取信息占全部信息的78%,机器人可以类比下)。因此,用前面四篇文章打下些许基础后,本人便迫不及待的想学习怎么在ROS上用上OpenCV视觉库。

好消息是我们第一篇文章选择了全部安装,这其中就把OpenCV库装进去了。那么剩下的就只是应用了。

为了操作方便,我们新建一个包,叫做rosOpenCV:

catkin_create_pkg rosOpenCV sensor_msgs cv_bridge roscpp std_msgs image_transport

先编译一下(这一步很关键):

catkin_make

在包下放一个cpp文件,叫做rosOpenCV.cpp,内容如下:

#include <ros/ros.h> #include <image_transport/image_transport.h> #include <opencv2/highgui/highgui.hpp> #include <cv_bridge/cv_bridge.h> #include <stdio.h> int main(int argc, char** argv) { ros::init(argc, argv, "image_publisher"); ros::NodeHandle nh; cv::Mat image = cv::imread("/home/weixin/图片/壁纸/3.jpg", CV_LOAD_IMAGE_COLOR); if(image.empty()) { printf("open error\n"); } cv::imshow("",image); cv::waitKey(3000); cv::destroyWindow(""); ros::spin(); }

在CMakeLists.txt末尾加上:

include_directories(${catkin_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS}) add_executable(rosOpenCV ./src/rosOpenCV.cpp) target_link_libraries(rosOpenCV ${OpenCV_LIBS}) target_link_libraries(rosOpenCV ${catkin_LIBRARIES})

注意,如果是在工程创建后添加的,而且创建工程的时候没有添加opencv,则可以通过添加

#find_package(OpenCV)

或者

find_package(cv_bridge)

来把OpenCV引进来

到此,我们就能用OpenCV读取一张本地的图像并显示出来了。当然这样的操作也并没有什么意义,下面我们来做点有意义的。

我们将从本地读取图片数据,然后通过话题将这张图片发送出去。

其中,因为OpenCV的格式不是ROS通用的,因此我们需要通过cv_bridge转换一下。

具体的,我们只需要将rosOpenCV.cpp稍做修改即可:

 

#include <ros/ros.h> #include <image_transport/image_transport.h> #include <opencv2/highgui/highgui.hpp> #include <cv_bridge/cv_bridge.h> #include <stdio.h> int main(int argc, char** argv) { ros::init(argc, argv, "image_publisher"); ros::NodeHandle nh; image_transport::ImageTransport it(nh);//用之前声明的节点句柄初始化it,其实这里的it和nh的功能基本一样,可以像之前一样使用it来发布和订阅相消息。 image_transport::Publisher pub = it.advertise("camera/image", 1); cv::Mat image = cv::imread("/home/weixin/图片/壁纸/3.jpg", CV_LOAD_IMAGE_COLOR); if(image.empty()) { printf("open error\n"); } sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image).toImageMsg();//图像格式转换 ros::Rate loop_rate(5);//每秒5帧 while (nh.ok()) { pub.publish(msg); ros::spinOnce(); loop_rate.sleep(); } }

运行起来之后,可以用

rostopic echo /camera/image

查看我们发布出来的图片话题,但因为数据太多,效果相当要命。

我们可以用rivz来看,因为我们之前把ros的工具全装了,直接打开就可以:

rosrun rviz rviz

打开后点击左下方的"Add",在弹出的对话框中选"By topic",里面有"Image"选中后点击"OK",然后便可以看到下面的画面:

 

也可以自己编写接受节点去接收图像并显示出来,代码如下:

#include <ros/ros.h> #include <image_transport/image_transport.h> #include <opencv2/highgui/highgui.hpp> #include <cv_bridge/cv_bridge.h> void imageCallback(const sensor_msgs::ImageConstPtr& msg) { cv::imshow("view", cv_bridge::toCvShare(msg, "bgr8")->image); cv::waitKey(30); } int main(int argc, char **argv) { ros::init(argc, argv, "image_listener"); ros::NodeHandle nh; image_transport::ImageTransport it(nh); image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback); ros::spin(); }

针对压缩格式的图像消息用一下代码:

#include "ros/ros.h" #include "sensor_msgs/CompressedImage.h" #include "sensor_msgs/image_encodings.h" #include <cv_bridge/cv_bridge.h> #include <opencv2/opencv.hpp> #include <iostream> cv::Mat imgCallback; static void ImageCallback(const sensor_msgs::CompressedImageConstPtr &msg) { cv_bridge::CvImagePtr cv_ptr_compressed = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8); imgCallback = cv_ptr_compressed->image; cv::imshow("imgCallback", imgCallback); cv::waitKey(1); } int main(int argc, char **argv) { ros::init(argc, argv, "CompressedImage"); ros::NodeHandle nh; ros::Subscriber image_sub; std::string image_topic = "/camera_front/image_color/compressed"; image_sub = nh.subscribe(image_topic, 10, ImageCallback); ros::Rate loop_rate(10); while (ros::ok()) { ros::spinOnce(); loop_rate.sleep(); } return 0; }

 

Ok,到此最简单的OpenCV的使用就讲完了。


 

 

转载请注明原文地址: https://www.6miu.com/read-5033697.html

最新回复(0)