1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| 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")
|