lihao57 commited on
Commit
7ebf5dc
·
0 Parent(s):

initial commit

Browse files
Files changed (7) hide show
  1. .gitattributes +35 -0
  2. .gitignore +3 -0
  3. .pre-commit-config.yaml +13 -0
  4. README.md +27 -0
  5. app.py +254 -0
  6. requirements.txt +4 -0
  7. utils/event.py +57 -0
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ .vscode
2
+ .gradio
3
+ **/__pycache__
.pre-commit-config.yaml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ repos:
2
+ - repo: https://github.com/psf/black
3
+ rev: 22.3.0
4
+ hooks:
5
+ - id: black
6
+ args: [--line-length=120]
7
+ - repo: https://github.com/pre-commit/pre-commit-hooks
8
+ rev: v3.2.0
9
+ hooks:
10
+ - id: check-json
11
+ - id: end-of-file-fixer
12
+ - id: trailing-whitespace
13
+ - id: requirements-txt-fixer
README.md ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: FE-LineViewer
3
+ emoji: 🌖
4
+ colorFrom: pink
5
+ colorTo: indigo
6
+ sdk: gradio
7
+ sdk_version: 5.44.1
8
+ app_file: app.py
9
+ pinned: false
10
+ license: mit
11
+ short_description: Frame-Event Line Segment Detection Dataset Viewer Space
12
+ ---
13
+
14
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
15
+
16
+ # Install
17
+ ```shell
18
+ git clone https://huggingface.co/spaces/lh9171338/FE-LineViewer
19
+ cd FE-LineViewer
20
+ python3 -m pip install -r requirements.txt
21
+ ```
22
+
23
+ # Run
24
+
25
+ ```shell
26
+ python3 app.py
27
+ ```
app.py ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ """
4
+ @File : app.py
5
+ @Time : 2025/8/29 15:25:00
6
+ @Author : lh9171338
7
+ @Version : 1.0
8
+ @Contact : 2909171338@qq.com
9
+ """
10
+
11
+ import os
12
+ import gradio as gr
13
+ from PIL import Image
14
+ import io
15
+ import logging
16
+ import matplotlib.pyplot as plt
17
+ import numpy as np
18
+ from datasets import load_dataset, DatasetDict
19
+ from utils.event import Event
20
+
21
+
22
+ dataset_dict = dict()
23
+ dataset = None
24
+ default_split_selector_info = dict(
25
+ choices=["train", "test"],
26
+ label="Split",
27
+ value="train",
28
+ interactive=False,
29
+ )
30
+ default_index_slider_info = dict(
31
+ minimum=0,
32
+ maximum=1,
33
+ step=1,
34
+ label="Index",
35
+ value=0,
36
+ interactive=False,
37
+ )
38
+ sample_info = dict(
39
+ dataset=dataset,
40
+ split="train",
41
+ index=0,
42
+ blur_image=None,
43
+ event_image=None,
44
+ start_image=None,
45
+ end_image=None,
46
+ )
47
+
48
+
49
+ def get_dataset(dataset_name):
50
+ """
51
+ Get dataset
52
+
53
+ Args:
54
+ dataset_name (str): dataset name or path
55
+
56
+ Returns:
57
+ dataset (datasets.Dataset): dataset
58
+ """
59
+ global dataset_dict
60
+ if dataset_name in dataset_dict:
61
+ dataset = dataset_dict[dataset_name]
62
+ else:
63
+ if os.path.exists(dataset_name):
64
+ dataset = load_dataset(dataset_name, data_dir=dataset_name, trust_remote_code=True)
65
+ else:
66
+ dataset = load_dataset(dataset_name, trust_remote_code=True)
67
+ dataset_dict[dataset_name] = dataset
68
+ return dataset
69
+
70
+
71
+ def submit_callback(dataset_name):
72
+ """
73
+ Submit callback function
74
+
75
+ Args:
76
+ dataset_name (str): dataset name or path
77
+
78
+ Returns:
79
+ split_selector_info (dict): updated split selector info
80
+ index_slider_info (dict): updated index slider info
81
+ blur_image (PIL.Image): updated blur image
82
+ event_image (PIL.Image): updated event image
83
+ start_image (PIL.Image): updated start image
84
+ end_image (PIL.Image): updated end image
85
+ """
86
+ global dataset
87
+ try:
88
+ dataset = get_dataset(dataset_name)
89
+ except Exception as e:
90
+ dataset = None
91
+ logging.error(f"Load dataset failed: {e}")
92
+ split_selector_info = gr.update(**default_split_selector_info)
93
+ index_slider_info = gr.update(**default_index_slider_info)
94
+ return split_selector_info, index_slider_info, None, None, None, None
95
+
96
+ if not isinstance(dataset, DatasetDict):
97
+ dataset = {str(dataset.split): dataset}
98
+ splits = list(dataset.keys())
99
+ split = splits[0]
100
+ maximum = len(dataset[split]) - 1
101
+ index = 0
102
+ split_selector_info = gr.update(choices=splits, value=split, interactive=True)
103
+ index_slider_info = gr.update(minimum=0, maximum=maximum, value=index, interactive=True)
104
+ blur_image, event_image, start_image, end_image = show_image(split=split, index=index)
105
+ return split_selector_info, index_slider_info, blur_image, event_image, start_image, end_image
106
+
107
+
108
+ def selector_change_callback(split):
109
+ """
110
+ Selector change callback function
111
+
112
+ Args:
113
+ split (str): selected split, value must be one of ["train", "test"]
114
+
115
+ Returns:
116
+ index_slider_info (dict): updated slider info
117
+ blur_image (PIL.Image): updated blur image
118
+ event_image (PIL.Image): updated event image
119
+ start_image (PIL.Image): updated start image
120
+ end_image (PIL.Image): updated end image
121
+ """
122
+ global dataset
123
+ if dataset is None:
124
+ index_slider_info = gr.update(**default_index_slider_info)
125
+ return index_slider_info, None, None, None, None
126
+
127
+ maximum = len(dataset[split]) - 1
128
+ index = 0
129
+ index_slider_info = gr.update(minimum=0, maximum=maximum, value=index)
130
+ blur_image, event_image, start_image, end_image = show_image(split=split, index=index)
131
+ return index_slider_info, blur_image, event_image, start_image, end_image
132
+
133
+
134
+ def draw_lines(image, lines):
135
+ """
136
+ Draw lines on image
137
+
138
+ Args:
139
+ image (np.ndarray): input image
140
+ lines (np.ndarray): list of lines, with shape [N, 2, 2]
141
+
142
+ Returns:
143
+ image (PIL.Image): drawn image
144
+ """
145
+ height, width = image.shape[:2]
146
+ fig = plt.figure()
147
+ fig.set_size_inches(width / height, 1, forward=False)
148
+ ax = plt.Axes(fig, [0.0, 0.0, 1.0, 1.0])
149
+ ax.set_axis_off()
150
+ fig.add_axes(ax)
151
+ plt.xlim([-0.5, width - 0.5])
152
+ plt.ylim([height - 0.5, -0.5])
153
+ plt.imshow(image)
154
+ for pts in lines:
155
+ pts = pts - 0.5
156
+ plt.plot(pts[:, 0], pts[:, 1], color="orange", linewidth=0.5)
157
+ plt.scatter(pts[:, 0], pts[:, 1], color="#33FFFF", s=1.2, edgecolors="none", zorder=5)
158
+
159
+ buf = io.BytesIO()
160
+ fig.savefig(buf, format="png", dpi=height, bbox_inches=0)
161
+ buf.seek(0)
162
+ plt.close(fig)
163
+ image = Image.open(buf)
164
+ return image
165
+
166
+
167
+ def show_image(split, index):
168
+ """
169
+ Show image
170
+
171
+ Args:
172
+ split (str): split name, value must be one of ["train", "test"]
173
+ index (int): index of the sample
174
+
175
+ Returns:
176
+ blur_image (PIL.Image): drawn blurred image
177
+ event_image (PIL.Image): drawn event image
178
+ start_image (PIL.Image): drawn start image
179
+ end_image (PIL.Image): drawn end image
180
+ """
181
+ global dataset
182
+ if dataset is None:
183
+ return None, None, None, None
184
+
185
+ global sample_info
186
+ old_sample_info = dict(
187
+ dataset=sample_info["dataset"],
188
+ split=sample_info["split"],
189
+ index=sample_info["index"],
190
+ )
191
+ new_sample_info = dict(dataset=dataset, split=split, index=index)
192
+ if old_sample_info == new_sample_info: # No need to update
193
+ logging.info("No need to update")
194
+ return sample_info["blur_image"], sample_info["event_image"], sample_info["start_image"], sample_info["end_image"]
195
+
196
+ sample = dataset[split][index]
197
+ blur_image = sample["blur_image"]
198
+ start_image = np.array(sample["start_image"])
199
+ end_image = np.array(sample["end_image"])
200
+ lines = np.array(sample["lines"]).reshape(-1, 2, 2)
201
+ event_image = Image.fromarray(Event(events=sample["events"]).event2image())
202
+ event_image = event_image.resize(blur_image.size)
203
+ start_image = draw_lines(start_image, lines)
204
+ end_image = draw_lines(end_image, lines)
205
+ sample_info.update(new_sample_info)
206
+ sample_info["blur_image"] = blur_image
207
+ sample_info["event_image"] = event_image
208
+ sample_info["start_image"] = start_image
209
+ sample_info["end_image"] = end_image
210
+ logging.info("Update")
211
+ return blur_image, event_image, start_image, end_image
212
+
213
+
214
+ def main():
215
+ """
216
+ Main
217
+
218
+ Args:
219
+ None
220
+
221
+ Returns:
222
+ None
223
+ """
224
+ with gr.Blocks() as demo:
225
+ dataset_textbox = gr.Textbox(value="lh9171338/FE-Blurframe", label="Dataset name or path")
226
+ split_selector = gr.Dropdown(**default_split_selector_info)
227
+ index_slider = gr.Slider(**default_index_slider_info)
228
+ with gr.Row():
229
+ blur_image = gr.Image(label="Blurred Image")
230
+ event_image = gr.Image(label="Event Image")
231
+ start_image = gr.Image(label="Start Image")
232
+ end_image = gr.Image(label="End Image")
233
+
234
+ dataset_textbox.submit(
235
+ submit_callback,
236
+ dataset_textbox,
237
+ [split_selector, index_slider, blur_image, event_image, start_image, end_image],
238
+ )
239
+ split_selector.change(selector_change_callback, split_selector, [index_slider, blur_image, event_image, start_image, end_image])
240
+ index_slider.change(show_image, [split_selector, index_slider], [blur_image, event_image, start_image, end_image])
241
+ demo.load(
242
+ submit_callback,
243
+ dataset_textbox,
244
+ [split_selector, index_slider, blur_image, event_image, start_image, end_image],
245
+ )
246
+ demo.launch(share=False)
247
+
248
+
249
+ if __name__ == "__main__":
250
+ # set base logging config
251
+ fmt = "[%(asctime)s - %(levelname)s - %(filename)s:%(lineno)s] %(message)s"
252
+ logging.basicConfig(format=fmt, level=logging.INFO)
253
+
254
+ main()
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ datasets
2
+ matplotlib
3
+ numpy<2
4
+ pillow
utils/event.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ """
4
+ @File : event.py
5
+ @Time : 2025/9/3 15:25:00
6
+ @Author : lh9171338
7
+ @Version : 1.0
8
+ @Contact : 2909171338@qq.com
9
+ """
10
+
11
+ import numpy as np
12
+
13
+
14
+ class Event:
15
+ """
16
+ Event
17
+
18
+ Args:
19
+ filename (str | None): path to the event file
20
+ events (dict | None): event data
21
+ """
22
+ def __init__(self, filename=None, events=None, **kwargs):
23
+ assert filename is not None or events is not None
24
+ if filename is not None:
25
+ events = np.load(filename)
26
+ events = dict(**events)
27
+ events["x"] = np.array(events["x"], dtype="int16")
28
+ events["y"] = np.array(events["y"], dtype="int16")
29
+ events["p"] = np.array(events["p"], dtype="int16")
30
+ events["t"] = np.array(events["t"], dtype="int32")
31
+
32
+ self.filename = filename
33
+ self.events = events
34
+
35
+ def event2image(self):
36
+ """
37
+ Convert event to image
38
+
39
+ Args:
40
+ None
41
+
42
+ Returns:
43
+ image (numpy.ndarray): event image
44
+ """
45
+ width, height = self.events["image_size"]
46
+ xs = self.events["x"]
47
+ ys = self.events["y"]
48
+ ps = self.events["p"]
49
+
50
+ event = np.zeros((height, width, 2), dtype="float32")
51
+ np.add.at(event, (ys, xs, ps), 1)
52
+ np.add.at(event, (ys, xs, ps), 1)
53
+ neg = event[:, :, 0]
54
+ pos = event[:, :, 1]
55
+ image = np.stack((neg, np.zeros_like(neg), pos), axis=-1)
56
+ image = (((image / image.max()) ** 0.5) * 255).astype(np.uint8)
57
+ return image