Spaces:
Running on Zero
Running on Zero
| from textwrap import wrap | |
| import matplotlib | |
| from matplotlib.patches import Rectangle | |
| import numpy as np | |
| from matplotlib import pyplot as plt | |
| from matplotlib.axes import Axes | |
| from matplotlib.figure import Figure | |
| import inspect | |
| from typing import Dict, List, Tuple | |
| import textwrap | |
| import random | |
| class TimelineVisualizer(object): | |
| LEFT_MARGIN = -50 | |
| def __init__( | |
| self, | |
| ax:Axes, | |
| data:Dict[str, List[Tuple[int, int, str]]], | |
| total_frames:int, | |
| title:str|None=None | |
| ): | |
| ''' | |
| data: | |
| set_name: [(start_frame, end_frame, text)] | |
| ''' | |
| self.ax = ax | |
| self.data = data | |
| self.title = title | |
| self.total_frames = total_frames | |
| def get_text_wrapping_width(self, fontsize, x_left, x_right): | |
| fig:Figure = self.ax.get_figure() | |
| dpi = fig.get_dpi() | |
| pixel_coords = self.ax.transData.transform([(x_left, 0), (x_right, 0)]) | |
| available_width_pixels = pixel_coords[1, 0] - pixel_coords[0, 0] | |
| avg_char_width_pixels = fontsize * 0.5 * (dpi / 72.0) | |
| if avg_char_width_pixels <= 0: | |
| return 1 | |
| wrap_width = int(available_width_pixels / avg_char_width_pixels) | |
| return wrap_width | |
| def get_random_light_color(): | |
| min_val = 180 | |
| # 在阈值和255之间生成随机整数 | |
| r = random.randint(min_val, 255) | |
| g = random.randint(min_val, 255) | |
| b = random.randint(min_val, 255) | |
| # Matplotlib 的颜色元组格式要求值为 0-1 的浮点数, | |
| # 因此需要将 0-255 的整数进行归一化处理(除以255) | |
| return (r / 255.0, g / 255.0, b / 255.0) | |
| def initialize_ax(self): | |
| self.ax.set_xlim(self.LEFT_MARGIN, self.total_frames) | |
| self.ax.set_ylim(-0.8 * len(self.data), 1) | |
| self.ax.set_xticks(range(0, self.total_frames + 1, 50)) | |
| self.ax.set_yticks([]) | |
| self.ax.set_xlabel("Frames", fontsize=10) | |
| self.ax.spines[['left', 'right', 'top']].set_visible(False) | |
| self.vline = self.ax.axvline(0, color='k', lw=2) | |
| for set_index, (set_name, set_segments) in enumerate(self.data.items()): | |
| wrapped_set_name = textwrap.fill(set_name, width=13) | |
| self.ax.text(self.LEFT_MARGIN + 1, -0.8 * set_index + 0.4, wrapped_set_name, ha='left', va='center', weight='bold', fontsize=9) | |
| for start_frame, end_frame, text in set_segments: | |
| face_color = TimelineVisualizer.get_random_light_color() | |
| self.ax.add_patch(Rectangle((start_frame, -0.8 * set_index), end_frame - start_frame, 0.8, ec='k', lw=0.5, facecolor=face_color)) | |
| auto_width = self.get_text_wrapping_width(9, start_frame, end_frame) | |
| wrapped_text = textwrap.fill(text, width=auto_width) | |
| self.ax.text((start_frame + end_frame) / 2, -0.8 * set_index + 0.4, wrapped_text, ha='center', va='center', fontsize=9) | |
| def update(self, frame): | |
| self.vline.set_xdata((frame, frame)) | |
| if __name__ == "__main__": | |
| fig = plt.figure() | |
| ax = fig.add_subplot(1, 1, 1) | |
| print(inspect.getfile(type(ax))) | |
| print(isinstance(ax, Axes)) | |