.mp4 文件转化成 .bag 文件并在 rviz 中显示

news2024/11/18 19:28:44

文章目录

      • 一、Python实现.mp4和.bag相互转化
        • 1、.mp4转.bag
        • 验证是否转换成功:使用 rosplay
        • 2、.bag转.mp4
      • 二、rviz 读取 *.bag 数据包并显示
        • 1、查看bag数据包的基本信息
        • 2、rviz 显示信息

一、Python实现.mp4和.bag相互转化

1、.mp4转.bag

# -*- coding: utf-8 -*-
##import logging
##logging.basicConfig()
import time ,sys ,os
import rosbag
import roslib,rospy
from cv_bridge import CvBridge
import cv2
from sensor_msgs.msg import Image
 
TOPIC = 'camera/image_raw'
 
def my_resize(my_img,x,y):
    resized = cv2.resize(my_img,(  int(my_img.shape[1]*x),int(my_img.shape[0]*y) ))
    return resized
 
def CreateVideoBag(videopath, bagname):
    '''Creates a bag file with a video file'''
    print(videopath)
    print(bagname)
    bag = rosbag.Bag(bagname, 'w')
    cap = cv2.VideoCapture(videopath)
    cb = CvBridge()
    # prop_fps = cap.get(cv2.cv.CV_CAP_PROP_FPS)  # 源代码是这个,不能正常运行
    prop_fps = cap.get(cv2.CAP_PROP_FPS)  # 帧速率
    if prop_fps != prop_fps or prop_fps <= 1e-2:
        print ("Warning: can't get FPS. Assuming 24.")
        prop_fps = 24
 
    print(prop_fps)
    ret = True
    frame_id = 0
        
    while(ret):
        ret, frame = cap.read()
        if not ret:
            break
        frame = cv2.resize(frame,(  960,540 ))
        stamp = rospy.rostime.Time.from_sec(float(frame_id) / prop_fps)
        frame_id += 1
        image = cb.cv2_to_imgmsg(frame, encoding='bgr8')
        image.header.stamp = stamp
        image.header.frame_id = "camera"
        bag.write(TOPIC, image, stamp)
    cap.release()
    bag.close()
 
 
if __name__ == "__main__":
    CreateVideoBag('./123.mp4','./123.bag')
 
 
    
##if __name__ == "__main__":
##    if len( sys.argv ) == 3:
##        CreateVideoBag(*sys.argv[1:])
##    else:
##        print( "Usage: video2bag videofilename bagfilename")
 

运行方式: 修改话题名TOPIC、videopath、bagname后直接F5运行代码

或者

参考链接:https://stackoverflow.com/questions/31432870/how-do-i-convert-a-video-or-a-sequence-of-images-to-a-bag-file

import time, sys, os
from ros import rosbag
import roslib, rospy
roslib.load_manifest('sensor_msgs')
from sensor_msgs.msg import Image

from cv_bridge import CvBridge
import cv2

TOPIC = 'camera/image_raw'

def CreateVideoBag(videopath, bagname):
    '''Creates a bag file with a video file'''
    print videopath
    print bagname
    bag = rosbag.Bag(bagname, 'w')
    cap = cv2.VideoCapture(videopath)
    cb = CvBridge()
    # prop_fps = cap.get(cv2.cv.CV_CAP_PROP_FPS)  # 源代码是这个,不能正常运行
    prop_fps = cap.get(cv2.CAP_PROP_FPS)  # 我该成了这个
    if prop_fps != prop_fps or prop_fps <= 1e-2:
        print "Warning: can't get FPS. Assuming 24."
        prop_fps = 24
    prop_fps = 24 # 我手机拍摄的是29.78,我还是转成24的。
    print prop_fps
    ret = True
    frame_id = 0
    while(ret):
        ret, frame = cap.read()
        if not ret:
            break
        stamp = rospy.rostime.Time.from_sec(float(frame_id) / prop_fps)
        frame_id += 1
        image = cb.cv2_to_imgmsg(frame, encoding='bgr8')
        image.header.stamp = stamp
        image.header.frame_id = "camera"
        bag.write(TOPIC, image, stamp)
    cap.release()
    bag.close()

if __name__ == "__main__":
    if len( sys.argv ) == 3:
        CreateVideoBag(*sys.argv[1:])
    else:
        print( "Usage: video2bag videofilename bagfilename")

运行方式: python Video2ROSbag.py TLout.mp4 TLout.bag

验证是否转换成功:使用 rosplay

rosbag info TLout.bag  # 查看 bag 包信息
rosbag play -l TLout.bag camera/image_raw:=image_raw0   # 循环播放图片,并重命名成自己需要的话题名
rqt_image_view  # 显示播放的图片,能正常显示说明ros包制作成功。

2、.bag转.mp4

# -*- coding: utf-8 -*-
 
#!/usr/bin/env python2
 
import roslib
#roslib.load_manifest('rosbag')
import rospy
import rosbag
import sys, getopt
import os
from sensor_msgs.msg import CompressedImage  #压缩图片
from sensor_msgs.msg import Image
import cv2
 
import numpy as np
 
import shlex, subprocess  #读取命令行参数
#subprocess 是一个 python 标准类库,用于创建进程运行系统命令,并且可以连接进程的输入输出和
#错误管道,获取它们的返回,使用起来要优于 os.system,在这里我们使用这个库运行 hive 语句并获取返回结果。
 
#shlex 是一个 python 标准类库,使用这个类我们可以轻松的做出对 linux shell 的词法分析,在
#这里我们将格式化好的 hive 连接语句用 shlex 切分,配合 subprocess.run 使用。
MJPEG_VIDEO = 1
RAWIMAGE_VIDEO = 2
VIDEO_CONVERTER_TO_USE = "ffmpeg" # or you may want to use "avconv" #视频转换器
 
def print_help():
    print('rosbag2video.py [--fps 25] [--rate 1] [-o outputfile] [-v] [-s] [-t topic] bagfile1 [bagfile2] ...')
    print()
    print('Converts image sequence(s) in ros bag file(s) to video file(s) with fixed frame rate using',VIDEO_CONVERTER_TO_USE)
    print(VIDEO_CONVERTER_TO_USE,'needs to be installed!')
    print()
    print('--fps   Sets FPS value that is passed to',VIDEO_CONVERTER_TO_USE)
    print('        Default is 25.')
    print('-h      Displays this help.')
    print('--ofile (-o) sets output file name.')
    print('        If no output file name (-o) is given the filename \'<prefix><topic>.mp4\' is used and default output codec is h264.')
    print('        Multiple image topics are supported only when -o option is _not_ used.')
    print('        ',VIDEO_CONVERTER_TO_USE,' will guess the format according to given extension.')
    print('        Compressed and raw image messages are supported with mono8 and bgr8/rgb8/bggr8/rggb8 formats.')
    print('--rate  (-r) You may slow down or speed up the video.')
    print('        Default is 1.0, that keeps the original speed.')
    print('-s      Shows each and every image extracted from the rosbag file (cv_bride is needed).')
    print('--topic (-t) Only the images from topic "topic" are used for the video output.')
    print('-v      Verbose messages are displayed.')
    print('--prefix (-p) set a output file name prefix othervise \'bagfile1\' is used (if -o is not set).')
    print('--start Optional start time in seconds.')
    print('--end   Optional end time in seconds.')
 
 
 
class RosVideoWriter():
    def __init__(self, fps=25.0, rate=1.0, topic="", output_filename ="", display= False, verbose = False, start = rospy.Time(0), end = rospy.Time(sys.maxsize)):
        self.opt_topic = topic
        self.opt_out_file = output_filename
        self.opt_verbose = verbose
        self.opt_display_images = display
        self.opt_start = start
        self.opt_end = end
        self.rate = rate
        self.fps = fps
        self.opt_prefix= None
        self.t_first={}
        self.t_file={}
        self.t_video={}
        self.p_avconv = {}
        
    #语法分析Args
    def parseArgs(self, args):
        opts, opt_files = getopt.getopt(args,"hsvr:o:t:p:",["fps=","rate=","ofile=","topic=","start=","end=","prefix="])
        #getopt()
        for opt, arg in opts:
            if opt == '-h':
                print_help()
                sys.exit(0)
            elif opt == '-s':
                self.opt_display_images = True
            elif opt == '-v':
                self.opt_verbose = True
            elif opt in ("--fps"):
                self.fps = float(arg)
            elif opt in ("-r", "--rate"):
                self.rate = float(arg)
            elif opt in ("-o", "--ofile"):
                self.opt_out_file = arg
            elif opt in ("-t", "--topic"):
                self.opt_topic = arg
            elif opt in ("-p", "--prefix"):
                self.opt_prefix = arg
            elif opt in ("--start"):
                self.opt_start = rospy.Time(int(arg))
                if(self.opt_verbose):
                    print("starting at",self.opt_start.to_sec())
            elif opt in ("--end"):
                self.opt_end = rospy.Time(int(arg))
                if(self.opt_verbose):
                    print("ending at",self.opt_end.to_sec())
            else:
                print("opt:", opt,'arg:', arg)
 
        if (self.fps<=0):
            print("invalid fps", self.fps)
            self.fps = 1
 
        if (self.rate<=0):
            print("invalid rate", self.rate)
            self.rate = 1
 
        if(self.opt_verbose):
            print("using ",self.fps," FPS")
        return opt_files
 
 
    # filter messages using type or only the opic we whant from the 'topic' argument
    def filter_image_msgs(self, topic, datatype, md5sum, msg_def, header):
        if(datatype=="sensor_msgs/CompressedImage"):
            if (self.opt_topic != "" and self.opt_topic == topic) or self.opt_topic == "":
                print("############# COMPRESSED IMAGE  ######################")
                print(topic,' with datatype:', str(datatype))
                print()
                return True;
 
        if(datatype=="theora_image_transport/Packet"):
            if (self.opt_topic != "" and self.opt_topic == topic) or self.opt_topic == "":
                print(topic,' with datatype:', str(datatype))
                print('!!! theora is not supported, sorry !!!')
                return False;
 
        if(datatype=="sensor_msgs/Image"):
            if (self.opt_topic != "" and self.opt_topic == topic) or self.opt_topic == "":
                print("############# UNCOMPRESSED IMAGE ######################")
                print(topic,' with datatype:', str(datatype))
                print()
                return True;
 
        return False;
 
 
    def write_output_video(self, msg, topic, t, video_fmt, pix_fmt = ""):
        # no data in this topic
        if len(msg.data) == 0 :
            return
        # initiate data for this topic
        if not topic in self.t_first :
            self.t_first[topic] = t # timestamp of first image for this topic
            self.t_video[topic] = 0
            self.t_file[topic] = 0
        # if multiple streams of images will start at different times the resulting video files will not be in sync
        # current offset time we are in the bag file
        self.t_file[topic] = (t-self.t_first[topic]).to_sec()
        # fill video file up with images until we reache the current offset from the beginning of the bag file
        while self.t_video[topic] < self.t_file[topic]/self.rate :
            if not topic in self.p_avconv:
                # we have to start a new process for this topic
                if self.opt_verbose :
                    print("Initializing pipe for topic", topic, "at time", t.to_sec())
                if self.opt_out_file=="":
                    out_file = self.opt_prefix + str(topic).replace("/", "_")+".mp4"
                else:
                    out_file = self.opt_out_file
 
                if self.opt_verbose :
                    print("Using output file ", out_file, " for topic ", topic, ".")
 
                if video_fmt == MJPEG_VIDEO :
                    cmd = [VIDEO_CONVERTER_TO_USE, '-v', '1', '-stats', '-r',str(self.fps),'-c','mjpeg','-f','mjpeg','-i','-','-an',out_file]
                    self.p_avconv[topic] = subprocess.Popen(cmd, stdin=subprocess.PIPE)
                    if self.opt_verbose :
                        print("Using command line:")
                        print(cmd)
                elif video_fmt == RAWIMAGE_VIDEO :
                    size = str(msg.width)+"x"+str(msg.height)
                    cmd = [VIDEO_CONVERTER_TO_USE, '-v', '1', '-stats','-r',str(self.fps),'-f','rawvideo','-s',size,'-pix_fmt', pix_fmt,'-i','-','-an',out_file]
                    self.p_avconv[topic] = subprocess.Popen(cmd, stdin=subprocess.PIPE)
                    if self.opt_verbose :
                        print("Using command line:")
                        print(cmd)
 
                else :
                    print("Script error, unknown value for argument video_fmt in function write_output_video.")
                    exit(1)
            # send data to ffmpeg process pipe
            self.p_avconv[topic].stdin.write(msg.data)
            # next frame time
            self.t_video[topic] += 1.0/self.fps
 
    def addBag(self, filename):
        if self.opt_display_images:
            from cv_bridge import CvBridge, CvBridgeError
            bridge = CvBridge()
            cv_image = []
 
        if self.opt_verbose :
            print("Bagfile: {}".format(filename))
 
        if not self.opt_prefix:
            # create the output in the same folder and name as the bag file minu '.bag'
            self.opt_prefix = bagfile[:-4]
 
        #Go through the bag file
        bag = rosbag.Bag(filename)
        if self.opt_verbose :
            print("Bag opened.")
        # loop over all topics
        for topic, msg, t in bag.read_messages(connection_filter=self.filter_image_msgs, start_time=self.opt_start, end_time=self.opt_end):
            try:
                if msg.format.find("jpeg")!=-1 :
                    if msg.format.find("8")!=-1 and (msg.format.find("rgb")!=-1 or msg.format.find("bgr")!=-1 or msg.format.find("bgra")!=-1 ):
                        if self.opt_display_images:
                            np_arr = np.fromstring(msg.data, np.uint8)
                            cv_image = cv2.imdecode(np_arr, cv2.CV_LOAD_IMAGE_COLOR)
                        self.write_output_video( msg, topic, t, MJPEG_VIDEO )
                    elif msg.format.find("mono8")!=-1 :
                        if self.opt_display_images:
                            np_arr = np.fromstring(msg.data, np.uint8)
                            cv_image = cv2.imdecode(np_arr, cv2.CV_LOAD_IMAGE_COLOR)
                        self.write_output_video( msg, topic, t, MJPEG_VIDEO )
                    elif msg.format.find("16UC1")!=-1 :
                        if self.opt_display_images:
                            np_arr = np.fromstring(msg.data, np.uint16)
                            cv_image = cv2.imdecode(np_arr, cv2.CV_LOAD_IMAGE_COLOR)
                        self.write_output_video( msg, topic, t, MJPEG_VIDEO )
                    else:
                        print('unsupported jpeg format:', msg.format, '.', topic)
 
            # has no attribute 'format'
            except AttributeError:
                try:
                        pix_fmt=None
                        if msg.encoding.find("mono8")!=-1 or msg.encoding.find("8UC1")!=-1:
                            pix_fmt = "gray"
                            if self.opt_display_images:
                                cv_image = bridge.imgmsg_to_cv2(msg, "bgr8")
 
                        elif msg.encoding.find("bgra")!=-1 :
                            pix_fmt = "bgra"
                            if self.opt_display_images:
                                cv_image = bridge.imgmsg_to_cv2(msg, "bgr8")
 
                        elif msg.encoding.find("bgr8")!=-1 :
                            pix_fmt = "bgr24"
                            if self.opt_display_images:
                                cv_image = bridge.imgmsg_to_cv2(msg, "bgr8")
                        elif msg.encoding.find("bggr8")!=-1 :
                            pix_fmt = "bayer_bggr8"
                            if self.opt_display_images:
                                cv_image = bridge.imgmsg_to_cv2(msg, "bayer_bggr8")
                        elif msg.encoding.find("rggb8")!=-1 :
                            pix_fmt = "bayer_rggb8"
                            if self.opt_display_images:
                                cv_image = bridge.imgmsg_to_cv2(msg, "bayer_rggb8")
                        elif msg.encoding.find("rgb8")!=-1 :
                            pix_fmt = "rgb24"
                            if self.opt_display_images:
                                cv_image = bridge.imgmsg_to_cv2(msg, "bgr8")
                        elif msg.encoding.find("16UC1")!=-1 :
                            pix_fmt = "gray16le"
                        else:
                            print('unsupported encoding:', msg.encoding, topic)
                            #exit(1)
                        if pix_fmt:
                            self.write_output_video( msg, topic, t, RAWIMAGE_VIDEO, pix_fmt )
 
                except AttributeError:
                    # maybe theora packet
                    # theora not supported
                    if self.opt_verbose :
                        print("Could not handle this format. Maybe thoera packet? theora is not supported.")
                    pass
            if self.opt_display_images:
                cv2.imshow(topic, cv_image)
                key=cv2.waitKey(1)
                if key==1048603:
                    exit(1)
        if self.p_avconv == {}:
            print("No image topics found in bag:", filename)
        bag.close()
 
 
 
if __name__ == '__main__':
    #print()
    #print('rosbag2video, by Maximilian Laiacker 2020 and Abel Gabor 2019')
    #print()
 
    if len(sys.argv) < 2:
        print('Please specify ros bag file(s)!')
        print_help()
        sys.exit(1)
    else :
        videowriter = RosVideoWriter()
        try:
            opt_files = videowriter.parseArgs(sys.argv[1:])
        except getopt.GetoptError:
            print_help()
            sys.exit(2)
 
 
    # loop over all files
    for files in range(0,len(opt_files)):
        #First arg is the bag to look at
        bagfile = opt_files[files]
        videowriter.addBag(bagfile)
    print("finished")

使用方法:

$ python rosbag2video.py [-h] [-s] [-v] [-r] [-o outputfile] [-t topic] [-p prefix_name] [--fps 25] [--rate 1.0] [--ofile output_file_name] [--start start_time] [--end end_time] bagfile1 [bagfile2] ...

二、rviz 读取 *.bag 数据包并显示

1、查看bag数据包的基本信息

已有数据:test_room1.bag

查看.bag信息:rosbag info test_room1.bag

在这里插入图片描述可以看出 topic:/mynteye/image_color
查看frame_id

//打开终端
roscore
//打开新终端 播放数据
rosbag play test_room1.bag
// 打开新终端 查看/velodyne_points的frame_id
rostopic echo /mynteye/image_color | grep frame_id

查看结果如下:frame_id=camera
在这里插入图片描述

若想更改frame_id,可以参考:改变ros bag 中消息的frame_id 和话题名

2、rviz 显示信息

执行以下命令:

roscore
//打开新终端
rosrun rviz rviz
//  打开rviz

rviz 设置:add->image
image 设置:Image Topic 设置为 /mynteye/image_color(上面info显示的topic)

在这里插入图片描述

播放bag包:rosbag play nsh_indoor_outdoor.bag

显示结果:

在这里插入图片描述

若需要显示的是点云,则需要设置pointcloud2

设置rviz:add->PointCloud2
设置:
fix-frame=camera
topic:/mynteye/image_color

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

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

相关文章

Webpack 的 Chunk,想怎么分就怎么分

想必大家都用过 webpack&#xff0c;也或多或少了解它的原理&#xff0c;但是不知道大家有没有写过 Webpack 的插件呢&#xff1f; 今天我们就一起来写一个划分 Chunk 的 webpack 插件吧&#xff0c;写完后你会发现想怎么分 Chunk 都可以&#xff01; 首先我们简单了解下 web…

图像配准:基于 OpenCV 的高效实现

在这篇文章中&#xff0c;我将对图像配准进行一个简单概述&#xff0c;展示一个最小的 OpenCV 实现&#xff0c;并展示一个可以使配准过程更加高效的简单技巧。什么是图像配准图像配准被定义为将不同成像设备或传感器在不同时间和角度拍摄的两幅或多幅图像&#xff0c;或来自同…

什么牌子的护眼灯最好推荐?盘点口碑好的护眼灯品牌

护眼灯是目前大部分家庭都在使用的灯具之一&#xff0c;利用光源起到保护视力的效果&#xff0c;预防近视&#xff0c;可谓是现代生活中伟大的发明&#xff0c;今天由小编来列出优秀的护眼灯品牌&#xff0c;并详细的介绍&#xff0c;告诉大家哪个护眼灯品牌好。① 南卡护眼台…

【微信小程序-原生开发】实用教程07 - Grid 宫格导航,详情页,侧边导航(含自定义页面顶部导航文字)

开始前&#xff0c;请先完成成员页的开发&#xff0c;详见 【微信小程序-原生开发】实用教程 06-轮播图、分类页签 tab 、成员列表&#xff08;含Tdesign升级&#xff0c;切换调试基础库&#xff0c;设置全局样式&#xff0c;配置组件按需注入&#xff0c;添加图片素材&#x…

Canal快速入门

Canal 一、Canal 入门 1.1、什么是 Canal ​ 阿里巴巴 B2B 公司&#xff0c;因为业务的特性&#xff0c;卖家主要集中在国内&#xff0c;买家主要集中在国外&#xff0c;所以衍生出了同步杭州和美国异地机房的需求&#xff0c;从 2010 年开始&#xff0c;阿里系公司开始逐步…

PaddleSeg图像分割预测pyinstaller打包报错:No module named ‘framework_pb2‘,问题解决

报错 在使用PaddlePaddle的FastDeploy部署图像分割时&#xff0c;需要验证目标电脑环境&#xff0c;所以先将预测代码predict.py用pyinstaller打包来试试&#xff0c;指令&#xff1a; pyinstaller -D predict.py 打包完成&#xff0c;成功生成exe 运行时报错如下&#xff1a;…

项目五linux 内网完整渗透测试实例笔记

1.DDD4 靶场介绍本靶场存在三个 flag 把下载到的虚拟机环境导入到虚拟机&#xff0c;本靶场需要把网络环境配置好。1.1.网络示意图2. 信息收集2.1.主机发现sudo netdiscover -i eth0 -r 192.168.1.0/242.2.nmap 主机发现nmap -sn 192.168.1.0/242.3.masscan 端口探测sudo massc…

Python批量改文件名

对以下路径中的文件名批量修改。 一、读取指定路径中的文件名 #导入标准库 import os#读取文件名 filesDir "路径……" fileNameList os.listdir(filesDir)#输出路径中的所有文件 for filename in fileNameList:print(filename)二、正则表达式提取需要保留的部分 …

[Vulnhub] DC-6

下载链接&#xff1a;https://download.vulnhub.com/dc/DC-6.zip 知识点&#xff1a; wordpress-getshellnc反弹shell横向越权nmap提权 目录 <1> 信息搜集 <2> wordpress_Activity monitor插件rce漏洞getshell <3> Privilege Escalation&#xff08;nm…

windows上安装hadoop

下载与安装 hadoop下载官网 清华大学镜像下载 进入官网点击Binary download是运行在windows上的。在Apache里面下东西经常会有binary和source的版本&#xff0c;binary是编译好的可以直接使用&#xff0c;source是还没编译过的源代码&#xff0c;需要自行编译。 镜像下载 选…

OSERDESE3与ODELAYE3原语

SelectIO 接口 UltraScale 架构的器件 包括三种I/O&#xff1a;高性能(HP), 高密度 (HD),和高量程(HR) I/O banks 。 HP I/O banks满足高速存储和片到片接口性能要求&#xff0c;电压最高1.8V。HR I/O banks支持更大范围电压&#xff0c;电压最高3.3V。HD I/O banks支持低速接…

Day872.事务间是否需要隔离 -MySQL实战

事务间是否需要隔离 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于事务间是否需要隔离的内容。 创建的视图是静态视图&#xff0c;当前视图对应的数据由字段的当前值加上回滚段计算得到。 事务隔离级别 的时候提到过&#xff0c;如果是可重复读隔离级别&#xff…

1457. 二叉树中的伪回文路径

1457. 二叉树中的伪回文路径题目算法设计&#xff1a;深度优先搜索题目 传送门&#xff1a;https://leetcode.cn/problems/pseudo-palindromic-paths-in-a-binary-tree/ 算法设计&#xff1a;深度优先搜索 如何判断一组数字是否存在一个回文串组合&#xff1f; 如 [1, 2, 1]…

css元素显示模式(行内、块级、行内块)

1.块级元素 显示特点&#xff1a; 1、独占一行&#xff08;一行只能显示一个&#xff09; 2、宽度默认是父元素的宽度&#xff0c;高度默认由内容撑开 3、可以设置宽高 代表标签&#xff1a; div、p、h系列、ul、li、dl、dt、dd、form、header、anv、footer <style>div…

电脑数据怎么迁移?6种旧电脑数据传输到新电脑方法分享

如今&#xff0c;我们拥有如此多的设备&#xff0c;从一个设备跳到另一个设备似乎是一项艰巨的任务。平均而言&#xff0c;一个人可能拥有一台电脑、一部智能手机和一台平板电脑。但是&#xff0c;如果您有多台计算机或要换一台新计算机怎么办&#xff1f;您可能在互联网上问过…

电脑录像软件推荐?分享3款,简单好用且方便

​在日常生活中&#xff0c;我们经常会遇到临时有事情需要外出处理的时候&#xff0c;但在如果正好在上网课或者开会议、听讲座的时候&#xff0c;这时候外出很容易会错过一些重要的内容。这个时候&#xff0c;就需要借助电脑录像软件了。电脑录像软件推荐什么&#xff1f;今天…

Docker consul

目录 一、Docker consul简介 二、Consul优势 三、Consul中的概念 四、部署 1、consul服务器配置 2、查看集群信息 3、在浏览器上进到consul的界面进行管理 4、容器服务自动注册到consul集群 5、consul节点配置nginx 6、配置模板信息 7、配置并启动consul-template …

Java创建pdf的代码

一、概述 以下代码可以在指定文件夹内创建一个简历pdf。 以下代码生成pdf&#xff0c;主要是设置cell所占的行、列、内容。 二、代码 1.需要的jar包 itext-asian-5.2.0.jar itextpdf-5.5.5.jar2.个人信息类MsgUtil.java 这个类里面放了个人信息&#xff1b;也可以放多个人…

Python量化投资——股票择时到底能否赚钱?TA-Lib中33种技术指标有效性回测研究

TA-Lib中33种技术指标回测研究Python量化投资——TA-Lib中33种股票择时技术指标的有效性研究为什么要做这个评测技术指标清单评测方法评测工具期待你的意见Python量化投资——TA-Lib中33种股票择时技术指标的有效性研究 为什么要做这个评测 技术指标是股票交易中最常用的技术…

CSS 常见布局

文章目录CSS 常见布局单列布局单列布局&#xff08;不通栏&#xff09;单列布局&#xff08;通栏&#xff09;双列布局floatoverflow:hiddenflexgridCSS 常见布局 单列布局 单列布局&#xff08;不通栏&#xff09; <!DOCTYPE html> <html><head><meta …