ROS学习笔记15:ROS与OpenCV结合处理图像

这篇具有很好参考价值的文章主要介绍了ROS学习笔记15:ROS与OpenCV结合处理图像。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、安装ROS-OpenCV

  安装OpenCVsudo apt-get install ros-kinetic-vision-opencv libopencv-dev python-opencv
  ROS进行图像处理是依赖于OpenCV库的。ROS通过一个叫CvBridge的功能包,将获取的图像数据转换成OpenCV的格式,OpenCV处理之后,传回给ROS进行图像显示(应用),如下图:
ROS学习笔记15:ROS与OpenCV结合处理图像

二、简单案例分析

  我们使用ROS驱动获取摄像头数据,将ROS获得的数据通过CvBridge转换成OpenCV需要的格式,调用OpenCV的算法库对这个图片进行处理(如画一个圆),然后返回给ROS进行rviz显示。

1.usb_cam.launch

  首先我们建立一个launch文件,可以调用摄像头驱动获取图像数据。运行launch文件roslaunch xxx(功能包名) usb_cam.launch

<launch>
    <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" >
      <param name="video_device" value="/dev/video0" />
      <param name="image_width" value="1280" />
      <param name="image_height" value="720" />
      <param name="pixel_format" value="yuyv" />
      <param name="camera_frame_id" value="usb_cam" />
      <param name="io_method" value="mmap"/>
    </node>
</launch>

2.cv_bridge_test.py

  建立一个py文件,是python2的。实现接收ROS发的图像信息,在图像上画一个圆后,返回给ROS。返回的话题名称是cv_bridge_image。运行py文件rosrun xxx(功能包名) cv_bridge_test.py
  如果出现权限不够的情况,记得切换到py文件目录下执行:sudo chmod +x *.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("/usb_cam/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:
            print e

if __name__ == '__main__':
    try:
        # 初始化ros节点
        rospy.init_node("cv_bridge_test")
        rospy.loginfo("Starting cv_bridge_test node")
        image_converter()
        rospy.spin()
    except KeyboardInterrupt:
        print "Shutting down cv_bridge_test node."
        cv2.destroyAllWindows()

3.rqt_image_view

  在终端下执行rqt_image_view,订阅cv_bridge_image话题,可以发现OpenCV处理之后的图像在ROS中显示出来。
ROS学习笔记15:ROS与OpenCV结合处理图像

三、CvBridge相关API

1.imgmsg_to_cv2()

  将ROS图像消息转换成OpenCV图像数据;

# 使用cv_bridge将ROS的图像数据转换成OpenCV的图像格式
try:
    cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")
except CvBridgeError as e:
    print e

2.cv2_to_imgmsg()

  将OpenCV格式的图像数据转换成ROS图像消息;

# 再将opencv格式额数据转换成ros image格式的数据发布
try:
    self.image_pub.publish(self.bridge.cv2_to_imgmsg(cv_image, "bgr8"))
except CvBridgeError as e:
    print e

四、利用ROS+OpenCV实现人脸检测案例

1.usb_cam.launch

  这个launch和上一个案例一样先打开摄像头驱动获取图像数据。运行launch文件roslaunch xxx(功能包名) usb_cam.launch

<launch>
    <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" >
      <param name="video_device" value="/dev/video0" />
      <param name="image_width" value="1280" />
      <param name="image_height" value="720" />
      <param name="pixel_format" value="yuyv" />
      <param name="camera_frame_id" value="usb_cam" />
      <param name="io_method" value="mmap"/>
    </node>
</launch>

2.face_detector.launch

  人脸检测算法采用基于Harr特征的级联分类器对象检测算法,检测效果并不佳。但是这里只是为了演示如何使用ROS和OpenCV进行图像处理,所以不必在乎算法本身效果。整个launch调用了一个py文件和两个xml文件,分别如下:

2.1 launch

(注意py文件和xml文件的存放位置)

<launch>
    <node pkg="robot_vision" name="face_detector" type="face_detector.py" output="screen">
        <remap from="input_rgb_image" to="/usb_cam/image_raw" />
        <rosparam>
            haar_scaleFactor: 1.2
            haar_minNeighbors: 2
            haar_minSize: 40
            haar_maxSize: 60
        </rosparam>
        <param name="cascade_1" value="$(find robot_vision)/data/haar_detectors/haarcascade_frontalface_alt.xml" />
        <param name="cascade_2" value="$(find robot_vision)/data/haar_detectors/haarcascade_profileface.xml" />
    </node>
</launch>

2.2 face_detector.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
import cv2
import numpy as np
from sensor_msgs.msg import Image, RegionOfInterest
from cv_bridge import CvBridge, CvBridgeError

class faceDetector:
    def __init__(self):
        rospy.on_shutdown(self.cleanup);

        # 创建cv_bridge
        self.bridge = CvBridge()
        self.image_pub = rospy.Publisher("cv_bridge_image", Image, queue_size=1)

        # 获取haar特征的级联表的XML文件,文件路径在launch文件中传入
        cascade_1 = rospy.get_param("~cascade_1", "")
        cascade_2 = rospy.get_param("~cascade_2", "")

        # 使用级联表初始化haar特征检测器
        self.cascade_1 = cv2.CascadeClassifier(cascade_1)
        self.cascade_2 = cv2.CascadeClassifier(cascade_2)

        # 设置级联表的参数,优化人脸识别,可以在launch文件中重新配置
        self.haar_scaleFactor  = rospy.get_param("~haar_scaleFactor", 1.2)
        self.haar_minNeighbors = rospy.get_param("~haar_minNeighbors", 2)
        self.haar_minSize      = rospy.get_param("~haar_minSize", 40)
        self.haar_maxSize      = rospy.get_param("~haar_maxSize", 60)
        self.color = (50, 255, 50)

        # 初始化订阅rgb格式图像数据的订阅者,此处图像topic的话题名可以在launch文件中重映射
        self.image_sub = rospy.Subscriber("input_rgb_image", Image, self.image_callback, queue_size=1)

    def image_callback(self, data):
        # 使用cv_bridge将ROS的图像数据转换成OpenCV的图像格式
        try:
            cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")     
            frame = np.array(cv_image, dtype=np.uint8)
        except CvBridgeError, e:
            print e

        # 创建灰度图像
        grey_image = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        # 创建平衡直方图,减少光线影响
        grey_image = cv2.equalizeHist(grey_image)

        # 尝试检测人脸
        faces_result = self.detect_face(grey_image)

        # 在opencv的窗口中框出所有人脸区域
        if len(faces_result)>0:
            for face in faces_result: 
                x, y, w, h = face
                cv2.rectangle(cv_image, (x, y), (x+w, y+h), self.color, 2)

        # 将识别后的图像转换成ROS消息并发布
        self.image_pub.publish(self.bridge.cv2_to_imgmsg(cv_image, "bgr8"))

    def detect_face(self, input_image):
        # 首先匹配正面人脸的模型
        if self.cascade_1:
            faces = self.cascade_1.detectMultiScale(input_image, 
                    self.haar_scaleFactor, 
                    self.haar_minNeighbors, 
                    cv2.CASCADE_SCALE_IMAGE, 
                    (self.haar_minSize, self.haar_maxSize))
                                         
        # 如果正面人脸匹配失败,那么就尝试匹配侧面人脸的模型
        if len(faces) == 0 and self.cascade_2:
            faces = self.cascade_2.detectMultiScale(input_image, 
                    self.haar_scaleFactor, 
                    self.haar_minNeighbors, 
                    cv2.CASCADE_SCALE_IMAGE, 
                    (self.haar_minSize, self.haar_maxSize))
        
        return faces

    def cleanup(self):
        print "Shutting down vision node."
        cv2.destroyAllWindows()

if __name__ == '__main__':
    try:
        # 初始化ros节点
        rospy.init_node("face_detector")
        faceDetector()
        rospy.loginfo("Face detector is started..")
        rospy.loginfo("Please subscribe the ROS image.")
        rospy.spin()
    except KeyboardInterrupt:
        print "Shutting down face detector node."
        cv2.destroyAllWindows()

2.3 两个xml文件

链接

3.rqt_image_view

  运行完上述两个launch文件后,在终端下执行rqt_image_view,订阅cv_bridge_image话题,可以发现OpenCV处理之后的图像在ROS中显示出来。
ROS学习笔记15:ROS与OpenCV结合处理图像

五、利用ROS+OpenCV实现帧差法物体追踪

1.usb_cam.launch

  这个launch和前两个案例一样先打开摄像头驱动获取图像数据。运行launch文件roslaunch xxx(功能包名) usb_cam.launch

<launch>
    <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" >
      <param name="video_device" value="/dev/video0" />
      <param name="image_width" value="1280" />
      <param name="image_height" value="720" />
      <param name="pixel_format" value="yuyv" />
      <param name="camera_frame_id" value="usb_cam" />
      <param name="io_method" value="mmap"/>
    </node>
</launch>

2.motion_detector.launch

  物体追踪方法采用帧差法,追踪效果并不佳。但是这里只是为了演示如何使用ROS和OpenCV进行图像处理,所以不必在乎算法本身效果。整个launch调用了一个py文件,如下:

2.1 launch

<launch>
    <node pkg="robot_vision" name="motion_detector" type="motion_detector.py" output="screen">
        <remap from="input_rgb_image" to="/usb_cam/image_raw" />
        <rosparam>
            minArea: 500
            threshold: 25
        </rosparam>
    </node>
</launch>

2.1 motion_detector.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
import cv2
import numpy as np
from sensor_msgs.msg import Image, RegionOfInterest
from cv_bridge import CvBridge, CvBridgeError

class motionDetector:
    def __init__(self):
        rospy.on_shutdown(self.cleanup);

        # 创建cv_bridge
        self.bridge = CvBridge()
        self.image_pub = rospy.Publisher("cv_bridge_image", Image, queue_size=1)

        # 设置参数:最小区域、阈值
        self.minArea   = rospy.get_param("~minArea",   500)
        self.threshold = rospy.get_param("~threshold", 25)

        self.firstFrame = None
        self.text = "Unoccupied"

        # 初始化订阅rgb格式图像数据的订阅者,此处图像topic的话题名可以在launch文件中重映射
        self.image_sub = rospy.Subscriber("input_rgb_image", Image, self.image_callback, queue_size=1)

    def image_callback(self, data):
        # 使用cv_bridge将ROS的图像数据转换成OpenCV的图像格式
        try:
            cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")     
            frame = np.array(cv_image, dtype=np.uint8)
        except CvBridgeError, e:
            print e

        # 创建灰度图像
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        gray = cv2.GaussianBlur(gray, (21, 21), 0)

        # 使用两帧图像做比较,检测移动物体的区域
        if self.firstFrame is None:
            self.firstFrame = gray
            return  
        frameDelta = cv2.absdiff(self.firstFrame, gray)
        thresh = cv2.threshold(frameDelta, self.threshold, 255, cv2.THRESH_BINARY)[1]

        thresh = cv2.dilate(thresh, None, iterations=2)
        binary, cnts, hierarchy= cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

        for c in cnts:
            # 如果检测到的区域小于设置值,则忽略
            if cv2.contourArea(c) < self.minArea:
               continue 

            # 在输出画面上框出识别到的物体
            (x, y, w, h) = cv2.boundingRect(c)
            cv2.rectangle(frame, (x, y), (x + w, y + h), (50, 255, 50), 2)
            self.text = "Occupied"

        # 在输出画面上打当前状态和时间戳信息
        cv2.putText(frame, "Status: {}".format(self.text), (10, 20),
            cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)

        # 将识别后的图像转换成ROS消息并发布
        self.image_pub.publish(self.bridge.cv2_to_imgmsg(frame, "bgr8"))

    def cleanup(self):
        print "Shutting down vision node."
        cv2.destroyAllWindows()

if __name__ == '__main__':
    try:
        # 初始化ros节点
        rospy.init_node("motion_detector")
        rospy.loginfo("motion_detector node is started...")
        rospy.loginfo("Please subscribe the ROS image.")
        motionDetector()
        rospy.spin()
    except KeyboardInterrupt:
        print "Shutting down motion detector node."
        cv2.destroyAllWindows()

3.rqt_image_view

  运行完上述两个launch文件后,在终端下执行rqt_image_view,订阅cv_bridge_image话题,可以发现OpenCV处理之后的图像在ROS中显示出来。(鉴于我的测试环境比较糟糕,并且这个算法本身精度不高,就不展示最终效果了)文章来源地址https://www.toymoban.com/news/detail-451961.html

到了这里,关于ROS学习笔记15:ROS与OpenCV结合处理图像的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数字图像处理第三章 学习笔记附部分例子代码(C++ & opencv)

    本系列博客参考书为, 数字图像处理第三版-冈萨雷斯 第三版教材中图片下载地址: book images downloads vs2019配置opencv可以查看:VS2019 Opencv4.5.4配置教程 后续剧情: 数字图像处理 第四章 频率域滤波 学习笔记 数字图像处理 第六章 彩色图像处理 学习笔记 数字图像处理 第七章 小

    2024年02月03日
    浏览(82)
  • 随手笔记——通过OpenCV获取图像转为ROS图像话题发布(C++版)

    通过OpenCV获取图像转为ROS图像话题发布 注:sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), “bgr8”, image).toImageMsg(); //核心代码

    2024年02月12日
    浏览(34)
  • Opencv-C++笔记 (15) : 像素重映射 与 图像扭曲

    重映射,就是把一幅图像中某位置的像素放置到另一图像指定位置的过程。即: 在重映射过程中,图像的大小也可以同时发生改变。此时像素与像素之间的关系就不是一一对应关系,因此在重映射过程中,可能会涉及到像素值的插值计算。 头文件 quick_opencv.h:声明类与公共

    2024年02月13日
    浏览(52)
  • opencv(15) 图像平滑处理之二:cv2.GaussianBlur()高斯滤波

    高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。 高斯模板是通过对二维高斯函数进行采样(高斯模糊的卷积核里的数值满足高斯分布)、量化并归一化得到的,它考虑了邻域像素位置的影响,距离当前被平滑像素越近的点,加权系数越大

    2024年02月10日
    浏览(57)
  • 数字图像处理 - 图像处理结合机器学习的应用示例

            在本文中,特别关注树叶分类机器学习技术的实现。我们的目标是演示如何利用机器学习算法来分析一系列叶子照片,从而实现准确分类并提供对植物领域有价值的算法。         图像处理中机器学习的本质         机器学习使计算机能够学习模式并根据

    2024年02月13日
    浏览(47)
  • 【高性能计算】opencl语法及相关概念(四):结合opencv进行图像高斯模糊处理

    高斯模糊是一种常用的图像处理技术,用于减少图像中的噪点和细节,并实现图像的平滑效果。它是基于高斯函数的卷积操作,通过对每个像素周围的邻域像素进行加权平均来实现模糊效果。 具体而言,高斯模糊通过在图像上滑动一个卷积核,将卷积核与输入图像的对应像素

    2024年02月10日
    浏览(56)
  • 【计算机视觉—python 】 图像处理入门教程 —— 图像属性、像素编辑、创建与复制、裁剪与拼接【 openCV 学习笔记 005 to 010 and 255】

    OpenCV中读取图像文件后的数据结构符合Numpy的ndarray多维数组结构,因此 ndarray 数组的属性和操作方法可用于图像处理的一些操作。数据结构如下图所示: img.ndim:查看代表图像的维度。彩色图像的维数为3,灰度图像的维度为2。 img.shape:查看图像的形状,代表矩阵的行数(高

    2024年01月19日
    浏览(70)
  • Opencv+Python笔记(五)图像阈值化处理

    图像阈值化可以理解为一个简单的图像分割操作,阈值又称为临界值,它的目的是确定出一个范围,然后这个范围内的像素点使用同一种方法处理,而阈值之外的部分则使用另一种处理方法或保持原样。 阈值处理有2种方式,一种是固定阈值方式,又包括多种处理模式,另一

    2023年04月26日
    浏览(41)
  • ROS高效进阶第四章 -- 机器视觉处理之图像格式,usb_cam,摄像头标定,opencv和cv_bridge引入

    从本文开始,我们用四篇文章学习ROS机器视觉处理,本文先学习一些外围的知识,为后面的人脸识别,目标跟踪和yolov5目标检测做准备。 我的笔记本是Thinkpad T14 i7 + Nvidia MX450,系统是ubuntu20.04,ros是noetic。由于很多驱动与硬件强相关,请读者注意这点。 本文的参考资料有:

    2024年02月04日
    浏览(45)
  • 实验二 ROS结合OpenCV示例——人脸识别

    Opencv库是一个基于BSD许可发行的跨平台开源计算机视觉库,基于opencv库,可以很方便的入手机器视觉方面的应用,ros已经集成了opencv库和相关接口功能包; 人脸识别的目的是在输入图像中确定人脸的位置、大小、姿态。利用大量样本的Haar特征进行分类器训练,然后调用训练

    2024年02月09日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包