Nidhamtek commited on
Commit
e6c1019
·
1 Parent(s): 5c2b142

Add Gradio app, requirements and timeline encodings

Browse files
README.md CHANGED
@@ -1,6 +1,6 @@
1
  ---
2
  title: Timeline Vlm
3
- emoji: 🐨
4
  colorFrom: purple
5
  colorTo: blue
6
  sdk: gradio
@@ -9,4 +9,11 @@ app_file: app.py
9
  pinned: false
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
1
  ---
2
  title: Timeline Vlm
3
+ emoji: 🕰️
4
  colorFrom: purple
5
  colorTo: blue
6
  sdk: gradio
 
9
  pinned: false
10
  ---
11
 
12
+ # 🕰️ Timeline VLM Visual Artifact Year Estimation
13
+
14
+ Demo for the paper **[Can Vision-Language Models Tell When Things Were Made?](https://arxiv.org/pdf/2510.19559)**
15
+
16
+ Upload images of visual artifacts (paintings, photographs, architecture, sculptures…) and the
17
+ model estimates **when they were created** by projecting CLIP embeddings onto a learned temporal Bézier curve.
18
+
19
+ 📄 [Paper](https://arxiv.org/pdf/2510.19559) · 💻 [GitHub](https://github.com/TekayaNidham/timeline-vlm)
app.py ADDED
@@ -0,0 +1,295 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify, render_template, send_from_directory
2
+ import numpy as np
3
+ import os
4
+ import torch
5
+ import clip
6
+ from PIL import Image
7
+ from sklearn.decomposition import KernelPCA
8
+ import io
9
+ import base64
10
+ import traceback
11
+ import matplotlib
12
+ matplotlib.use('Agg')
13
+ import matplotlib.pyplot as plt
14
+ from matplotlib.colors import Normalize
15
+ import matplotlib.cm as cm
16
+ from matplotlib.lines import Line2D
17
+ import uuid
18
+ import shutil
19
+ import atexit
20
+
21
+ app = Flask(__name__, static_folder='static', template_folder='templates')
22
+
23
+ DATA_PATHS = {
24
+ 'clip': {
25
+ 'timeline_embeddings': 'encodings/timeline_embeddings.npy',
26
+ 'timeline_labels': 'encodings/timeline_labels.txt',
27
+ },
28
+ 'eva': {
29
+ 'timeline_embeddings': 'encodings/eva/eva_timeline_embeddings.npy',
30
+ 'timeline_labels': 'encodings/eva/eva_labels_timeline.txt',
31
+ },
32
+ }
33
+
34
+ UPLOAD_FOLDER = 'static/uploads'
35
+ os.makedirs(UPLOAD_FOLDER, exist_ok=True)
36
+
37
+ # Per-session state (in-memory; fine for a demo)
38
+ _session_embeddings: dict[str, list] = {}
39
+ _session_labels: dict[str, list] = {}
40
+ _session_paths: dict[str, list] = {}
41
+
42
+ # ── CLIP model ────────────────────────────────────────────────────────────────
43
+ try:
44
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
45
+ model, preprocess = clip.load("ViT-B/32", device=device)
46
+ CLIP_AVAILABLE = True
47
+ print(f"CLIP loaded on {device}")
48
+ except Exception as e:
49
+ CLIP_AVAILABLE = False
50
+ print(f"CLIP not available: {e}")
51
+
52
+
53
+ # ── Core math ─────────────────────────────────────────────────────────────────
54
+ def de_casteljau(pts, t):
55
+ pts = pts.copy()
56
+ for r in range(1, len(pts)):
57
+ pts[: len(pts) - r] = (1 - t) * pts[: len(pts) - r] + t * pts[1 : len(pts) - r + 1]
58
+ return pts[0]
59
+
60
+
61
+ def bezier_curve(control_points, num_points=1000):
62
+ return np.array([de_casteljau(control_points, t) for t in np.linspace(0, 1, num_points)])
63
+
64
+
65
+ def project_onto_curve(points, curve):
66
+ projected, indices = [], []
67
+ for p in points:
68
+ d = np.linalg.norm(curve - p, axis=1)
69
+ idx = np.argmin(d)
70
+ projected.append(curve[idx])
71
+ indices.append(idx)
72
+ return np.array(projected), np.array(indices)
73
+
74
+
75
+ # ── Encoding ──────────────────────────────────────────────────────────────────
76
+ def encode_image(image_bytes: bytes) -> np.ndarray:
77
+ if not CLIP_AVAILABLE:
78
+ return np.random.randn(512)
79
+ img = Image.open(io.BytesIO(image_bytes)).convert("RGB")
80
+ tensor = preprocess(img).unsqueeze(0).to(device)
81
+ with torch.no_grad():
82
+ emb = model.encode_image(tensor).cpu().numpy().flatten()
83
+ return emb
84
+
85
+
86
+ # ── Embedding pipeline ────────────────────────────────────────────────────────
87
+ def load_embeddings(data_type: str = 'clip'):
88
+ paths = DATA_PATHS[data_type]
89
+ try:
90
+ embeddings = np.load(paths['timeline_embeddings'])
91
+ with open(paths['timeline_labels']) as f:
92
+ labels = [l.strip() for l in f]
93
+ return embeddings, labels
94
+ except FileNotFoundError:
95
+ print("Embedding files not found – using synthetic data.")
96
+ embeddings = np.random.randn(20, 512)
97
+ labels = [str(1700 + i * 15) for i in range(20)]
98
+ return embeddings, labels
99
+
100
+
101
+ def process_embeddings(timeline_embs, timeline_labels, dimension=3,
102
+ n_ctrl=300, user_embs=None, user_labels=None, user_paths=None):
103
+ kpca = KernelPCA(n_components=dimension, kernel="cosine")
104
+ reduced = kpca.fit_transform(timeline_embs)
105
+
106
+ idx = np.linspace(0, len(reduced) - 1, min(n_ctrl, len(reduced)), dtype=int)
107
+ ctrl = reduced[idx]
108
+ curve = bezier_curve(ctrl, num_points=1000)
109
+ proj_text, text_idx = project_onto_curve(reduced, curve)
110
+
111
+ years = []
112
+ for lbl in timeline_labels:
113
+ try:
114
+ years.append(int(lbl))
115
+ except ValueError:
116
+ years.append(1900)
117
+
118
+ out = dict(reduced_text=reduced, projected_text=proj_text,
119
+ text_indices=text_idx, bezier_points=curve,
120
+ years=years, timeline_labels=timeline_labels)
121
+
122
+ if user_embs and len(user_embs) > 0:
123
+ r_user = kpca.transform(np.array(user_embs))
124
+ p_user, u_idx = project_onto_curve(r_user, curve)
125
+ out.update(reduced_uploads=r_user, projected_uploads=p_user,
126
+ upload_indices=u_idx, upload_labels=user_labels,
127
+ upload_paths=user_paths)
128
+ return out
129
+
130
+
131
+ # ── Matplotlib 3-D visualisation ──────────��───────────────────────────────────
132
+ def make_figure(data, show_original=False) -> str:
133
+ reduced = data['reduced_text']
134
+ projected = data['projected_text']
135
+ curve = data['bezier_points']
136
+ years = data['years']
137
+
138
+ fig = plt.figure(figsize=(13, 10))
139
+ ax = fig.add_subplot(111, projection='3d')
140
+
141
+ norm = Normalize(vmin=min(years), vmax=max(years))
142
+ cmap = cm.viridis
143
+
144
+ if show_original:
145
+ ax.scatter(*reduced.T, c=years, cmap='viridis', s=20, alpha=0.4,
146
+ label='Original embeddings')
147
+
148
+ sc = ax.scatter(*projected.T, c=years, cmap='viridis', s=35,
149
+ label='Projected points', zorder=5)
150
+ ax.plot(*curve.T, 'r-', linewidth=1.2, label='Bézier curve', zorder=10)
151
+
152
+ # Year annotations every ~10 ticks
153
+ step = max(1, (max(years) - min(years)) // 11)
154
+ annotated = set(range(min(years), max(years) + 1, step))
155
+ for yr, pt in zip(years, projected):
156
+ if yr in annotated:
157
+ ax.text(pt[0], pt[1], pt[2], str(yr), fontsize=7,
158
+ ha='right', color='#222')
159
+
160
+ # User images
161
+ if 'projected_uploads' in data:
162
+ pu = data['projected_uploads']
163
+ u_idx = data['upload_indices']
164
+ t_idx = data['text_indices']
165
+ t_lbls = data['timeline_labels']
166
+
167
+ for i, pt in enumerate(pu):
168
+ lifted = pt.copy(); lifted[2] += 0.02
169
+ ax.scatter(*lifted, c='gold', marker='*', s=600,
170
+ edgecolors='black', linewidth=1.5, zorder=1000)
171
+ near = np.argmin(np.abs(t_idx - u_idx[i]))
172
+ pred_yr = t_lbls[near]
173
+ ax.text(lifted[0], lifted[1], lifted[2] + 0.01,
174
+ f"~{pred_yr}", fontsize=8, color='darkred', fontweight='bold')
175
+
176
+ ax.legend(handles=[
177
+ Line2D([0],[0], marker='*', color='w', markerfacecolor='gold',
178
+ markersize=14, label='Your images', markeredgecolor='black')
179
+ ], loc='upper right', fontsize=9)
180
+
181
+ cbar = plt.colorbar(sc, ax=ax, pad=0.05, shrink=0.55)
182
+ cbar.set_label('Year')
183
+ ax.set_xlabel('Dim 1'); ax.set_ylabel('Dim 2'); ax.set_zlabel('Dim 3')
184
+ ax.view_init(elev=30, azim=45)
185
+ plt.tight_layout()
186
+
187
+ buf = io.BytesIO()
188
+ plt.savefig(buf, format='png', dpi=130, bbox_inches='tight')
189
+ plt.close(fig)
190
+ buf.seek(0)
191
+ return base64.b64encode(buf.read()).decode()
192
+
193
+
194
+ # ── Routes ────────────────────────────────────────────────────────────────────
195
+ @app.route('/')
196
+ def index():
197
+ return render_template('index.html')
198
+
199
+
200
+ @app.route('/static/<path:path>')
201
+ def serve_static(path):
202
+ return send_from_directory('static', path)
203
+
204
+
205
+ @app.route('/api/visualize')
206
+ def api_visualize():
207
+ data_type = request.args.get('type', 'clip')
208
+ n_ctrl = int(request.args.get('controlPoints', 300))
209
+ show_orig = request.args.get('showOriginal', 'false').lower() == 'true'
210
+ session_id = request.args.get('sessionId', 'default')
211
+
212
+ try:
213
+ t_embs, t_lbls = load_embeddings(data_type)
214
+
215
+ u_embs = _session_embeddings.get(session_id, [])
216
+ u_lbls = _session_labels.get(session_id, [])
217
+ u_paths = _session_paths.get(session_id, [])
218
+
219
+ vis_data = process_embeddings(t_embs, t_lbls, dimension=3,
220
+ n_ctrl=n_ctrl,
221
+ user_embs=u_embs or None,
222
+ user_labels=u_lbls or None,
223
+ user_paths=u_paths or None)
224
+ img_b64 = make_figure(vis_data, show_original=show_orig)
225
+
226
+ # Build prediction list
227
+ predictions = []
228
+ if 'upload_indices' in vis_data:
229
+ t_idx = vis_data['text_indices']
230
+ u_idx = vis_data['upload_indices']
231
+ t_lbls_ = vis_data['timeline_labels']
232
+ for i, lbl in enumerate(vis_data['upload_labels']):
233
+ near = np.argmin(np.abs(t_idx - u_idx[i]))
234
+ pred_yr = t_lbls_[near]
235
+ conf = max(0, 100 - abs(int(u_idx[i]) - int(t_idx[near])) / 10)
236
+ predictions.append({
237
+ 'label': lbl,
238
+ 'year': pred_yr,
239
+ 'confidence': f"{conf:.1f}%",
240
+ 'path': vis_data['upload_paths'][i],
241
+ })
242
+
243
+ return jsonify(success=True, visualization=img_b64, predictions=predictions)
244
+
245
+ except Exception as e:
246
+ traceback.print_exc()
247
+ return jsonify(success=False, error=str(e))
248
+
249
+
250
+ @app.route('/api/encode', methods=['POST'])
251
+ def api_encode():
252
+ if 'image' not in request.files:
253
+ return jsonify(success=False, error="No image in request")
254
+ file = request.files['image']
255
+ session_id = request.form.get('sessionId', 'default')
256
+
257
+ fname = f"{uuid.uuid4()}_{file.filename}"
258
+ fpath = os.path.join(UPLOAD_FOLDER, fname)
259
+ file.save(fpath)
260
+
261
+ with open(fpath, 'rb') as f:
262
+ emb = encode_image(f.read())
263
+
264
+ _session_embeddings.setdefault(session_id, []).append(emb)
265
+ _session_labels.setdefault(session_id, []).append(file.filename)
266
+ _session_paths.setdefault(session_id, []).append(f"/static/uploads/{fname}")
267
+
268
+ return jsonify(success=True, filename=file.filename,
269
+ path=f"/static/uploads/{fname}")
270
+
271
+
272
+ @app.route('/api/reset', methods=['POST'])
273
+ def api_reset():
274
+ session_id = request.form.get('sessionId', 'default')
275
+ for store in (_session_embeddings, _session_labels, _session_paths):
276
+ store.pop(session_id, None)
277
+ # Clean upload folder
278
+ for fn in os.listdir(UPLOAD_FOLDER):
279
+ fp = os.path.join(UPLOAD_FOLDER, fn)
280
+ try:
281
+ if os.path.isfile(fp):
282
+ os.unlink(fp)
283
+ except Exception:
284
+ pass
285
+ return jsonify(success=True)
286
+
287
+
288
+ @atexit.register
289
+ def _cleanup():
290
+ if os.path.exists(UPLOAD_FOLDER):
291
+ shutil.rmtree(UPLOAD_FOLDER, ignore_errors=True)
292
+
293
+
294
+ if __name__ == '__main__':
295
+ app.run(host='0.0.0.0', port=7860, debug=False)
encodings/eva/eva_labels_timeline.txt ADDED
@@ -0,0 +1,324 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 1700
2
+ 1701
3
+ 1702
4
+ 1703
5
+ 1704
6
+ 1705
7
+ 1706
8
+ 1707
9
+ 1708
10
+ 1709
11
+ 1710
12
+ 1711
13
+ 1712
14
+ 1713
15
+ 1714
16
+ 1715
17
+ 1716
18
+ 1717
19
+ 1718
20
+ 1719
21
+ 1720
22
+ 1721
23
+ 1722
24
+ 1723
25
+ 1724
26
+ 1725
27
+ 1726
28
+ 1727
29
+ 1728
30
+ 1729
31
+ 1730
32
+ 1731
33
+ 1732
34
+ 1733
35
+ 1734
36
+ 1735
37
+ 1736
38
+ 1737
39
+ 1738
40
+ 1739
41
+ 1740
42
+ 1741
43
+ 1742
44
+ 1743
45
+ 1744
46
+ 1745
47
+ 1746
48
+ 1747
49
+ 1748
50
+ 1749
51
+ 1750
52
+ 1751
53
+ 1752
54
+ 1753
55
+ 1754
56
+ 1755
57
+ 1756
58
+ 1757
59
+ 1758
60
+ 1759
61
+ 1760
62
+ 1761
63
+ 1762
64
+ 1763
65
+ 1764
66
+ 1765
67
+ 1766
68
+ 1767
69
+ 1768
70
+ 1769
71
+ 1770
72
+ 1771
73
+ 1772
74
+ 1773
75
+ 1774
76
+ 1775
77
+ 1776
78
+ 1777
79
+ 1778
80
+ 1779
81
+ 1780
82
+ 1781
83
+ 1782
84
+ 1783
85
+ 1784
86
+ 1785
87
+ 1786
88
+ 1787
89
+ 1788
90
+ 1789
91
+ 1790
92
+ 1791
93
+ 1792
94
+ 1793
95
+ 1794
96
+ 1795
97
+ 1796
98
+ 1797
99
+ 1798
100
+ 1799
101
+ 1800
102
+ 1801
103
+ 1802
104
+ 1803
105
+ 1804
106
+ 1805
107
+ 1806
108
+ 1807
109
+ 1808
110
+ 1809
111
+ 1810
112
+ 1811
113
+ 1812
114
+ 1813
115
+ 1814
116
+ 1815
117
+ 1816
118
+ 1817
119
+ 1818
120
+ 1819
121
+ 1820
122
+ 1821
123
+ 1822
124
+ 1823
125
+ 1824
126
+ 1825
127
+ 1826
128
+ 1827
129
+ 1828
130
+ 1829
131
+ 1830
132
+ 1831
133
+ 1832
134
+ 1833
135
+ 1834
136
+ 1835
137
+ 1836
138
+ 1837
139
+ 1838
140
+ 1839
141
+ 1840
142
+ 1841
143
+ 1842
144
+ 1843
145
+ 1844
146
+ 1845
147
+ 1846
148
+ 1847
149
+ 1848
150
+ 1849
151
+ 1850
152
+ 1851
153
+ 1852
154
+ 1853
155
+ 1854
156
+ 1855
157
+ 1856
158
+ 1857
159
+ 1858
160
+ 1859
161
+ 1860
162
+ 1861
163
+ 1862
164
+ 1863
165
+ 1864
166
+ 1865
167
+ 1866
168
+ 1867
169
+ 1868
170
+ 1869
171
+ 1870
172
+ 1871
173
+ 1872
174
+ 1873
175
+ 1874
176
+ 1875
177
+ 1876
178
+ 1877
179
+ 1878
180
+ 1879
181
+ 1880
182
+ 1881
183
+ 1882
184
+ 1883
185
+ 1884
186
+ 1885
187
+ 1886
188
+ 1887
189
+ 1888
190
+ 1889
191
+ 1890
192
+ 1891
193
+ 1892
194
+ 1893
195
+ 1894
196
+ 1895
197
+ 1896
198
+ 1897
199
+ 1898
200
+ 1899
201
+ 1900
202
+ 1901
203
+ 1902
204
+ 1903
205
+ 1904
206
+ 1905
207
+ 1906
208
+ 1907
209
+ 1908
210
+ 1909
211
+ 1910
212
+ 1911
213
+ 1912
214
+ 1913
215
+ 1914
216
+ 1915
217
+ 1916
218
+ 1917
219
+ 1918
220
+ 1919
221
+ 1920
222
+ 1921
223
+ 1922
224
+ 1923
225
+ 1924
226
+ 1925
227
+ 1926
228
+ 1927
229
+ 1928
230
+ 1929
231
+ 1930
232
+ 1931
233
+ 1932
234
+ 1933
235
+ 1934
236
+ 1935
237
+ 1936
238
+ 1937
239
+ 1938
240
+ 1939
241
+ 1940
242
+ 1941
243
+ 1942
244
+ 1943
245
+ 1944
246
+ 1945
247
+ 1946
248
+ 1947
249
+ 1948
250
+ 1949
251
+ 1950
252
+ 1951
253
+ 1952
254
+ 1953
255
+ 1954
256
+ 1955
257
+ 1956
258
+ 1957
259
+ 1958
260
+ 1959
261
+ 1960
262
+ 1961
263
+ 1962
264
+ 1963
265
+ 1964
266
+ 1965
267
+ 1966
268
+ 1967
269
+ 1968
270
+ 1969
271
+ 1970
272
+ 1971
273
+ 1972
274
+ 1973
275
+ 1974
276
+ 1975
277
+ 1976
278
+ 1977
279
+ 1978
280
+ 1979
281
+ 1980
282
+ 1981
283
+ 1982
284
+ 1983
285
+ 1984
286
+ 1985
287
+ 1986
288
+ 1987
289
+ 1988
290
+ 1989
291
+ 1990
292
+ 1991
293
+ 1992
294
+ 1993
295
+ 1994
296
+ 1995
297
+ 1996
298
+ 1997
299
+ 1998
300
+ 1999
301
+ 2000
302
+ 2001
303
+ 2002
304
+ 2003
305
+ 2004
306
+ 2005
307
+ 2006
308
+ 2007
309
+ 2008
310
+ 2009
311
+ 2010
312
+ 2011
313
+ 2012
314
+ 2013
315
+ 2014
316
+ 2015
317
+ 2016
318
+ 2017
319
+ 2018
320
+ 2019
321
+ 2020
322
+ 2021
323
+ 2022
324
+ 2023
encodings/eva/eva_timeline_embeddings.npy ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:df73efb267fd7e9f81d4181cad642c82aab05afb3f3ae55dafc23d2291b961b0
3
+ size 331904
encodings/timeline_embeddings.npy ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6cca6694dcb61653c3c0e586d0f2b1210548f6d639bc44240b53fee0ea863206
3
+ size 665728
encodings/timeline_labels.txt ADDED
@@ -0,0 +1,325 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 1700
2
+ 1701
3
+ 1702
4
+ 1703
5
+ 1704
6
+ 1705
7
+ 1706
8
+ 1707
9
+ 1708
10
+ 1709
11
+ 1710
12
+ 1711
13
+ 1712
14
+ 1713
15
+ 1714
16
+ 1715
17
+ 1716
18
+ 1717
19
+ 1718
20
+ 1719
21
+ 1720
22
+ 1721
23
+ 1722
24
+ 1723
25
+ 1724
26
+ 1725
27
+ 1726
28
+ 1727
29
+ 1728
30
+ 1729
31
+ 1730
32
+ 1731
33
+ 1732
34
+ 1733
35
+ 1734
36
+ 1735
37
+ 1736
38
+ 1737
39
+ 1738
40
+ 1739
41
+ 1740
42
+ 1741
43
+ 1742
44
+ 1743
45
+ 1744
46
+ 1745
47
+ 1746
48
+ 1747
49
+ 1748
50
+ 1749
51
+ 1750
52
+ 1751
53
+ 1752
54
+ 1753
55
+ 1754
56
+ 1755
57
+ 1756
58
+ 1757
59
+ 1758
60
+ 1759
61
+ 1760
62
+ 1761
63
+ 1762
64
+ 1763
65
+ 1764
66
+ 1765
67
+ 1766
68
+ 1767
69
+ 1768
70
+ 1769
71
+ 1770
72
+ 1771
73
+ 1772
74
+ 1773
75
+ 1774
76
+ 1775
77
+ 1776
78
+ 1777
79
+ 1778
80
+ 1779
81
+ 1780
82
+ 1781
83
+ 1782
84
+ 1783
85
+ 1784
86
+ 1785
87
+ 1786
88
+ 1787
89
+ 1788
90
+ 1789
91
+ 1790
92
+ 1791
93
+ 1792
94
+ 1793
95
+ 1794
96
+ 1795
97
+ 1796
98
+ 1797
99
+ 1798
100
+ 1799
101
+ 1800
102
+ 1801
103
+ 1802
104
+ 1803
105
+ 1804
106
+ 1805
107
+ 1806
108
+ 1807
109
+ 1808
110
+ 1809
111
+ 1810
112
+ 1811
113
+ 1812
114
+ 1813
115
+ 1814
116
+ 1815
117
+ 1816
118
+ 1817
119
+ 1818
120
+ 1819
121
+ 1820
122
+ 1821
123
+ 1822
124
+ 1823
125
+ 1824
126
+ 1825
127
+ 1826
128
+ 1827
129
+ 1828
130
+ 1829
131
+ 1830
132
+ 1831
133
+ 1832
134
+ 1833
135
+ 1834
136
+ 1835
137
+ 1836
138
+ 1837
139
+ 1838
140
+ 1839
141
+ 1840
142
+ 1841
143
+ 1842
144
+ 1843
145
+ 1844
146
+ 1845
147
+ 1846
148
+ 1847
149
+ 1848
150
+ 1849
151
+ 1850
152
+ 1851
153
+ 1852
154
+ 1853
155
+ 1854
156
+ 1855
157
+ 1856
158
+ 1857
159
+ 1858
160
+ 1859
161
+ 1860
162
+ 1861
163
+ 1862
164
+ 1863
165
+ 1864
166
+ 1865
167
+ 1866
168
+ 1867
169
+ 1868
170
+ 1869
171
+ 1870
172
+ 1871
173
+ 1872
174
+ 1873
175
+ 1874
176
+ 1875
177
+ 1876
178
+ 1877
179
+ 1878
180
+ 1879
181
+ 1880
182
+ 1881
183
+ 1882
184
+ 1883
185
+ 1884
186
+ 1885
187
+ 1886
188
+ 1887
189
+ 1888
190
+ 1889
191
+ 1890
192
+ 1891
193
+ 1892
194
+ 1893
195
+ 1894
196
+ 1895
197
+ 1896
198
+ 1897
199
+ 1898
200
+ 1899
201
+ 1900
202
+ 1901
203
+ 1902
204
+ 1903
205
+ 1904
206
+ 1905
207
+ 1906
208
+ 1907
209
+ 1908
210
+ 1909
211
+ 1910
212
+ 1911
213
+ 1912
214
+ 1913
215
+ 1914
216
+ 1915
217
+ 1916
218
+ 1917
219
+ 1918
220
+ 1919
221
+ 1920
222
+ 1921
223
+ 1922
224
+ 1923
225
+ 1924
226
+ 1925
227
+ 1926
228
+ 1927
229
+ 1928
230
+ 1929
231
+ 1930
232
+ 1931
233
+ 1932
234
+ 1933
235
+ 1934
236
+ 1935
237
+ 1936
238
+ 1937
239
+ 1938
240
+ 1939
241
+ 1940
242
+ 1941
243
+ 1942
244
+ 1943
245
+ 1944
246
+ 1945
247
+ 1946
248
+ 1947
249
+ 1948
250
+ 1949
251
+ 1950
252
+ 1951
253
+ 1952
254
+ 1953
255
+ 1954
256
+ 1955
257
+ 1956
258
+ 1957
259
+ 1958
260
+ 1959
261
+ 1960
262
+ 1961
263
+ 1962
264
+ 1963
265
+ 1964
266
+ 1965
267
+ 1966
268
+ 1967
269
+ 1968
270
+ 1969
271
+ 1970
272
+ 1971
273
+ 1972
274
+ 1973
275
+ 1974
276
+ 1975
277
+ 1976
278
+ 1977
279
+ 1978
280
+ 1979
281
+ 1980
282
+ 1981
283
+ 1982
284
+ 1983
285
+ 1984
286
+ 1985
287
+ 1986
288
+ 1987
289
+ 1988
290
+ 1989
291
+ 1990
292
+ 1991
293
+ 1992
294
+ 1993
295
+ 1994
296
+ 1995
297
+ 1996
298
+ 1997
299
+ 1998
300
+ 1999
301
+ 2000
302
+ 2001
303
+ 2002
304
+ 2003
305
+ 2004
306
+ 2005
307
+ 2006
308
+ 2007
309
+ 2008
310
+ 2009
311
+ 2010
312
+ 2011
313
+ 2012
314
+ 2013
315
+ 2014
316
+ 2015
317
+ 2016
318
+ 2017
319
+ 2018
320
+ 2019
321
+ 2020
322
+ 2021
323
+ 2022
324
+ 2023
325
+ 2024
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ torch
2
+ torchvision
3
+ git+https://github.com/openai/CLIP.git
4
+ Pillow
5
+ scikit-learn
6
+ matplotlib
7
+ numpy