ROS通过话题发布订阅Image类型的视频帧(python)

ROS通过话题发布订阅Image类型的视频帧(python)

前言:

本文中,主要是关于OpenCV格式图片(或视频帧)和ROS数据格式图片(或视频帧)之间的转换。或者直白点书,通过ROS发送图片(Image)数据类型的消息(message)

本文其实是为下一篇博文“YOLOROS下的使用”打下基础。

1、使用环境和平台

ubuntu 18.04+ python2.7+opencv3

注意:使用python3的话提示报错,还是用python2
2、示例代码

其实,下述代码完全可以在一个脚本中完成,而且不需要结合ROS;本文为了讲述通过ROS发送Image的方法,故而拆分开来。一个脚本中,只进行图像捕捉;另一个订阅之后,只进行图像现实。

(1)通过调用webcam捕捉视频,然后经过ROSTopic发布出去:

#!/usr/bin/env python
#!coding=utf-8
 
#write by leo at 2018.04.26
#function: 
#1, Get live_video from the webcam.
#2, With ROS publish Image_info (to yolo and so on).
#3, Convert directly, don't need to save pic at local.
 
import rospy
from sensor_msgs.msg import Image
import cv2
import numpy as np
from cv_bridge import CvBridge, CvBridgeError
import sys
 
 
def webcamImagePub():
    # init ros_node
    rospy.init_node('webcam_puber', anonymous=True)
    # queue_size should be small in order to make it 'real_time'
    # or the node will pub the past_frame
    img_pub = rospy.Publisher('webcam/image_raw', Image, queue_size=2)
    rate = rospy.Rate(5) # 5hz
 
    # make a video_object and init the video object
    cap = cv2.VideoCapture(0)
    # define picture to_down' coefficient of ratio
    scaling_factor = 0.5
    # the 'CVBridge' is a python_class, must have a instance.
    # That means "cv2_to_imgmsg() must be called with CvBridge instance"
    bridge = CvBridge()
 
    if not cap.isOpened():
        sys.stdout.write("Webcam is not available !")
        return -1
 
    count = 0
    # loop until press 'esc' or 'q'
    while not rospy.is_shutdown():
        ret, frame = cap.read()
        # resize the frame
        if ret:
            count = count + 1
        else:
            rospy.loginfo("Capturing image failed.")
        if count == 2:
            count = 0
            frame = cv2.resize(frame,None,fx=scaling_factor,fy=scaling_factor,interpolation=cv2.INTER_AREA)
            msg = bridge.cv2_to_imgmsg(frame, encoding="bgr8")
            img_pub.publish(msg)
            print '** publishing webcam_frame ***'	
        rate.sleep()
 
if __name__ == '__main__':
    try:
        webcamImagePub()
    except rospy.ROSInterruptException:
        pass

(2)通过ROS订阅Image类型的视频帧,然后在窗口显示出来:

#!/usr/bin/env python
#!coding=utf-8
 
#right code !
#write by leo at 2018.04.26
#function: 
#display the frame from another node.
 
import rospy
import numpy as np
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError
import cv2
 
def callback(data):
    # define picture to_down' coefficient of ratio
    scaling_factor = 0.5
    global count,bridge
    count = count + 1
    if count == 1:
        count = 0
        cv_img = bridge.imgmsg_to_cv2(data, "bgr8")
        cv2.imshow("frame" , cv_img)
        cv2.waitKey(3)
    else:
        pass
 
def displayWebcam():
    rospy.init_node('webcam_display', anonymous=True)
 
    # make a video_object and init the video object
    global count,bridge
    count = 0
    bridge = CvBridge()
    rospy.Subscriber('webcam/image_raw', Image, callback)
    rospy.spin()
 
if __name__ == '__main__':
    displayWebcam()
 

当然,上面话题发布之后,也可以使用RVIZ工具箱的image工具进行显示

3、代码解释(函数讲解)

从代码中可以看出:

from cv_bridge import CvBridge, CvBridgeError

导入了一个模块下的两个类,然后实例化一个对象:

bridge = CvBridge()

接下来,调用该对象下的方法(函数):

msg = bridge.cv2_to_imgmsg(frame, encoding="bgr8")
img_pub.publish(msg)

发布信息的脚本(上程序(1)中)里,利用此方法将OpenCV类型的图片转化为ROS类型,然后通过话题发布出去;

然后:

cv_img = bridge.imgmsg_to_cv2(data, "bgr8")

订阅话题的脚本(上程序(2)中)里,利用此方法将订阅到的ROS类型的数据转化为OpenCV格式的图片,然后通过imshow函数在窗口显示出图像。

PS:上边的程序中,不论发布还是订阅,都可以跳过一些帧(通过改变count的值即可)。

4、参考链接

ROS初学者教程:

http://wiki.ros.org/cn/ROS/Tutorials

OpnCV-Python教程:

https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_tutorials.html

Converting between ROS images and OpenCV images (Python)
https://answers.ros.org/question/226819/trouble-converting-cv2-to-imgmsg/
http://wiki.ros.org/cv_bridge/Tutorials/ConvertingBetweenROSImagesAndOpenCVImagesPython

https://github.com/pirobot/ros-by-example/blob/master/rbx_vol_1/rbx1_vision/nodes/cv_bridge_demo.py

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/2145.html原文链接:https://javaforall.net

(0)
上一篇 2020年11月8日 下午9:33
下一篇 2020年11月8日 下午9:33


相关推荐

  • Futex系统调用,Futex机制,及具体案例分析[通俗易懂]

    Futex系统调用,Futex机制,及具体案例分析[通俗易懂]Futex1、背景1.1自己实现锁1.1.1自旋锁1.1.2sleep+自旋1.1.3小结1.2futex1.2.1什么是Futex1.2.2futex诞生之前1.2.3futex诞生之后2、Futex系统调用3、Futex机制4、具体案例分析4.1在Bionic中的实现4.2C语言实现5、参考及扩展阅读首先要区分一下futex系统调用和futex机制。futex系统调用是操作系统提供给上层的系统调用接口。而futex机制是使用futex接口实现的一种锁。1、背景线程同步可以说

    2026年2月8日
    3
  • 即梦ai最苹果版 v2.0.9 ios版

    即梦ai最苹果版 v2.0.9 ios版

    2026年3月12日
    3
  • Ping和traceroute的原理

    Ping和traceroute的原理ping 原理 ping 主要是用来探测主机和主机之间是否可以进行通信 如果不能 ping 到某台主机 表示不能与这台主机建立连接 ping 使用的是 ICMP 协议 他发送 ICMP 回送请求消息给目的主机 ICMP 协议规定 目的主机必须返回 ICMP 回送应答消息给源主机 如果源主机在一定时间内收到应答 表明主机可达 ICMP 协议是通过 IP 协议发送的 IP 协议是无连接的 不可靠的数据报协议 ping 是用来检测网络是否畅通或者网络连接速度的命令在同一网段内 在主机 A 上运行 Ping192 168 0 5 后 都发生

    2026年3月26日
    1
  • 【教程】最简单的Claude Code Router(ccr)配置教程,低成本使用claude code

    【教程】最简单的Claude Code Router(ccr)配置教程,低成本使用claude code

    2026年3月16日
    3
  • 【POI框架实战】——POI导出Excel时设置单元格类型为数值类型

    【POI框架实战】——POI导出Excel时设置单元格类型为数值类型最近做的一个 ITFIN 的项目中 导出的数据中有文本格式 也有货币格式 所以为了方便在将来导出的表格中做计算 存放货币先用正则表达式判断数据是否为数值型 如果为数值型 则设置单元格格式为整数或者小数 然后往单元格中存放数据的时候要设置数据的格式为 double 类型 如果查看 poi 的源码 HSSFCell java 会发现设置数据的方法如下 所以用 setCellValue double 方法即可

    2026年3月18日
    3
  • android开发之AIDL用法_进程间通信原理详解

    转自http://blog.csdn.net/saintswordsman/article/details/5130947欢迎阅读本文,你能关注本文,你知道你需要进程间通信、需要AIDL(以及Binder),那么可以默认你对这些概念已经有了一些了解,你(大致)知道它们是什么,它们有什么用,所以为了节约大家的眼力和时间,在此我不复制粘贴网上泛滥的博客或者翻译冗长的android文档。

    2022年3月10日
    41

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号