Tonic.utils.plot.grid()
イベントを視覚化し、フレームに描画します
1.関数プロトタイプ
機能: 目視検査のために、軸の積に等しいフレームにイベントを蓄積します。
import numpy as np
import tonic.transforms as transforms
def plot_event_grid(events, axis_array=(1, 3), plot_frame_number=False):
"""Plot events accumulated as frames equal to the product of axes for visual inspection.
Parameters:
events: Structured numpy array of shape [num_events, num_event_channels].
事件流,numpy数组
axis_array: dimensions of plotting grid. The larger the grid,
the more fine-grained the events will be sliced in time.
将事件流,绘制成帧,并用网格形式表示出来,此处可设定帧的数量,以axis_array=(2,3)为例,则帧的数量为2*3=6,以2行3列的网格显示出 来
plot_frame_number: optional index of frame when plotting
绘图时帧的可选索引
Example:
>>> import tonic
>>> dataset = tonic.datasets.NMNIST(save_to='./data')
>>> events, target = dataset[100]
>>> tonic.utils.plot_event_grid(events)
Returns:
None
"""
try:
import matplotlib.pyplot as plt
except ImportError:
raise ImportError(
"Please install the matplotlib package to plot events. This is an optional"
" dependency."
)
# 事件流events是一个numpy列表,其中dtype为 [('x', '<i8'), ('y', '<i8'), ('t', '<i8'), ('p', '<i8')]
# events.dtype.names 为 ('x', 'y', 't', 'p') 表示一个事件的坐标x,y(像素坐标系) 时间辍,极性
if "y" in events.dtype.names:
# 得到了 events 事件流中事件在像素坐标系中横坐标与纵坐标的最大值,用于绘制帧的尺寸
sensor_size_x = int(events["x"].max() + 1)
sensor_size_y = int(events["y"].max() + 1)
# np.unique(events["p"]) 对于一个以为列表或者数组,去除重复元素,并按照元素从小到大返回一个新的列表或者元组
# 此处得到了,事件有机种极性,也代表着之后的事件帧有几个通道
sensor_size_p = len(np.unique(events["p"]))
# 此处为帧的尺寸,长、宽、通道数
sensor_size = (sensor_size_x, sensor_size_y, sensor_size_p)
# 将事件转化为事件帧,sensor_size为事件帧的尺寸,n_time_bins为按照时间箱得到固定的帧数
# np.product(axis_array) 返回数组或者元组 axis_array中元素的乘积。即时间流通过切片方式得到的事件帧的数量
transform = transforms.ToFrame(
sensor_size=sensor_size, n_time_bins=np.product(axis_array)
)
# 将事件流转化为事件帧
frames = transform(events)
# *axis_array在python中表示 将数组或者元组解开成几个独立的参数,传入函数,如axis_array=(2,3),则*axis_array = 2 3
# plt.subplots(m,n) 绘制 m*n个子图,字图在一个大图中以m行n列的方式显示
# 函数的返回值是一个元组,包括一个图形对象和所有的 axes_array 对象。
# 其中 axes_array 对象(含所有子图的一个数组)的数量等于 nrows * ncols,且每个 axes_array 对象均可通过索引值访问
# fig 的类型就是一个大的画布,所有子图均显示在上面(<class 'matplotlib.figure.Figure'>)
fig, axes_array = plt.subplots(*axis_array)
if 1 in axis_array:
axes_array = axes_array.reshape(1, -1)
for i in range(axis_array[0]):
for j in range(axis_array[1]):
# 按照索引得到一帧图像
frame = frames[i * axis_array[1] + j]
# 将事件帧的两个通道的像素值进行作差---并在子图中显示出来,可以简单的看出事件相机在录制数据时的移动方向
axes_array[i, j].imshow(frame[1] - frame[0])
# 关闭子图中所有坐标轴线、刻度标记和标签
axes_array[i, j].axis("off")
# 是否给每张子图设置一个标题 title
if plot_frame_number:
axes_array[i, j].title.set_text(str(i * axis_array[1] + j))
# 自动调整子图参数,使之填充整个图像区域
plt.tight_layout()
# 显示所有的figure,这是必要的,若没有则会出现,只出现一张子图的情况
plt.show()
else:
sensor_size_x = int(events["x"].max() + 1)
frame_transform = transforms.ToFrame(
sensor_size=(sensor_size_x, 1, 1), n_time_bins=sensor_size_x * 2
)
frames = frame_transform(events)
plt.imshow(frames.squeeze().T)
plt.xlabel("Time")
plt.ylabel("Channels")
1. プログラム例:
"""
将事件数据转换为帧
"""
import tonic
import tonic.transforms as transforms
import matplotlib.pyplot as plt
import torch
# 下载 NMINST 数据
dataset = tonic.datasets.NMNIST(save_to="/home/zxz/Proj/DP/Do/demo_03/Tonic_dir/tutorials/data",train=False)
print(len(dataset)) # 10000
events,target = dataset[1000]
print(events) # numpy数组
"""
每行对应一个事件,由四个参数组成:(x坐标、y坐标、时间戳、极性)
x和y坐标对应34*34网格中的地址
事件的时间戳以微秒为单位记录
极性指的是是否发生了峰上(+1)或峰下(-1);即,亮度的增加或减少
"""
# 将许多事件累积到一个框架中,使其可视化---将事件流划分为3*2个事件帧
tonic.utils.plot_event_grid(events,axis_array=(3,2))
ディスプレイ効果
2. 同じ効果を持つプログラムを手書きする
"""
将事件数据转换为帧---对tonic中的一些操作进行合并
"""
import tonic
import tonic.transforms as transforms
import matplotlib.pyplot as plt
import torch
import torchvision
"""
事件帧的可视化程序,将事件帧可视化
"""
def plot_frames(frames):
# subplots 生成 1*len(frames) 个子图像
# 函数的返回值是一个元组,包括一个图形对象和所有的 axes 对象。
# 其中 axes 对象的数量等于 nrows * ncols,且每个 axes 对象均可通过索引值访问(从1开始)
fig, axes = plt.subplots(1, len(frames))
# zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表
for axis, frame in zip(axes, frames):
# 让画布上的每一个子图显示一个图像
axis.imshow((frame[1]-frame[0]))
# 关闭所有坐标轴线、刻度标记和标签next(iternext(iter
axis.axis("off")
# 自动调整子图参数,使之填充整个图像区域
plt.tight_layout()
# 显示所有的figure,这是必要的,若没有则会出现,只出现一张子图的情况
plt.show()
# 设置 CPU 生成随机数的 种子,可见不同的随机种子能够生成不同的随机数,但只要随机种子一样,每次运行代码都会生成该种子下的随机数
torch.manual_seed(1234)
# 手动转化
sensor_size = tonic.datasets.NMNIST.sensor_size
# 帧有尺寸(时间,极性数,高度和宽度)。让我们为N-MNIST样本中的三次扫视绘制一个帧。我们将利用两个相机的极性差来观察运动方向
# 用时间箱将事件流划分为 数量为n_time_bins的事件帧
frame_transfrom = transforms.ToFrame(sensor_size=sensor_size,n_time_bins=6)
# 对事件进行去噪
denoise_transform = tonic.transforms.Denoise(filter_time=10000)
# 对事件的变化操作
transform = transforms.Compose([denoise_transform,frame_transfrom])
# 下载 NMINST 数据 --- 已经对NMINST中数据进行处理变为帧
dataset = tonic.datasets.NMNIST(
save_to="/home/zxz/Proj/DP/Do/demo_03/Tonic_dir/tutorials/data", train=False, transform=transform
)
frame,target = dataset[1000]
plot_frames(frame)
ディスプレイ効果