基于ros将文件夹中的图像转换为bag包(c++版本)

news2024/12/1 0:48:56

一、前期工作创建工作空间

 二、创建工作包

创建完成后,文件夹的格式为:

三、准备编译文件和代码

3.1 更换编译文件中的内容

将上图中的,CMakeLists.txt文件中的内容,替换为下面的内容

cmake_minimum_required(VERSION 3.0.2)
project(create_bag)
 
## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)
 
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
# 寻找OpenCV库
find_package( OpenCV  REQUIRED )
# 添加头文件
include_directories( ${OpenCV_INCLUDE_DIRS} )
 
find_package(catkin REQUIRED COMPONENTS
  cv_bridge
  rosbag
  roscpp
  rospy
  std_msgs
)
 
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES imgtobag
#  CATKIN_DEPENDS cv_bridge rosbag roscpp rospy std_msgs
#  DEPENDS system_lib
)
 
###########
## Build ##
###########
 
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
  ${catkin_INCLUDE_DIRS}
  ${catkin_INCLUDE_DIRS}
  ${rosbag_INCLUDE_DIRS}
  ${OpenCV_INCLUDE_DIRS}
)
 
add_executable(node src/torosbag.cpp)
target_link_libraries(node
  ${catkin_LIBRARIES}
  ${PCL_LIBRARIES}
  ${rosbag_LIBRARIES}
  ${OpenCV_LIBS}
)

 3.2 准备主程序

leedarson@leedarson-desktop:~/catkin_ws/src/create_bag/src$ touch torosbag.cpp
创建一个cpp的文件夹,cpp文件中的内容为:

#include <string>
#include <ros/console.h>
#include <rosbag/bag.h>
#include <cv_bridge/cv_bridge.h>
#include <iostream>
#include <vector>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
 
void GetFileNames(string path,vector<string>& filenames, string con);
void GetFileNamesByGlob(cv::String path,vector<cv::String>& filenames, string con);
bool read_images(string path, vector<string> &image_files);
int main(int argc, char **argv)
{
    //输入文件和输出文件路径
    string base_dir = "/home/leedarson/catkin_ws/src/create_bag/data/";
    string img_dir = base_dir + "img/";
    std::cout<<"image path is"<<img_dir<<std::endl;
    string output_bag=base_dir +"Human2.bag";
    string img_format = ".jpg";//格式
    vector<string> img_names;
    //GetFileNames(img_dir, img_names,".jpg");
    read_images(img_dir, img_names);
    cout<<"图片读取完成"<<endl;
 
    cout<<"----"<<endl;
 
    ros::Time::init();
    rosbag::Bag bag;
    bag.open(output_bag, rosbag::bagmode::Write);
    int seq = 0;
    vector<string>::iterator it;
    for(it = img_names.begin(); it != img_names.end();it++)//todo 之后改成图片数量的多少
    {
        string tmp = *it;
        std::cout<<"tmp path is"<<tmp<<std::endl;
        //cout<<tmp<<endl;
        //string strImgFile =  img_dir + tmp + img_format;
        string strImgFile = tmp;
        usleep(200000);//4hz
        ros::Time timestamp_ros = ros::Time::now();
        
        // --- for image ---//
        cv::Mat img = cv::imread(strImgFile);
        if (img.empty())
            cout<<"图片为空: "<<strImgFile<<endl;
        cv_bridge::CvImage ros_image;
        sensor_msgs::ImagePtr ros_image_msg;
 
        ros_image.image = img;
        ros_image.encoding = "bgr8";
        //cout<<"debug_______"<<endl;
        //ros::Time timestamp_ros2 = ros::Time::now();
        ros_image_msg = ros_image.toImageMsg();
        ros_image_msg->header.seq = seq;
        ros_image_msg->header.stamp = timestamp_ros;
        ros_image_msg->header.frame_id = "/image_raw";
 
        bag.write("/camera/color/image_raw", ros_image_msg->header.stamp, ros_image_msg);
        cout<<"write frame: "<<seq<<endl;
        seq++;
    }
 
    cout<<"---end---"<<endl;
 
    return 0;
}
 
//con:文件格式 form:文件命名形式
void GetFileNames(string path,vector<string>& filenames, string con)
{
    DIR *pDir;
    struct dirent* ptr;
    string filename, format, name, name2;
 
    if(!(pDir = opendir(path.c_str())))
        return;
    int num=0;
    while((ptr = readdir(pDir))!=0) 
    {
        //跳过.和..文件
        if(strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0)
            continue;
        filename = ptr->d_name;
        format = filename.substr(filename.find("."), filename.length());
        //name = filename.substr(0, filename.find("."));
        name = filename.substr(0, filename.find("."));
        cout<<filename<<"\t"<<name<<"\t"<<format<<endl;
 
        if(format == con)//也可以添加对文件名的要求
        {
            filenames.push_back(name);
            
            num++;
        }        
    }
    std::cout<<"file size of:"<<filenames.size()<<"****"<<num<<std::endl;
    closedir(pDir);
}

//cv::glob(路径,要放置路径下文件定义的容器,false)
/*find_first_of()和find_last_of() 
执行简单的模式匹配,如在字符串中查找单个字符c:函数find_first_of() 查找在字符串中第1个出现的字符c,而函数find_last_of()查找最后一个出现的c。匹配的位置是返回值。如果没有匹配发生,则函数返回-1*/
//复制子字符串substr(所需的子字符串的起始位置,默认值为0 , 复制的字符数目)返回值:一个子字符串,从其指定的位置开始
//按图片名升序排列
bool read_images(string path, vector<string> &image_files)
{
    //fn存储path目录下所有文件的路径名称,如../images/0001.png
	vector<cv::String> fn;
    cv::glob(path, fn, false);
    size_t count_1 = fn.size();
    if (count_1 == 0)
    {
        cout << "file " << path << " not  exits"<<endl;
        return -1;
    }
    //v1用来存储只剩数字的字符串
    vector<string> v1;
    for (int i = 0; i < count_1; ++i)
    {
        //cout << fn[i] << endl;
        //1.获取不带路径的文件名,000001.jpg(获取最后一个/后面的字符串)
        string::size_type iPos = fn[i].find_last_of('/') + 1;
        string filename = fn[i].substr(iPos, fn[i].length() - iPos);
        //cout << filename << endl;
        //2.获取不带后缀的文件名,000001
        string name = filename.substr(0, filename.rfind("."));
        //cout << name << endl;
        v1.push_back(name);
    }
    //把v1升序排列
    sort(v1.begin(), v1.end(),[](string a, string b) {return stoi(a) < stoi(b); });
    
    string v = ".jpg";
    size_t count_2 = v1.size();
    for(int j = 0; j < count_2; ++j)
    {
        string z = path + v1[j] + v;
        image_files.push_back(z);//把完整的图片名写回来
    }
	return true;
}

四、编译及执行

4.1 编译

4.2 执行 

1,首先打开一个终端,输入roscore,启动ros

 2,打开新的终端,进入工作空间,执行以下语句

leedarson@leedarson-desktop:~/catkin_ws$ source devel/setup.bash
leedarson@leedarson-desktop:~/catkin_ws$ rosrun create_bag node

通过以上操作就可以将文件夹中的图像转换为bag包。

4.3 检测录制的bag包的话题和信息

rostopic list

rostopic echo 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/152159.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【漏洞复现】Yapi接口管理平台RCE漏洞汇总

文章目录前言YApi接口管理平台远程代码执行漏洞一、漏洞描述二、影响版本三、FOFA语句四、漏洞复现五、修复建议YApi NoSQL注入导致远程命令执行漏洞一、YApi介绍二、漏洞描述三、漏洞分析四、漏洞详情五、影响版本六、漏洞复现七、修复建议前言 本篇文章主要归纳总结YApi各版…

南邮数据结构

md文档网址&#xff1a;https://gitee.com/infiniteStars/wang-dao-408-notes/blob/master/408/数据结构.md 1 绪论 1.1算法的基本概念 程序与算法的区别和联系 联系&#xff1a;程序是计算机指令的有序集合&#xff0c;是算法用某种程序设计语言的表述&#xff0c;是算法在…

2023年如何搭建最小可行性的产品文档/产品手册?

在推出并击败竞争对手进入市场的竞赛中&#xff0c;很容易将“不必要的”任务&#xff08;如文档&#xff09;放在次要位置。但根据 Write the Docs 纪录片社区的说法&#xff0c;文档应该既是先导性的&#xff0c;也是参与性的。这意味着您应该在开始开发之前开始记录&#xf…

吊打高斯模糊的stackBlur加入OpenCV

stackBlur介绍 stackBlur 最近才加入到OpenCV中&#xff0c;将在下一个Relase版本&#xff08;4.7&#xff09;中出现。C用户可以尝试从源码编译OpenCV体验一下。Python 用户可以尝试用pip安装rolling版本的OpenCV&#xff1a; pip install opencv-python-rolling4.6.0.202210…

新手教程 | 常见的爬虫类型有哪些?

程序猿圈流传着一个神话级别的事&#xff1a;全公司仅靠1个人&#xff0c;每年就能转上1400多万美元。听起来天方夜谭一样&#xff0c;那他是如何做到的呢&#xff1f;看报道就会发现&#xff0c;他利用的是爬虫技术。 随着互联网的发展&#xff0c;从海量的互联网数据中&…

不可错过,Java程序员必备珍藏书单

不要因为迷茫&#xff0c;而停止了脚下的路。给大家推荐一份Java程序员必看的书单&#xff0c;豆瓣评分都挺不错的&#xff0c;往下看&#xff01; 一、Java 基础篇书单 《Java编程思想》&#xff1a;从Java的基础语法到最高级特性&#xff08;深入的面向对象概念、多线程、自…

煤矿智能化相关50项团体标准征求意见

智能化煤矿总体架构 原文地址&#xff1a;https://chinacs.scimall.org.cn/a3651.html 由煤矿智能化创新联盟等单位提出&#xff0c;中国煤炭学会归口&#xff0c;中煤科工集团常州研究院有限公司等单位起草的《煤矿通信接口与协议通用技术要求》50项团体标准已完成征求意见稿的…

用 Python 脚本实现电脑唤醒后自动拍照 截屏并发邮件通知

背景 背景是这样的, 我的家里台式机常年 休眠, 并配置了 Wake On Lan (WOL) 方便远程唤醒并使用. 但是我发现, 偶尔台式机会被其他情况唤醒, 这时候我并不知道, 结果白白运行了好几天, 浪费了很多电. 所以我的需求是这样的: &#x1f914; 电脑唤醒后(可能是开机, 有可能是…

3款电脑必装软件,功能强大且免费,打死也舍不得卸载

闲话不多说&#xff0c;直接上狠货。 1、FlowUs息流 FlowUs息流是一款知识管理与协作平台&#xff0c;以云端笔记为载体&#xff0c;配合在线文档、知识库、文件夹等多形态功能&#xff0c;支持免费使用&#xff0c;极大提高个人与团队工作效率。支持多端同步使用&#xff0c;无…

STL空间配置器框架分析

目录 一、空间配置器概念 二、空间配置器的作用 三、内存池技术 四、空间配置器的实现原理 3.1 流程概述 3.2 一级空间配置器 3.3 二级空间配置器 3.3.1 二级空间配置器设计 3.3.2 内存碎片问题 一、空间配置器概念 即为各个容器高效的管理空间(空间的申请与回收)的。…

聊一聊双亲委派模式

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 说起双亲委派模型&#xff0c;不得不说一下类加载器。 类加载器是什么&#xff1f; 当我们编译Java类时&#xff0c;JVM会创建与平台和…

Allegro174版本新功能介绍之移动画布不闪屏设置

Allegro174版本新功能介绍之移动画布不闪屏设置 Allegro在升级到174版本后,在移动画布的时候,视图数据量比较大的情况,会出现闪屏现象 Allegro在切换到Open GL模式下,这个现象会有所缓解,具体操作如下 选择Setup选择User-preferences

【Ansible】ansible 基础知识

ansible 文章目录ansible一、ansible Ad-Hoc 命令1.命令格式2.模块类型3.联机帮助4.常用模块4.1 command & shell 模块4.2 script 模块4.3 copy 模块4.4 yum_repository4.5 yum 模块4.6 systemd 模块4.7 group 模块4.8 user 模块4.9 file 模块4.10 cron 模块4.11 template …

SIE高级副总裁:关于PS VR2定价、设计、内容的思考

2023年2月22日&#xff0c;索尼将正式推出次世代头显PS VR2&#xff0c;首发VR游戏将超过30款&#xff0c;其中包括热门游戏《GT赛车7 VR》。此外&#xff0c;PS5全球销量也已突破3000万。实际上距离索尼推出上一代PS VR&#xff0c;已经过去了6年时间&#xff0c;相比于Quest等…

M12269 支持PD3.1等快充协议、140W升降压3-8节多串锂电充放电移动电源管理IC

引言 在快充技术持续迭代升级的过程中&#xff0c;充电从小功率向中大功率的转变是最为明显的。支持的快充功率从最初的7.5W&#xff0c;已经向最高240W迈进。PD3.1协议的推出&#xff0c;进一步助力快充加速走向中大功率。新增三种固定电压档&#xff1a;28V&#xff08;100-1…

VS1053 MP3模块介绍

VS1053MP3模块简介ATK-VS1053 MP3 MODULE是ALIENTEK推出的一款高性能音频编解码模块&#xff0c;该模块采用VS1053B作为主芯片&#xff0c;支持&#xff1a;MP3/WMA/OGG/WAV/FLAC/MIDI/AAC等音频格式的解码&#xff0c;并支持&#xff1a;OGG/WAV音频格式的录音&#xff0c;支持…

Mask RCNN网络源码解读(Ⅱ) --- ResNet、ResNeXt网络结构、BN及迁移学习

目录 1.ResNet简介 2.residual结构和ResNet-34详解 2.1 residual结构 2.2 Batch Normalization 3.迁移学习 4.ResNeXt网络结构 1.ResNet简介 ResNet在2015年由微软实验室提出&#xff0c;斩获当年lmageNet竞赛中分类任务第一名&#xff0c;目标检测第一名。获得coco数据…

信道模型:Rayleigh、Rician、卫星→地面

这里写目录标题比较C. Loo模型&#xff1a;直射阴影&#xff0c;多径不阴影Corazza模型&#xff1a;直射和多径都阴影Lutz模型&#xff1a;好坏2个状态Rayleigh and Rician 信道生成Shadowed-Rician 直射径 散射径[Secure Transmission in Cognitive Satellite Terrestrial Net…

Redis的String类型,原来这么占内存

Redis的String类型&#xff0c;原来这么占内存 存一个 Long 类型这么占内存&#xff0c;Redis 的内存开销都花在哪儿了&#xff1f; 1、场景介绍 假设现在我们要开发一个图片存储系统&#xff0c;要求这个系统能够根据图片 ID 快速查找到图片存储对象 ID。图片 ID 和图片存储对…

【Flink基础】-- 源码中的注解

1.Flink自定义注解级别在升级 Flink版本至 1.15.3时&#xff0c;偶然遇到了一个异常&#xff0c;然后就准备详细了解下源码中的注解。设计注解的初衷&#xff1a;为了更好地进行代码和版本管理&#xff0c;Flink使用了Java的注解特性自定义了注解&#xff0c;对代码进行增强说明…