Ros-Kinetic<使用cv_bridge进行OpenCV和ROS图像处理>

1.环境准备

Ubuntu16.04
ROS-kinetic
opencv3.3.1
video-stream-opencv
一个USB摄像头

video-stream-opencv是USB摄像头驱动,关于它的介绍,请看github:https://github.com/ros-drivers/video_stream_opencv

安装video-stream-opencv

cd ~/catkin_ws/src/
git clone https://github.com/ros-drivers/video_stream_opencv.git
cd ~/catkin_ws/
catkin_make

测试是否安装成功

在终端输入:

rosrun video_stream_opencv test_video_resource.py

如果能从摄像头中看到影像说明安装成功。

2.opencv格式的图片与ROS中Image-message之间的相互转换

ROS image消息类型到opencv类型的转换:

cv_image = bridge.imgmsg_to_cv2(image_message, desired_encoding="passthrough")

Opencv类型到ROS Image类型的转换:

image_message = cv2_to_imgmsg(cv_image, encoding="passthrough")

3.目标

接下来要完成使用Opencv获取图片,通过ROS的publisher(web_cam)发布图片到image_topic主题下,然后有一个新的listener(image-converter)订阅这个topic,并在图片中的制定位置画出一个实心圆。

这里写图片描述

4.发布者

在video_stream_opencv这个package下有一个test_video_resource.py,这个文件的 原始作用只是简单的将OpenCv获取到的图片显示出来,这里我们要做的是通过这个node,将获取到的图片发布到image_topic下去,以下是我修改过的 test_video_resource.py:

#! /usr/bin/env python2
# -*- coding: utf-8 -*-
"""

Copyright (c) 2015 PAL Robotics SL.
Released under the BSD License.

Created on 7/14/15

@author: Sammy Pfeiffer

test_video_resource.py contains
a testing code to see if opencv can open a video stream
useful to debug if video_stream does not work
"""

import sys
import signal
import cv2
import rospy
from cv_bridge import CvBridge, CvBridgeError
from sensor_msgs.msg import Image


def quit(signum, frame):
    print ''
    print 'stop fusion'
    sys.exit()


if __name__ == '__main__':
    signal.signal(signal.SIGINT, quit)
    signal.signal(signal.SIGTERM, quit)
    # 参数的长度
    if len(sys.argv) < 2:
        print "You must give an argument to open a video stream."
        print "  It can be a number as video device, e.g.: 0 would be /dev/video0"
        print "  It can be a url of a stream,        e.g.: rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"
        print "  It can be a video file,             e.g.: myvideo.mkv"
        exit(0)

    resource = sys.argv[1]
    # If we are given just a number, interpret it as a video device
    if len(resource) < 3:
        resource_name = "/dev/video" + resource
        resource = int(resource)
    else:
        resource_name = resource
    print "Trying to open resource: " + resource_name
    cap = cv2.VideoCapture(resource)
    if not cap.isOpened():
        print "Error opening resource: " + str(resource)
        print "Maybe opencv VideoCapture can't open it"
        exit(0)
    bridge = CvBridge()
    publisher = rospy.Publisher('image_topic', Image, queue_size=10)
    rospy.init_node('web_cam')
    print "Correctly opened resource, starting to show feed."
    rval, frame = cap.read()

    while rval:
        # 将opencv格式的图片转换为ROS可接受的msg
        image_message = bridge.cv2_to_imgmsg(frame, encoding="bgr8")
        try:
            publisher.publish(image_message)
        except CvBridgeError as e:
            print(e)
        rval, frame = cap.read()

以上代码不做过多解释,都比较简单。特别指出以下代码是为了坚挺键盘当用户输入Ctrl+c的时候节点终止

def quit(signum, frame):
    print ''
    print 'stop fusion'
    sys.exit()


if __name__ == '__main__':
    signal.signal(signal.SIGINT, quit)
    signal.signal(signal.SIGTERM, quit)
    ...

    while rval:
        ...

5.订阅者

订阅者的作用就是上边说的从image-topic中订阅消息,然后将其转换为opencv格式的图片,然后在图片中画出一个实心圆,在与发布者相同的文件夹下创建一个web_cam_listener.py:

#!/usr/bin/env python
import roslib

roslib.load_manifest('video_stream_opencv')
import rospy
import cv2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError


class image_converter:

    def __init__(self):
        self.bridge = CvBridge()
        self.image_sub = rospy.Subscriber("image_topic", Image, self.callback)

    def callback(self, data):
        try:
            cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")
        except CvBridgeError as e:
            print(e)

        (rows, cols, channels) = cv_image.shape
        if cols > 60 and rows > 60:
            cv2.circle(cv_image, (150, 150), 20, (30, 144, 255), -1)
        cv2.imshow("Image window", cv_image)
        cv2.waitKey(3)


if __name__ == '__main__':
    ic = image_converter()
    rospy.init_node('image_converter')
    try:
        rospy.spin()
    except KeyboardInterrupt:
        print("Shutting down")
    cv2.destroyAllWindows()

6.运行节点

  • 启动第一个终端输入roscore;
  • 启动(publisher)第二个终端输入rosrun video_stream_opencv test_video_resource.py 0
    得到如下输出:
xzchuang@Vostro:~/catkin_ws$ rosrun video_stream_opencv test_video_resource.py 0Trying to open resource: /dev/video0
Correctly opened resource, starting to show feed.
  • 启动(Subscriber)启动第三个终端输入:
rosrun video_stream_opencv web_cam_listener.py

这时候会在摄像头输入中画一个实心圆(橙色),然后显示出来,如图:
这里写图片描述

  • 启动一个新的终端调用rqt-graph插件:rosrun rqt_graph rqt_graph

这里写图片描述

<think>我们正在解决一个ROS2编译错误:在构建armor_detector项目时,出现`cv_bridge/cv_bridge.h`文件未找到的错误。 根据引用内容,我们注意到在ROS1中类似问题的解决方案,但ROS2的环境构建工具有所不同。不过,问题的本质可能相似:缺少opencv相关依赖或路径配置问题。 步骤分析: 1. 错误信息:`fatal error: cv_bridge/cv_bridge.h: No such file or directory` 表明编译器在查找cv_bridge头文件时失败。 2. 可能原因: - 没有安装cv_bridge包。 - 安装的cv_bridge包与ROS2版本不兼容。 - 项目的依赖配置中没有正确声明对cv_bridge的依赖。 - CMakeLists.txt中没有正确包含cv_bridge的头文件路径。 3. 解决方案: a. 确保安装了ROS2cv_bridge包。在ROS2中,cv_bridge包属于vision_opencv仓库,可以通过apt安装。 命令:`sudo apt install ros-<distro>-vision-opencv` 其中`<distro>`是你的ROS2发行版名称(如foxy、humble等)。 b. 在项目的package.xml文件中,添加对cv_bridge的依赖。 例如:`<depend>cv_bridge</depend>` c. 在CMakeLists.txt中,确保通过`find_package`查找cv_bridge,并将其包含路径添加到目标包含目录。 例如: ``` find_package(cv_bridge REQUIRED) ... include_directories( include ${cv_bridge_INCLUDE_DIRS} ) ``` 同时,在链接目标时,将cv_bridge添加到`ament_target_dependencies`或`target_link_libraries`中。 例如: ``` ament_target_dependencies(your_target cv_bridge ... ) ``` d. 如果仍然遇到问题,检查cv_bridge安装路径。在ROS2中,头文件通常位于`/opt/ros/<distro>/include/`下,可以确认该路径下是否存在`cv_bridge`目录。 e. 如果以上步骤无法解决,考虑环境问题。确保在colcon工作空间中,已经通过`source /opt/ros/<distro>/setup.bash`设置了环境。 f. 引用[4]提到在ROS1中通过添加绝对路径`/opt/ros/kinetic/include`来解决类似问题。在ROS2中,我们通常不需要这样做,因为通过`find_package``ament_target_dependencies`可以自动处理。但是,如果自动查找失败,可以尝试手动添加包含路径: 在CMakeLists.txt中添加: ``` include_directories(/opt/ros/<distro>/include) ``` 4. 注意:ROS2使用ament_cmake,其CMakeLists的写法与ROS1的catkin略有不同。 5. 如果问题仍然存在,可能需要检查cv_bridge是否确实安装成功。可以尝试在终端中直接查看头文件是否存在: ``` ls /opt/ros/<distro>/include/cv_bridge/ ``` 如果不存在,则需要重新安装。 6. 另外,引用[3]提到在ROS1中修改cv_bridgeConfig.cmake文件的方法。在ROS2中,我们通常不推荐手动修改安装包的文件,因为这样可能会破坏包的完整性。但作为最后的手段,可以检查该文件(位于`/opt/ros/<distro>/share/cv_bridge/cmake/cv_bridgeConfig.cmake`)中关于opencv路径的配置是否正确。 7. 如果项目需要特定版本的OpenCV,而系统中有多个OpenCV版本,可能需要设置OpenCV_DIR环境变量指向正确的OpenCV版本。 由于用户使用的是colcon构建工具,我们按照ROS2的标准构建流程进行配置。 下面是一个具体的解决方案示例: 步骤1:安装cv_bridge ``` sudo apt update sudo apt install ros-<distro>-cv-bridge ``` 步骤2:在package.xml中添加依赖 在`<depend>...</depend>`部分添加: ``` <depend>cv_bridge</depend> ``` 步骤3:修改CMakeLists.txt 确保包含以下内容: ``` cmake_minimum_required(VERSION 3.5) project(armor_detector) # 默认使用C++14 if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) endif() # 查找依赖包 find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(cv_bridge REQUIRED) find_package(sensor_msgs REQUIRED) # 添加头文件目录 include_directories( include ${cv_bridge_INCLUDE_DIRS} ) # 添加可执行文件 add_executable(armor_detector_node src/armor_detector_node.cpp) # 链接依赖 ament_target_dependencies(armor_detector_node rclcpp cv_bridge sensor_msgs ) # 安装 install(TARGETS armor_detector_node DESTINATION lib/${PROJECT_NAME}) # 导出依赖 ament_package() ``` 步骤4:重新构建 回到工作空间根目录,运行: ``` colcon build --symlink-install ``` 如果问题仍然存在,请提供具体的ROS2发行版错误信息,以便进一步排查。 相关问题: 1. 如何检查ROS2中一个包是否安装成功? 2.ROS2中,如何正确配置CMakeLists.txt来使用第三方库? 3. ROS2的colcon构建工具常见错误有哪些? 4. 如何解决ROS2中多个OpenCV版本冲突的问题?</think>### ROS2 armor_detector 编译错误:cv_bridge/cv_bridge.h not found 解决方案 #### 错误原因分析 该错误通常发生在以下情况: 1. **缺少 OpenCV 依赖**:`cv_bridge` 需要 OpenCV 核心库支持,但系统未正确安装或配置 2. **路径配置错误**:CMake 无法定位 `cv_bridge` 的头文件路径 3. **ROS2 环境未完全配置**:工作空间未正确链接到 ROS2 核心库 4. **包依赖声明缺失**:`package.xml` 或 `CMakeLists.txt` 中未声明对 `cv_bridge` 的依赖[^1][^2] --- ### 完整解决方案 #### 步骤 1:安装缺失依赖 ```bash # 安装 ROS2 cv_bridge OpenCV 核心包 sudo apt install ros-${ROS_DISTRO}-cv-bridge ros-${ROS_DISTRO}-vision-opencv # 安装开发工具链 sudo apt install libopencv-dev ``` 将 `${ROS_DISTRO}` 替换为你的 ROS2 版本(如 `humble`, `foxy`) #### 步骤 2:修改 CMakeLists.txt 在项目 `CMakeLists.txt` 中添加以下配置: ```cmake find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(cv_bridge REQUIRED) # 添加 cv_bridge 依赖查找 # 添加头文件路径 include_directories( include ${cv_bridge_INCLUDE_DIRS} # 关键配置 /opt/ros/${ROS_DISTRO}/include # 显式添加 ROS2 包含路径 ) # 链接目标时添加依赖 ament_target_dependencies(your_target rclcpp cv_bridge # 必须添加 ) ``` #### 步骤 3:更新 package.xml 在 `package.xml` 中添加依赖声明: ```xml <depend>cv_bridge</depend> <depend>vision_opencv</depend> <depend>sensor_msgs</depend> <!-- 通常需要图像消息支持 --> ``` #### 步骤 4:环境配置与编译 ```bash # 加载 ROS2 基础环境 source /opt/ros/${ROS_DISTRO}/setup.bash # 在工作空间重新编译 colcon build --symlink-install --packages-select armor_detector # 加载工作空间环境 source install/setup.bash ``` #### 步骤 5:验证安装路径 检查头文件是否存在: ```bash ls /opt/ros/${ROS_DISTRO}/include/cv_bridge/ # 应看到 cv_bridge.h 等文件 ``` #### 备选方案:手动包含路径 如果仍报错,在 CMakeLists.txt 中显式添加绝对路径: ```cmake include_directories(/opt/ros/${ROS_DISTRO}/include) ``` --- ### 常见问题排查 1. **版本冲突**:确保所有 OpenCV 相关包来自同一源(建议使用 ROS 官方源) 2. **多版本 OpenCV**:若有多个 OpenCV 版本,设置环境变量: ```bash export OpenCV_DIR=/usr/local/opencv-4.x/share/OpenCV ``` 3. **工作空间覆盖**:检查是否覆盖了系统包: ```bash echo $ROS_PACKAGE_PATH ``` > 提示:在 ROS2 中,`cv_bridge` 需要与 ROS2 消息系统配合使用,确保正确包含 `sensor_msgs` 相关依赖[^4]。 --- ### 相关问题 1. 如何解决 ROS2 中其他 OpenCV 相关包的类似错误? 2. 当系统中存在多个 OpenCV 版本时,如何确保 ROS2 使用正确的版本? 3. 在跨平台开发中,如何保证 cv_bridge 的兼容性? 4. 如何为自定义 OpenCV 版本编译 cv_bridge? [^1]: 编译错误显示缺少 opencv2/core/core.hpp 头文件 [^2]: CMake 报错提示找不到指定的 include 目录 [^3]: 需要手动修改 cv_bridgeConfig.cmake 中的路径配置 [^4]: 通过显式添加 `/opt/ros/kinetic/include` 解决类似问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值