有多少人工,就有多少智能

Robotics-Ros1-cv_bridge功能包使用示例

我们用一个最简单、完整的例子来理解 cv_bridge:ROS 订阅摄像头图像 → 转换为 OpenCV 图像 → 将彩色图像转换成灰度图 → 再通过 ROS 发布出去。

下面使用你之前学习的环境:ROS1 Noetic + Ubuntu 20.04 + C++。

一、先理解程序的工作流程

 
摄像头节点
    │
    │ 发布 /camera/image_raw
    ▼
我们的图像处理节点
    │
    ├── ① 接收 sensor_msgs/Image
    │
    ├── ② cv_bridge 转换为 cv::Mat
    │
    ├── ③ OpenCV 转换为灰度图
    │
    ├── ④ cv_bridge 转换回 ROS 图像消息
    │
    └── ⑤ 发布 /camera/image_gray
                 │
                 ▼
             其他 ROS 节点

这里有三个不同的角色:

  • ROS:负责图像消息的传输。
  • cv_bridge:负责 ROS 图像消息和 OpenCV 图像数据之间的转换。
  • OpenCV:负责真正的图像处理。

二、编写 C++ 程序

创建一个 ROS 功能包,名称为 cv_bridge_demo。

1. 编写图像处理节点

新建文件 src/image_processor.cpp:

#include <ros/ros.h>
#include <sensor_msgs/Image.h>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/imgproc/imgproc.hpp>

class ImageProcessor
{
public:
    ImageProcessor()
    {
        // 订阅摄像头图像
        image_sub_ = nh_.subscribe(
            "/camera/image_raw",
            1,
            &ImageProcessor::imageCallback,
            this
        );

        // 发布灰度图像
        image_pub_ = nh_.advertise<sensor_msgs::Image>(
            "/camera/image_gray",
            1
        );

        ROS_INFO("ImageProcessor started.");
    }

private:
    ros::NodeHandle nh_;

    ros::Subscriber image_sub_;
    ros::Publisher image_pub_;

    void imageCallback(
        const sensor_msgs::ImageConstPtr& msg)
    {
        try
        {
            // 1. ROS 图像消息转换为 OpenCV 图像
            cv_bridge::CvImagePtr cv_ptr =
                cv_bridge::toCvCopy(msg, "bgr8");

            // 2. 获取 OpenCV 图像
            cv::Mat color_image = cv_ptr->image;

            // 3. 使用 OpenCV 转换为灰度图
            cv::Mat gray_image;

            cv::cvtColor(
                color_image,
                gray_image,
                cv::COLOR_BGR2GRAY
            );

            // 4. OpenCV 图像转换为 ROS 图像消息
            sensor_msgs::ImagePtr output_msg =
                cv_bridge::CvImage(
                    msg->header,
                    "mono8",
                    gray_image
                ).toImageMsg();

            // 5. 发布处理结果
            image_pub_.publish(output_msg);

            ROS_INFO_THROTTLE(
                5.0,
                "Image processed successfully."
            );
        }
        catch (const cv_bridge::Exception& e)
        {
            ROS_ERROR(
                "cv_bridge exception: %s",
                e.what()
            );
        }
    }
};

int main(int argc, char** argv)
{
    ros::init(argc, argv, "image_processor");

    ImageProcessor processor;

    ros::spin();

    return 0;
}

 

2. 重点看这三行代码

第一步:ROS 消息转换为 OpenCV 图像。

cv_bridge::CvImagePtr cv_ptr =
    cv_bridge::toCvCopy(msg, "bgr8");

输入:

sensor_msgs::Image

输出:

cv_bridge::CvImagePtr

通过:

cv::Mat color_image = cv_ptr->image;

获取 OpenCV 图像。

注意,toCvCopy() 会创建图像数据副本,必要时还会进行编码转换。

第二步:OpenCV 处理图像。

cv::cvtColor(
    color_image,
    gray_image,
    cv::COLOR_BGR2GRAY
);

这一步完全由 OpenCV 完成,与 cv_bridge 无关。

输入是 BGR 彩色图像,输出是单通道灰度图像。

第三步:OpenCV 图像转换为 ROS 消息。

sensor_msgs::ImagePtr output_msg =
    cv_bridge::CvImage(
        msg->header,
        "mono8",
        gray_image
    ).toImageMsg();

这一步重新使用 cv_bridge,把 OpenCV 处理后的图像封装为 ROS 消息。

最后:

image_pub_.publish(output_msg);

由 ROS 将图像发送给其他节点。


三、配置编译文件

在功能包的 CMakeLists.txt 中添加以下配置:

cmake_minimum_required(VERSION 3.0.2)

project(cv_bridge_demo)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  sensor_msgs
  cv_bridge
)

find_package(OpenCV REQUIRED)

catkin_package()

include_directories(
  ${catkin_INCLUDE_DIRS}
  ${OpenCV_INCLUDE_DIRS}
)

add_executable(image_processor
  src/image_processor.cpp
)

target_link_libraries(image_processor
  ${catkin_LIBRARIES}
  ${OpenCV_LIBRARIES}
)
在 package.xml 中声明依赖:

<buildtool_depend>catkin</buildtool_depend>

<depend>roscpp</depend>
<depend>sensor_msgs</depend>
<depend>cv_bridge</depend>

 

如果你使用 Ubuntu 20.04 的 ROS Noetic,通常可以直接安装相关依赖:

sudo apt update

sudo apt install \
  ros-noetic-cv-bridge \
  ros-noetic-sensor-msgs \
  libopencv-dev

四、编译运行

假设你的 ROS 工作空间为 ~/catkin_ws。

1. 编译

将功能包放在:

~/catkin_ws/src/cv_bridge_demo/

执行:

cd ~/catkin_ws

catkin_make

source devel/setup.bash

2. 启动 ROS

首先启动 ROS Master:

roscore

然后在另一个终端启动图像处理节点:

source ~/catkin_ws/devel/setup.bash

rosrun cv_bridge_demo image_processor

注意:此时还需要有摄像头节点或其他图像发布节点,向 /camera/image_raw 发布图像,否则程序不会收到图像。

3. 查看图像话题

查看系统中的图像话题:

rostopic list

查看处理后的灰度图像:

rostopic echo /camera/image_gray

这里会输出消息的元数据和图像数据,图像数据本身通常较长。

如果安装了 rqt_image_view,可以用它直接查看图像:

sudo apt install ros-noetic-rqt-image-view

rosrun rqt_image_view rqt_image_view

在界面中选择:

/camera/image_gray

就可以看到灰度图像。


五、没有摄像头怎么办?

你可以先使用电脑上的图片进行测试。

例如,准备一张 test.jpg,然后使用 ROS 自带的 image_publisher 发布图片:

rosrun image_publisher image_publisher \
  /绝对路径/test.jpg

安装命令:

sudo apt install ros-noetic-image-publisher

注意,不同版本的 image_publisher 参数形式可能有所区别,可以先执行:

rosrun image_publisher image_publisher --help

确认参数格式。

然后启动前面的 image_processor 节点。

如果发布的图像话题名称不是 /camera/image_raw,需要将代码中的订阅话题修改为实际名称。


六、通过这个例子,你应该理解什么?

操作使用的技术作用
接收图像 ROS Subscriber 获取 ROS 图像消息
toCvCopy() cv_bridge 将 ROS 图像转换为 OpenCV 图像
cv::cvtColor() OpenCV 完成灰度化处理
toImageMsg() cv_bridge 将 OpenCV 图像封装为 ROS 消息
publish() ROS Publisher 发布处理后的图像

你可以把整个程序理解为三个模块协作:

ROS 负责通信,cv_bridge 负责适配,OpenCV 负责处理。

对于你后续学习机器人视觉,这种设计很重要:你可以更换摄像头、替换图像处理算法,或者把图像处理模块部署到其他节点,而不必将所有功能耦合在一起。

另外,这个示例是 ROS1 Noetic 版本。如果以后使用 ROS2,整体思路不变,但节点接口、构建系统和消息发布订阅 API 都会有所不同。

posted @ 2026-10-25 12:06  lvdongjie-avatarx  阅读(3)  评论(0)    收藏  举报