vidformer 1.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of vidformer might be problematic. Click here for more details.

@@ -0,0 +1,635 @@
1
+ """
2
+ vidformer.supervision is the [supervision](https://supervision.roboflow.com/) frontend for [vidformer](https://github.com/ixlab/vidformer).
3
+ """
4
+
5
+ from math import sqrt
6
+
7
+ import numpy as np
8
+ import supervision as _sv
9
+ from supervision import Color, ColorLookup, ColorPalette, Detections
10
+ from supervision.annotators.utils import resolve_color, resolve_text_background_xyxy
11
+ from supervision.config import CLASS_NAME_DATA_FIELD
12
+
13
+ # supervision moved this between two versions, so we need to handle both cases
14
+ try:
15
+ from supervision.detection.utils import spread_out_boxes
16
+ except ImportError:
17
+ from supervision.detection.utils.boxes import spread_out_boxes
18
+
19
+ from supervision.geometry.core import Position
20
+
21
+ import vidformer.cv2 as vf_cv2
22
+
23
+ try:
24
+ import cv2 as ocv_cv2
25
+ except ImportError:
26
+ ocv_cv2 = None
27
+
28
+ CV2_FONT = vf_cv2.FONT_HERSHEY_SIMPLEX
29
+
30
+
31
+ class BoxAnnotator:
32
+ def __init__(
33
+ self,
34
+ color=ColorPalette.DEFAULT,
35
+ thickness=2,
36
+ color_lookup=ColorLookup.CLASS,
37
+ ):
38
+ self.color = color
39
+ self.thickness = thickness
40
+ self.color_lookup = color_lookup
41
+
42
+ def annotate(
43
+ self,
44
+ scene: vf_cv2.Frame,
45
+ detections: Detections,
46
+ custom_color_lookup=None,
47
+ ):
48
+ for detection_idx in range(len(detections)):
49
+ x1, y1, x2, y2 = detections.xyxy[detection_idx].astype(int)
50
+ color = resolve_color(
51
+ color=self.color,
52
+ detections=detections,
53
+ detection_idx=detection_idx,
54
+ color_lookup=(
55
+ self.color_lookup
56
+ if custom_color_lookup is None
57
+ else custom_color_lookup
58
+ ),
59
+ )
60
+ vf_cv2.rectangle(
61
+ img=scene,
62
+ pt1=(x1, y1),
63
+ pt2=(x2, y2),
64
+ color=color.as_rgb(),
65
+ thickness=self.thickness,
66
+ )
67
+ return scene
68
+
69
+
70
+ class RoundBoxAnnotator:
71
+ def __init__(
72
+ self,
73
+ color=ColorPalette.DEFAULT,
74
+ thickness: int = 2,
75
+ color_lookup: ColorLookup = ColorLookup.CLASS,
76
+ roundness: float = 0.6,
77
+ ):
78
+ self.color = color
79
+ self.thickness = thickness
80
+ self.color_lookup = color_lookup
81
+ if not 0 < roundness <= 1.0:
82
+ raise ValueError("roundness attribute must be float between (0, 1.0]")
83
+ self.roundness = roundness
84
+
85
+ def annotate(
86
+ self,
87
+ scene: vf_cv2.Frame,
88
+ detections: _sv.Detections,
89
+ custom_color_lookup=None,
90
+ ):
91
+ for detection_idx in range(len(detections)):
92
+ x1, y1, x2, y2 = detections.xyxy[detection_idx].astype(int)
93
+ color = resolve_color(
94
+ color=self.color,
95
+ detections=detections,
96
+ detection_idx=detection_idx,
97
+ color_lookup=(
98
+ self.color_lookup
99
+ if custom_color_lookup is None
100
+ else custom_color_lookup
101
+ ),
102
+ )
103
+ radius = (
104
+ int((x2 - x1) // 2 * self.roundness)
105
+ if abs(x1 - x2) < abs(y1 - y2)
106
+ else int((y2 - y1) // 2 * self.roundness)
107
+ )
108
+ circle_coordinates = [
109
+ ((x1 + radius), (y1 + radius)),
110
+ ((x2 - radius), (y1 + radius)),
111
+ ((x2 - radius), (y2 - radius)),
112
+ ((x1 + radius), (y2 - radius)),
113
+ ]
114
+ line_coordinates = [
115
+ ((x1 + radius, y1), (x2 - radius, y1)),
116
+ ((x2, y1 + radius), (x2, y2 - radius)),
117
+ ((x1 + radius, y2), (x2 - radius, y2)),
118
+ ((x1, y1 + radius), (x1, y2 - radius)),
119
+ ]
120
+ start_angles = (180, 270, 0, 90)
121
+ end_angles = (270, 360, 90, 180)
122
+ for center_coordinates, line, start_angle, end_angle in zip(
123
+ circle_coordinates, line_coordinates, start_angles, end_angles
124
+ ):
125
+ vf_cv2.ellipse(
126
+ img=scene,
127
+ center=center_coordinates,
128
+ axes=(radius, radius),
129
+ angle=0,
130
+ startAngle=start_angle,
131
+ endAngle=end_angle,
132
+ color=color.as_rgb(),
133
+ thickness=self.thickness,
134
+ )
135
+ vf_cv2.line(
136
+ img=scene,
137
+ pt1=line[0],
138
+ pt2=line[1],
139
+ color=color.as_rgb(),
140
+ thickness=self.thickness,
141
+ )
142
+ return scene
143
+
144
+
145
+ class BoxCornerAnnotator:
146
+ def __init__(
147
+ self,
148
+ color=ColorPalette.DEFAULT,
149
+ thickness=4,
150
+ corner_length=15,
151
+ color_lookup=ColorLookup.CLASS,
152
+ ):
153
+ self.color = color
154
+ self.thickness: int = thickness
155
+ self.corner_length: int = corner_length
156
+ self.color_lookup: ColorLookup = color_lookup
157
+
158
+ def annotate(
159
+ self,
160
+ scene: vf_cv2.Frame,
161
+ detections: Detections,
162
+ custom_color_lookup=None,
163
+ ):
164
+ for detection_idx in range(len(detections)):
165
+ x1, y1, x2, y2 = detections.xyxy[detection_idx].astype(int)
166
+ color = resolve_color(
167
+ color=self.color,
168
+ detections=detections,
169
+ detection_idx=detection_idx,
170
+ color_lookup=(
171
+ self.color_lookup
172
+ if custom_color_lookup is None
173
+ else custom_color_lookup
174
+ ),
175
+ )
176
+ corners = [(x1, y1), (x2, y1), (x1, y2), (x2, y2)]
177
+ for x, y in corners:
178
+ x_end = x + self.corner_length if x == x1 else x - self.corner_length
179
+ vf_cv2.line(
180
+ scene, (x, y), (x_end, y), color.as_rgb(), thickness=self.thickness
181
+ )
182
+
183
+ y_end = y + self.corner_length if y == y1 else y - self.corner_length
184
+ vf_cv2.line(
185
+ scene, (x, y), (x, y_end), color.as_rgb(), thickness=self.thickness
186
+ )
187
+ return scene
188
+
189
+
190
+ class ColorAnnotator:
191
+ def __init__(
192
+ self,
193
+ color=ColorPalette.DEFAULT,
194
+ opacity: float = 0.5,
195
+ color_lookup: ColorLookup = ColorLookup.CLASS,
196
+ ):
197
+ self.color = color
198
+ self.color_lookup: ColorLookup = color_lookup
199
+ self.opacity = opacity
200
+
201
+ def annotate(
202
+ self,
203
+ scene: vf_cv2.Frame,
204
+ detections: Detections,
205
+ custom_color_lookup=None,
206
+ ):
207
+ scene_with_boxes = scene.copy()
208
+ for detection_idx in range(len(detections)):
209
+ x1, y1, x2, y2 = detections.xyxy[detection_idx].astype(int)
210
+ color = resolve_color(
211
+ color=self.color,
212
+ detections=detections,
213
+ detection_idx=detection_idx,
214
+ color_lookup=(
215
+ self.color_lookup
216
+ if custom_color_lookup is None
217
+ else custom_color_lookup
218
+ ),
219
+ )
220
+ vf_cv2.rectangle(
221
+ img=scene_with_boxes,
222
+ pt1=(x1, y1),
223
+ pt2=(x2, y2),
224
+ color=color.as_rgb(),
225
+ thickness=-1,
226
+ )
227
+
228
+ vf_cv2.addWeighted(
229
+ scene_with_boxes, self.opacity, scene, 1 - self.opacity, gamma=0, dst=scene
230
+ )
231
+ return scene
232
+
233
+
234
+ class CircleAnnotator:
235
+ def __init__(
236
+ self,
237
+ color=ColorPalette.DEFAULT,
238
+ thickness: int = 2,
239
+ color_lookup: ColorLookup = ColorLookup.CLASS,
240
+ ):
241
+ self.color = color
242
+ self.thickness: int = thickness
243
+ self.color_lookup: ColorLookup = color_lookup
244
+
245
+ def annotate(
246
+ self,
247
+ scene: vf_cv2.Frame,
248
+ detections: Detections,
249
+ custom_color_lookup=None,
250
+ ):
251
+ for detection_idx in range(len(detections)):
252
+ x1, y1, x2, y2 = detections.xyxy[detection_idx].astype(int)
253
+ center = ((x1 + x2) // 2, (y1 + y2) // 2)
254
+ distance = sqrt((x1 - center[0]) ** 2 + (y1 - center[1]) ** 2)
255
+ color = resolve_color(
256
+ color=self.color,
257
+ detections=detections,
258
+ detection_idx=detection_idx,
259
+ color_lookup=(
260
+ self.color_lookup
261
+ if custom_color_lookup is None
262
+ else custom_color_lookup
263
+ ),
264
+ )
265
+ vf_cv2.circle(
266
+ img=scene,
267
+ center=center,
268
+ radius=int(distance),
269
+ color=color.as_rgb(),
270
+ thickness=self.thickness,
271
+ )
272
+
273
+ return scene
274
+
275
+
276
+ class DotAnnotator:
277
+ def __init__(
278
+ self,
279
+ color=ColorPalette.DEFAULT,
280
+ radius: int = 4,
281
+ position: Position = Position.CENTER,
282
+ color_lookup: ColorLookup = ColorLookup.CLASS,
283
+ outline_thickness: int = 0,
284
+ outline_color=Color.BLACK,
285
+ ):
286
+ self.color = color
287
+ self.radius: int = radius
288
+ self.position: Position = position
289
+ self.color_lookup: ColorLookup = color_lookup
290
+ self.outline_thickness = outline_thickness
291
+ self.outline_color = outline_color
292
+
293
+ def annotate(
294
+ self,
295
+ scene: vf_cv2.Frame,
296
+ detections: Detections,
297
+ custom_color_lookup=None,
298
+ ):
299
+ xy = detections.get_anchors_coordinates(anchor=self.position)
300
+ for detection_idx in range(len(detections)):
301
+ color = resolve_color(
302
+ color=self.color,
303
+ detections=detections,
304
+ detection_idx=detection_idx,
305
+ color_lookup=(
306
+ self.color_lookup
307
+ if custom_color_lookup is None
308
+ else custom_color_lookup
309
+ ),
310
+ )
311
+ center = (int(xy[detection_idx, 0]), int(xy[detection_idx, 1]))
312
+
313
+ vf_cv2.circle(scene, center, self.radius, color.as_rgb(), -1)
314
+ if self.outline_thickness:
315
+ outline_color = resolve_color(
316
+ color=self.outline_color,
317
+ detections=detections,
318
+ detection_idx=detection_idx,
319
+ color_lookup=(
320
+ self.color_lookup
321
+ if custom_color_lookup is None
322
+ else custom_color_lookup
323
+ ),
324
+ )
325
+ vf_cv2.circle(
326
+ scene,
327
+ center,
328
+ self.radius,
329
+ outline_color.as_rgb(),
330
+ self.outline_thickness,
331
+ )
332
+ return scene
333
+
334
+
335
+ class LabelAnnotator:
336
+ def __init__(
337
+ self,
338
+ color=ColorPalette.DEFAULT,
339
+ text_color=Color.WHITE,
340
+ text_scale: float = 0.5,
341
+ text_thickness: int = 1,
342
+ text_padding: int = 10,
343
+ text_position: Position = Position.TOP_LEFT,
344
+ color_lookup: ColorLookup = ColorLookup.CLASS,
345
+ border_radius: int = 0,
346
+ smart_position: bool = False,
347
+ ):
348
+ self.border_radius: int = border_radius
349
+ self.color = color
350
+ self.text_color = text_color
351
+ self.text_scale: float = text_scale
352
+ self.text_thickness: int = text_thickness
353
+ self.text_padding: int = text_padding
354
+ self.text_anchor: Position = text_position
355
+ self.color_lookup: ColorLookup = color_lookup
356
+ self.smart_position = smart_position
357
+
358
+ def annotate(
359
+ self,
360
+ scene,
361
+ detections: Detections,
362
+ labels,
363
+ custom_color_lookup=None,
364
+ ):
365
+ self._validate_labels(labels, detections)
366
+
367
+ labels = self._get_labels_text(detections, labels)
368
+ label_properties = self._get_label_properties(detections, labels)
369
+
370
+ if self.smart_position:
371
+ xyxy = label_properties[:, :4]
372
+ xyxy = spread_out_boxes(xyxy)
373
+ label_properties[:, :4] = xyxy
374
+
375
+ self._draw_labels(
376
+ scene=scene,
377
+ labels=labels,
378
+ label_properties=label_properties,
379
+ detections=detections,
380
+ custom_color_lookup=custom_color_lookup,
381
+ )
382
+
383
+ return scene
384
+
385
+ def _validate_labels(self, labels, detections: Detections):
386
+ if labels is not None and len(labels) != len(detections):
387
+ raise ValueError(
388
+ f"The number of labels ({len(labels)}) does not match the "
389
+ f"number of detections ({len(detections)}). Each detection "
390
+ f"should have exactly 1 label."
391
+ )
392
+
393
+ def _get_label_properties(
394
+ self,
395
+ detections: Detections,
396
+ labels,
397
+ ):
398
+ label_properties = []
399
+ anchors_coordinates = detections.get_anchors_coordinates(
400
+ anchor=self.text_anchor
401
+ ).astype(int)
402
+
403
+ for label, center_coords in zip(labels, anchors_coordinates):
404
+ (text_w, text_h) = vf_cv2.getTextSize(
405
+ text=label,
406
+ fontFace=CV2_FONT,
407
+ fontScale=self.text_scale,
408
+ thickness=self.text_thickness,
409
+ )[0]
410
+
411
+ width_padded = text_w + 2 * self.text_padding
412
+ height_padded = text_h + 2 * self.text_padding
413
+
414
+ text_background_xyxy = resolve_text_background_xyxy(
415
+ center_coordinates=tuple(center_coords),
416
+ text_wh=(width_padded, height_padded),
417
+ position=self.text_anchor,
418
+ )
419
+
420
+ label_properties.append(
421
+ [
422
+ *text_background_xyxy,
423
+ text_h,
424
+ ]
425
+ )
426
+
427
+ return np.array(label_properties).reshape(-1, 5)
428
+
429
+ @staticmethod
430
+ def _get_labels_text(detections: Detections, custom_labels):
431
+ if custom_labels is not None:
432
+ return custom_labels
433
+
434
+ labels = []
435
+ for idx in range(len(detections)):
436
+ if CLASS_NAME_DATA_FIELD in detections.data:
437
+ labels.append(detections.data[CLASS_NAME_DATA_FIELD][idx])
438
+ elif detections.class_id is not None:
439
+ labels.append(str(detections.class_id[idx]))
440
+ else:
441
+ labels.append(str(idx))
442
+ return labels
443
+
444
+ def _draw_labels(
445
+ self,
446
+ scene,
447
+ labels,
448
+ label_properties,
449
+ detections,
450
+ custom_color_lookup,
451
+ ) -> None:
452
+ assert len(labels) == len(label_properties) == len(detections), (
453
+ f"Number of label properties ({len(label_properties)}), "
454
+ f"labels ({len(labels)}) and detections ({len(detections)}) "
455
+ "do not match."
456
+ )
457
+
458
+ color_lookup = (
459
+ custom_color_lookup
460
+ if custom_color_lookup is not None
461
+ else self.color_lookup
462
+ )
463
+
464
+ for idx, label_property in enumerate(label_properties):
465
+ background_color = resolve_color(
466
+ color=self.color,
467
+ detections=detections,
468
+ detection_idx=idx,
469
+ color_lookup=color_lookup,
470
+ )
471
+ text_color = resolve_color(
472
+ color=self.text_color,
473
+ detections=detections,
474
+ detection_idx=idx,
475
+ color_lookup=color_lookup,
476
+ )
477
+
478
+ box_xyxy = label_property[:4]
479
+ text_height_padded = label_property[4]
480
+ self.draw_rounded_rectangle(
481
+ scene=scene,
482
+ xyxy=box_xyxy,
483
+ color=background_color.as_rgb(),
484
+ border_radius=self.border_radius,
485
+ )
486
+
487
+ text_x = box_xyxy[0] + self.text_padding
488
+ text_y = box_xyxy[1] + self.text_padding + text_height_padded
489
+ vf_cv2.putText(
490
+ img=scene,
491
+ text=labels[idx],
492
+ org=(text_x, text_y),
493
+ fontFace=CV2_FONT,
494
+ fontScale=self.text_scale,
495
+ color=text_color.as_rgb(),
496
+ thickness=self.text_thickness,
497
+ lineType=vf_cv2.LINE_AA,
498
+ )
499
+
500
+ @staticmethod
501
+ def draw_rounded_rectangle(
502
+ scene: np.ndarray,
503
+ xyxy,
504
+ color,
505
+ border_radius: int,
506
+ ) -> np.ndarray:
507
+ x1, y1, x2, y2 = xyxy
508
+ width = x2 - x1
509
+ height = y2 - y1
510
+
511
+ border_radius = min(border_radius, min(width, height) // 2)
512
+
513
+ if border_radius <= 0:
514
+ vf_cv2.rectangle(
515
+ img=scene,
516
+ pt1=(x1, y1),
517
+ pt2=(x2, y2),
518
+ color=color,
519
+ thickness=-1,
520
+ )
521
+ else:
522
+ rectangle_coordinates = [
523
+ ((x1 + border_radius, y1), (x2 - border_radius, y2)),
524
+ ((x1, y1 + border_radius), (x2, y2 - border_radius)),
525
+ ]
526
+ circle_centers = [
527
+ (x1 + border_radius, y1 + border_radius),
528
+ (x2 - border_radius, y1 + border_radius),
529
+ (x1 + border_radius, y2 - border_radius),
530
+ (x2 - border_radius, y2 - border_radius),
531
+ ]
532
+
533
+ for coordinates in rectangle_coordinates:
534
+ vf_cv2.rectangle(
535
+ img=scene,
536
+ pt1=coordinates[0],
537
+ pt2=coordinates[1],
538
+ color=color,
539
+ thickness=-1,
540
+ )
541
+ for center in circle_centers:
542
+ vf_cv2.circle(
543
+ img=scene,
544
+ center=center,
545
+ radius=border_radius,
546
+ color=color,
547
+ thickness=-1,
548
+ )
549
+ return scene
550
+
551
+
552
+ class MaskAnnotator:
553
+ def __init__(
554
+ self,
555
+ color=ColorPalette.DEFAULT,
556
+ opacity: float = 0.5,
557
+ color_lookup: ColorLookup = ColorLookup.CLASS,
558
+ ):
559
+ self.color = color
560
+ self.opacity = opacity
561
+ self.color_lookup: ColorLookup = color_lookup
562
+
563
+ def annotate(
564
+ self,
565
+ scene,
566
+ detections: Detections,
567
+ custom_color_lookup=None,
568
+ ):
569
+ if detections.mask is None:
570
+ return scene
571
+
572
+ colored_mask = scene.copy()
573
+
574
+ for detection_idx in np.flip(np.argsort(detections.box_area)):
575
+ color = resolve_color(
576
+ color=self.color,
577
+ detections=detections,
578
+ detection_idx=detection_idx,
579
+ color_lookup=(
580
+ self.color_lookup
581
+ if custom_color_lookup is None
582
+ else custom_color_lookup
583
+ ),
584
+ )
585
+ mask = detections.mask[detection_idx]
586
+ colored_mask[mask] = color.as_bgr()
587
+
588
+ vf_cv2.addWeighted(
589
+ colored_mask, self.opacity, scene, 1 - self.opacity, 0, dst=scene
590
+ )
591
+ return scene
592
+
593
+
594
+ class MaskStreamWriter:
595
+ def __init__(self, path: str, shape: tuple):
596
+ # Shape should be (width, height)
597
+ assert ocv_cv2 is not None, "OpenCV cv2 is required for ExternDetectionsBuilder"
598
+ assert type(shape) is tuple, "shape must be a tuple"
599
+ assert len(shape) == 2, "shape must be a tuple of length 2"
600
+ self._shape = (shape[1], shape[0])
601
+ self._writer = ocv_cv2.VideoWriter(
602
+ path, ocv_cv2.VideoWriter_fourcc(*"FFV1"), 1, shape, isColor=False
603
+ )
604
+ assert self._writer.isOpened(), f"Failed to open video writer at {path}"
605
+ self._i = 0
606
+
607
+ def write_detections(self, detections: Detections):
608
+ if len(detections) == 0:
609
+ return self._i
610
+
611
+ mask = detections.mask
612
+ assert (
613
+ mask.shape[1:] == self._shape
614
+ ), f"mask shape ({mask.shape[:1]}) must match the shape of the video ({self._shape})"
615
+ for i in range(mask.shape[0]):
616
+ frame_uint8 = detections.mask[i].astype(np.uint8)
617
+ self._writer.write(frame_uint8)
618
+ self._i += 1
619
+ return self._i
620
+
621
+ def release(self):
622
+ self._writer.release()
623
+
624
+
625
+ def populate_mask(
626
+ detections: Detections, mask_stream: vf_cv2.VideoCapture, frame_idx: int
627
+ ):
628
+ assert type(detections) is Detections
629
+ assert detections.mask is None
630
+ detections.mask = []
631
+ assert len(detections) + frame_idx <= len(mask_stream)
632
+ for i in range(len(detections)):
633
+ mask = mask_stream[frame_idx + i]
634
+ assert mask.shape[2] == 1, "mask must be a single channel image"
635
+ detections.mask.append(mask)
@@ -0,0 +1,37 @@
1
+ Metadata-Version: 2.4
2
+ Name: vidformer
3
+ Version: 1.2.0
4
+ Summary: vidformer-py is a Python 🐍 interface for [vidformer](https://github.com/ixlab/vidformer).
5
+ Author-email: Dominik Winecki <dominikwinecki@gmail.com>
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Dist: requests
11
+ Requires-Dist: numpy
12
+ Project-URL: Documentation, https://ixlab.github.io/vidformer/vidformer-py/
13
+ Project-URL: Homepage, https://ixlab.github.io/vidformer/
14
+ Project-URL: Issues, https://github.com/ixlab/vidformer/issues
15
+
16
+ # vidformer-py
17
+
18
+ [![PyPI version](https://img.shields.io/pypi/v/vidformer.svg)](https://pypi.org/project/vidformer/)
19
+ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/ixlab/vidformer/blob/main/LICENSE)
20
+
21
+ vidformer-py is a Python 🐍 frontend for [vidformer](https://github.com/ixlab/vidformer).
22
+ It has an API compatability layer with OpenCV cv2, as well as some [supervision](https://github.com/roboflow/supervision) annotators.
23
+ Our [getting started guide](https://ixlab.github.io/vidformer/getting-started.html) explains how to use it.
24
+
25
+ **Quick links:**
26
+ * [📦 PyPI](https://pypi.org/project/vidformer/)
27
+ * [📘 Documentation - vidformer-py](https://ixlab.github.io/vidformer/vidformer-py/pdoc/)
28
+ * [📘 Documentation - vidformer.cv2](https://ixlab.github.io/vidformer/vidformer-py/pdoc/vidformer/cv2.html)
29
+ * [📘 Documentation - vidformer.supervision](https://ixlab.github.io/vidformer/vidformer-py/pdoc/vidformer/supervision.html)
30
+ * [🧑‍💻 Source Code](https://github.com/ixlab/vidformer/tree/main/vidformer-py/)
31
+
32
+ **Publish:**
33
+ ```bash
34
+ export FLIT_USERNAME='__token__' FLIT_PASSWORD='<token>'
35
+ flit publish
36
+ ```
37
+
@@ -0,0 +1,6 @@
1
+ vidformer/__init__.py,sha256=0l6e8yMCWfQmk5P80Z2JhKEUGIXhlza4SeS9p9jzSbc,29972
2
+ vidformer/cv2/__init__.py,sha256=QYB-rpkBURtE-q9MhqF1zgsq1qfbPLb0DDjtDpRxVJY,27978
3
+ vidformer/supervision/__init__.py,sha256=FzuFmMUtnnxlXoeSzLDYTWatQ5E-RsMF5Atwbv_RfHI,20523
4
+ vidformer-1.2.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
5
+ vidformer-1.2.0.dist-info/METADATA,sha256=oXwwyrPIMpMOzFUaiCkky-a76c0kpiWzUiX4YINN0WY,1776
6
+ vidformer-1.2.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: flit 3.12.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any