事件相机(Event-based camera)模拟器ESIM配置及使用指南

事件相机的原理和特性在此处不解释,本文只讲解如何配置和使用事件相机模拟器。模拟器是用线性插值和高斯噪声扰动的方式,模拟出事件流来。因此需要帧率尽可能的高一些。亲自测了以后,和DAVIS事件相机实际对着电脑屏幕拍摄的已经记录的视频没什么差别。

模拟器在github网址为:点击这里

目录

一、模拟器的配置

可能出错以及解决方案: 

继续配置: 

二、模拟器的使用

(一)跑通demo:

(二)用自己的视频模拟事件流

(三)从bag中解析数据至txt文件中


一、模拟器的配置

首先,安装事件相机模拟器,最基本的要求有两点:

1.(必要)必须安装ROS (这个教程网上已经足够多,本文不再介绍)

2.(可能必要,看情况)挂代理 


刚开始的步骤,和github安装上的步骤一样,而且一般不会出问题:

mkdir -p ~/sim_ws/src && cd ~/sim_ws
catkin init
catkin config --extend /opt/ros/kinetic --cmake-args -DCMAKE_BUILD_TYPE=Release

之后安装vcstools:

sudo apt-get install python-vcstool

之后的三步:

cd src/
git clone git@github.com:uzh-rpg/rpg_esim.git
vcs-import < rpg_esim/dependencies.yaml

其中,第二步可能会报错:Permission denied (publickey). fatal: Could not read from remote repository.

解决方法为:git push(clone)失败报错:Permission denied (publickey). fatal: Could not read from remote repository.

在解决这个问题之后,安装pcl-ros:

sudo apt-get install ros-kinetic-pcl-ros

安装glfw:

sudo apt-get install libglfw3 libglfw3-dev

安装glm:

sudo apt-get install libglm-dev

继续安装:

sudo apt-get install ros-kinetic-hector-trajectory-server

执行以下操作:

cd ze_oss
touch imp_3rdparty_cuda_toolkit/CATKIN_IGNORE \
      imp_app_pangolin_example/CATKIN_IGNORE \
      imp_benchmark_aligned_allocator/CATKIN_IGNORE \
      imp_bridge_pangolin/CATKIN_IGNORE \
      imp_cu_core/CATKIN_IGNORE \
      imp_cu_correspondence/CATKIN_IGNORE \
      imp_cu_imgproc/CATKIN_IGNORE \
      imp_ros_rof_denoising/CATKIN_IGNORE \
      imp_tools_cmd/CATKIN_IGNORE \
      ze_data_provider/CATKIN_IGNORE \
      ze_geometry/CATKIN_IGNORE \
      ze_imu/CATKIN_IGNORE \
      ze_trajectory_analysis/CATKIN_IGNORE

之后,执行关键的一步:

catkin build esim_ros

这一步非常重要。最后一定要提示所有的都安装了,0个跳过,0个failed,0个abandon。否则使用功能的时候会出错。

如果直接就成功了,那么恭喜,跳过我下面这部分的分割线继续看。


可能出错以及解决方案: 

如果有类似如下错误:

[ 16%] Performing download step (download, verify and extract) for 'luacov'
-- downloading...
 src='https://github.com/keplerproject/luacov/archive/v0.7.tar.gz'
 dst='/home/build/my_build/external_projects/downloads/v0.7.tar.gz'
 timeout='none'
CMake Error at /home/build/my_build/luacov-prefix/src/luacov-stamp/download-luacov.cmake:21 (message):
 error: downloading
'https://github.com/keplerproject/luacov/archive/v0.7.tar.gz' failed

status_code: 1
status_string: "Unsupported protocol"
log: Protocol "https" not supported or disabled in libcurl

Closing connection -1

make[3]: *** [luacov-prefix/src/luacov-stamp/luacov-download] Error 1
make[2]: *** [CMakeFiles/luacov.dir/all] Error 2
make[1]: *** [CMakeFiles/luacov.dir/rule] Error 2
make: *** [luacov] Error 2

那么可以进行如下操作:先进入cmake的目录下,

然后:

./bootstrap --system-curl
make
sudo make install

注意boostrap这个文件夹是在cmake目录下。

(实验室有朋友表示,找不到这个cmake的目录。如果你遇到这种情况,你应该去回忆一下,你到底有没有到官网用源码装过Cmake。因为ROS也自带一个Cmake,如果把ROS卸载掉,就不能使用cmake了,那说明你没有装过。应该去官网安装一个Cmake。我随便找个教程:Ubuntu 下cmake的安装(以ubuntu16.04,cmake-3.14.0为例,其他版本也可进行参考)

执行完上面的操作后,在刚刚的sim_ws文件夹下重新:

catkin build esim_ros

检查是否是否所有的都被安装了。如果仍然有错误(一般就是那个assimp有问题),那么参见:

ubuntu下配置ss教程

要按我教程中的去做。(这个链接已经打不开了,相关内容不让发,总之是想挂上out网,所以各位自己想办法吧,国内的网配这个可能有点问题)

做完以后,之后重新执行该指令:(proxychains是一个指令,在终端里访问那什么的。把网的事情搞定了,这个指令不用也行,直接catkin build esim_ros即可)

proxychains catkin build esim_ros

可以看到所有的都被安装了,0个fail,0个abondan。


继续配置: 

在执行完catkin build指令后,

echo "source ~/sim_ws/devel/setup.bash" >> ~/setupeventsim.sh
chmod +x ~/setupeventsim.sh

然后打开bashrc文件:

sudo gedit ~/.bashrc

在bashrc文件最末尾,加上这句话:

alias ssim='source ~/setupeventsim.sh'


二、模拟器的使用

这里只讲解,如何根据video,模拟生成对应的模拟事件流rosbag。(即:Simulating events from a video)

模拟器其余功能的介绍见 事件相机(Event-based camera)模拟器功能介绍

(一)跑通demo:

mkdir -p /tmp/cheetah_example
cd /tmp/cheetah_example

这里保存在根目录的tmp文件下,重启后会自动删除。之所以样例中会这样,可能是因为这样路径长度比较短。

然后,下载安装这个:

pip install youtube-dl

这个不挂代理也能成功的装上。

youtube-dl https://youtu.be/THA_5cqAfCQ -o cheetah

上面这步相当于是下载视频,然后保存名字为cheeetah。要想这步执行成功,必须按照上面配置的ss方法中,把终端也挂上代理。实测发现proxychains这个指令在这不顶用了,还是应该开启代理,然后在当前终端里输入

export http_proxy=socks5://127.0.0.1:1080

(这个是按照你自己的代理设置配的)

然后重新执行上面的下载视频指令。

切割视频:

ffmpeg -i cheetah.mkv -ss 00:02:07 -t 00:00:40 -async 1 -strict -2 cheetah_cut.mkv

resize视频:

ffmpeg -i cheetah_cut.mkv -vf scale=640:-1 -crf 0 cheetah_sd.mkv

然后预处理:

mkdir frames
ffmpeg -i cheetah_sd.mkv frames/frames_%010d.png

之后决定启动模拟器(一定要打开,在当前终端有效,否则之后会报错):

ssim

重新开启一个终端,把roscore也打开:

roscore

然后回到之前的终端,执行:

roscd esim_ros
python scripts/generate_stamps_file.py -i /tmp/cheetah_example/frames -r 1200.0

然后执行:

rosrun esim_ros esim_node \
 --data_source=2 \
 --path_to_output_bag=/tmp/out.bag \
 --path_to_data_folder=/tmp/cheetah_example/frames \
 --ros_publisher_frame_rate=60 \
 --exposure_time_ms=10.0 \
 --use_log_image=1 \
 --log_eps=0.1 \
 --contrast_threshold_pos=0.15 \
 --contrast_threshold_neg=0.15

(如果这一步提示,没有找到esim_node,首先要判断,在当前终端里有没有执行ssim这个指令启动模拟器,有没有在外面打开roscore。如果还是找不到,说明最之前的catkin build就没有成功,回到上面重新弄吧!)

重新开启终端:

rosrun dvs_renderer dvs_renderer events:=/cam0/events

重新开启终端:

rosbag play /tmp/out.bag -l -r 0.1.

然后重新开启终端:

rqt_image_view /dvs_rendering

可以看到一个豹子在上面跑。这样样例的demo就跑通了。


(二)用自己的视频模拟事件流

这个如果需要切割,或者resize,就可以模仿样例中的ffmpeg使用方式来。这个不属于模拟器的范畴。

反正,首先,把你要用的视频,(未必是样例中的mkv格式,mp4什么的都可以),拷贝到home下面的文件夹下。(因为样例中的tmp文件夹重启后会清空。

例如,拷贝到/home/zhaokai/sim_ws/MOT/下:

这样sim_ws下面有一个名为MOT的文件夹,里面放着一个视频,例如:MOT16-04.mp4

然后:

cd /home/zhaokai/sim_ws/
mkdir frames
ffmpeg -i MOT16-04.mp4 frames/frames_%010d.png

然后发现ffmpeg把视频拆成了帧,放到了frames文件夹下。

ssim
roscd esim_ros
python scripts/generate_stamps_file.py -i /home/zhaokai/sim_ws/MOT/frames -r 1200.0

注意:

1.这里路径是不认“~”这种符号的。如果写成了 ~/sim_ws会报错的,要从根目录下面开始写。

2.1200表示的是输入视频的帧率。如果你不知道输入视频的帧率,那就可以打开那个视频,看看时长。然后看看frames文件夹下拆成了多少帧,二者一除就知道了。

之后,执行模拟器指令(要确保另一个终端里开着roscore)

rosrun esim_ros esim_node \
 --data_source=2 \
 --path_to_output_bag=/home/zhaokai/sim_ws/MOT/out.bag \
 --path_to_data_folder=/home/zhaokai/sim_ws/MOT/frames \
 --ros_publisher_frame_rate=60 \
 --exposure_time_ms=10.0 \
 --use_log_image=1 \
 --log_eps=0.1 \
 --contrast_threshold_pos=0.15 \
 --contrast_threshold_neg=0.15

指令的介绍见github上的解释。

这样执行完,就生成了一个out.bag文件。

然后还是和之前跑样例一样,开一个新的终端:

rosrun dvs_renderer dvs_renderer events:=/cam0/events

如果之前本身就开着,那就不用执行上面这步了。

然后回到原终端,播放bag:

rosbag play /home/zhaokai/sim_ws/MOT/out.bag -l -r 0.1

这里 -l 表示是循环播放。-r表示是慢速播放。如果你想跟原视频同步,那么把 指令中的-r 0.1给去掉。

开一个新的终端:

rqt_image_view /dvs_rendering

可以看到你的视频模拟成了事件流。

最后的输出保存在bag文件中。如果想把其中的事件,读成txt文本的形式,读出其中模拟的的x,y,p,t,需要解析bag包。


(三)从bag中解析数据至txt文件中

记录为bag后,不太熟悉ros的或者只专注于图像的同学可能对于如何把这个bag解析为txt文件有些疑惑。我刚刚接触的时候也比较疑惑,一个月前我对ros就懂一些皮毛。在这个上面走了一些弯路,特意把过程记录在这里,一个目的是能帮助到大家,第二个目的是方便我回头再看。(因为不写下来的话很快就会忘记)

先分析一下,播放这个bag文件:

ssim
rosbag play out.bag -l -r 0.1

然后再开启一个终端:

rostopic list

可以看到,输出为:

/cam0/camera_info
/cam0/events
/cam0/image_corrupted
/cam0/image_raw
/clock
/rosout
/rosout_agg

很明显,播放的话题就是这个/cam0/events

我们需要看一下这个话题的格式:

rostopic type /cam0/events

可以看到输出为:

dvs_msgs/EventArray

或者用info语句来看:

rostopic info /cam0/events

 可以看到输出为:

Type: dvs_msgs/EventArray

Publishers: 
 * /play_1579125764739259831 (http://zhaokai-System:33439/)

Subscribers: None

 这时,两种方式都显示话题/cam0/events的发布类型为:dvs_msgs/EventArray

因此,再用rosmsg查看一下这个类型的具体内容:

rosmsg show dvs_msgs/EventArray

或者也可以直接用roscd指令,到具体文件夹下拿vi指令去查看这个类型的定义:

roscd dvs_msgs
ls
cd msg
vi EventArray.msg

可以看到输出为: 

std_msgs/Header header
  uint32 seq
  time stamp
  string frame_id
uint32 height
uint32 width
dvs_msgs/Event[] events
  uint16 x
  uint16 y
  time ts
  bool polarity

 现在我们要做的就是把里面的events给保存到txt当中。

弯路:

刚开始我打算写一个监听程序,把顺便把内容给记录下来。由于CPP版本的程序还需要再编译,所以随手写了一个脚本,想在callback里面把它记录在txt当中。先随便试了一下,随便打印点什么东西:

#!/usr/bin/env python
import rospy
from std_msgs.msg import String
from dvs_msgs.msg import EventArray

EVENT=[]

def callback(data):
    #events=data.events
    #global EVENT
    #EVENT.append(events)
    global flag
    a=data.header.stamp
    if(flag):
        print("first msg")
        first=a
        flag=False
    else:
        print(a)
    

def listener():

    # In ROS, nodes are uniquely named. If two nodes with the same
    # node are launched, the previous one is kicked off. The
    # anonymous=True flag means that rospy will choose a unique
    # name for our 'listener' node so that multiple listeners can
    # run simultaneously.
    rospy.init_node('listener', anonymous=True)

    rospy.Subscriber("/cam0/events", EventArray, callback)

    # spin() simply keeps python from exiting until this node is stopped
    rospy.spin()

if __name__ == '__main__':
    flag=True
    listener()

结果发现打印频率和监听频率对不上,每次输出的都不太一样(有的给漏掉了),说明不能用这这种方法。后来听别人的,又在rospy.Subscriber("/cam0/events", EventArray, callback)中加了一堆消息队列和缓冲序列,还是有问题。

通过这种方式在终端中运行python脚本,首先是需在终端中启用ssim,其次,如果安装了anaconda的话,需要在~/.bashrc下面把anaconda的环境变量注释掉。python3是不能用rospy的,会报错,找不到rospkg。因此在命令行里的python应该是python2才行,所以需要去掉环境变量中的anaconda去掉,让默认启动的python是2而不是3。

之后又想通过matlab解析这个bag包,结果用github上的开源版本,bug一堆,关键这个消息还是自己定义的,可谓浪费时间。(还花了段时间在ubuntu下面装matlab,感觉自己简直像弱智)

最后,发现python本来就有方法读取,rosbag就可以了。至于里面的数据结构怎么定义的,可以拿关键字“dir”写在脚本里看一下。试了好一会,最后写完的代码如下:

#!/usr/bin/env python
import rosbag
from tqdm import tqdm
bag=rosbag.Bag('out.bag')
with open("out.txt",'w') as f: 
    for i,(topic,msgs,t) in enumerate(bag.read_messages(topics=['/cam0/events'])):
        for single_event in tqdm(msgs.events):  
            f.write(str(single_event.ts.secs+single_event.ts.nsecs*1.0/1000000000)+' ')         
            f.write(str(single_event.x)+' ')
	        f.write(str(single_event.y)+' ')
            if(single_event.polarity==True):        
	            f.write("1")
            else:
                f.write("0")
	    f.write('\n')  
        print("Writing events between two pic, now is "+ str(i)+'!')
print("Writing is over!")
bag.close()

把这个文件命名为reader.py,放置在生成的out.bag同一路径下。

注意,为了可视化进度,我安装了tqdm。安装指令:

pip install tqdm

之后通过如下指令,解析bag,记录到txt中:

ssim
python reader.py

  • 20
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 41
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 41
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值