denkproto 1.0.93__py3-none-any.whl → 1.0.95__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 denkproto might be problematic. Click here for more details.
- denkproto/__about__.py +1 -1
- denkproto/json/annotation_comparer_request.py +47 -38
- denkproto/json/ocr_markup.py +45 -26
- denkproto/json/prediction_request.py +295 -35
- denkproto/json/segmentation_markup.py +7 -7
- {denkproto-1.0.93.dist-info → denkproto-1.0.95.dist-info}/METADATA +1 -1
- {denkproto-1.0.93.dist-info → denkproto-1.0.95.dist-info}/RECORD +8 -8
- {denkproto-1.0.93.dist-info → denkproto-1.0.95.dist-info}/WHEEL +0 -0
denkproto/__about__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.0.
|
|
1
|
+
__version__ = "1.0.95"
|
|
@@ -281,30 +281,46 @@ class ObjectDetectionMarkup:
|
|
|
281
281
|
|
|
282
282
|
|
|
283
283
|
class BoundingBox:
|
|
284
|
+
"""A bounding box with optional rotation information"""
|
|
285
|
+
|
|
286
|
+
angle: Optional[float]
|
|
287
|
+
"""Optional rotation angle"""
|
|
288
|
+
|
|
284
289
|
bottom_right_x: float
|
|
285
290
|
bottom_right_y: float
|
|
291
|
+
full_orientation: Optional[bool]
|
|
292
|
+
"""Optional full orientation flag"""
|
|
293
|
+
|
|
286
294
|
top_left_x: float
|
|
287
295
|
top_left_y: float
|
|
288
296
|
|
|
289
|
-
def __init__(self, bottom_right_x: float, bottom_right_y: float, top_left_x: float, top_left_y: float) -> None:
|
|
297
|
+
def __init__(self, angle: Optional[float], bottom_right_x: float, bottom_right_y: float, full_orientation: Optional[bool], top_left_x: float, top_left_y: float) -> None:
|
|
298
|
+
self.angle = angle
|
|
290
299
|
self.bottom_right_x = bottom_right_x
|
|
291
300
|
self.bottom_right_y = bottom_right_y
|
|
301
|
+
self.full_orientation = full_orientation
|
|
292
302
|
self.top_left_x = top_left_x
|
|
293
303
|
self.top_left_y = top_left_y
|
|
294
304
|
|
|
295
305
|
@staticmethod
|
|
296
306
|
def from_dict(obj: Any) -> 'BoundingBox':
|
|
297
307
|
assert isinstance(obj, dict)
|
|
308
|
+
angle = from_union([from_float, from_none], obj.get("angle"))
|
|
298
309
|
bottom_right_x = from_float(obj.get("bottom_right_x"))
|
|
299
310
|
bottom_right_y = from_float(obj.get("bottom_right_y"))
|
|
311
|
+
full_orientation = from_union([from_bool, from_none], obj.get("full_orientation"))
|
|
300
312
|
top_left_x = from_float(obj.get("top_left_x"))
|
|
301
313
|
top_left_y = from_float(obj.get("top_left_y"))
|
|
302
|
-
return BoundingBox(bottom_right_x, bottom_right_y, top_left_x, top_left_y)
|
|
314
|
+
return BoundingBox(angle, bottom_right_x, bottom_right_y, full_orientation, top_left_x, top_left_y)
|
|
303
315
|
|
|
304
316
|
def to_dict(self) -> dict:
|
|
305
317
|
result: dict = {}
|
|
318
|
+
if self.angle is not None:
|
|
319
|
+
result["angle"] = from_union([to_float, from_none], self.angle)
|
|
306
320
|
result["bottom_right_x"] = to_float(self.bottom_right_x)
|
|
307
321
|
result["bottom_right_y"] = to_float(self.bottom_right_y)
|
|
322
|
+
if self.full_orientation is not None:
|
|
323
|
+
result["full_orientation"] = from_union([from_bool, from_none], self.full_orientation)
|
|
308
324
|
result["top_left_x"] = to_float(self.top_left_x)
|
|
309
325
|
result["top_left_y"] = to_float(self.top_left_y)
|
|
310
326
|
return result
|
|
@@ -332,20 +348,26 @@ class RingPoint:
|
|
|
332
348
|
return result
|
|
333
349
|
|
|
334
350
|
|
|
335
|
-
class
|
|
351
|
+
class GeometrySchema:
|
|
352
|
+
"""A single closed loop (ring) of a polygon, defining either an outer boundary or a hole."""
|
|
353
|
+
|
|
336
354
|
hierarchy: int
|
|
355
|
+
"""Nesting level: 0=outer, 1=hole in level 0, 2=poly in level 1 hole, etc. Even levels are
|
|
356
|
+
filled areas, odd levels are holes.
|
|
357
|
+
"""
|
|
337
358
|
points: List[RingPoint]
|
|
359
|
+
"""Vertices of the ring."""
|
|
338
360
|
|
|
339
361
|
def __init__(self, hierarchy: int, points: List[RingPoint]) -> None:
|
|
340
362
|
self.hierarchy = hierarchy
|
|
341
363
|
self.points = points
|
|
342
364
|
|
|
343
365
|
@staticmethod
|
|
344
|
-
def from_dict(obj: Any) -> '
|
|
366
|
+
def from_dict(obj: Any) -> 'GeometrySchema':
|
|
345
367
|
assert isinstance(obj, dict)
|
|
346
368
|
hierarchy = from_int(obj.get("hierarchy"))
|
|
347
369
|
points = from_list(RingPoint.from_dict, obj.get("points"))
|
|
348
|
-
return
|
|
370
|
+
return GeometrySchema(hierarchy, points)
|
|
349
371
|
|
|
350
372
|
def to_dict(self) -> dict:
|
|
351
373
|
result: dict = {}
|
|
@@ -355,20 +377,25 @@ class AnnotationComparerRequestSchema:
|
|
|
355
377
|
|
|
356
378
|
|
|
357
379
|
class Polygon:
|
|
358
|
-
rings
|
|
380
|
+
"""A polygon defined by one or more rings, allowing for holes and nested structures."""
|
|
381
|
+
|
|
382
|
+
rings: List[GeometrySchema]
|
|
383
|
+
"""Array of polygon rings. The hierarchy field within each ring determines nesting and
|
|
384
|
+
fill/hole status.
|
|
385
|
+
"""
|
|
359
386
|
|
|
360
|
-
def __init__(self, rings: List[
|
|
387
|
+
def __init__(self, rings: List[GeometrySchema]) -> None:
|
|
361
388
|
self.rings = rings
|
|
362
389
|
|
|
363
390
|
@staticmethod
|
|
364
391
|
def from_dict(obj: Any) -> 'Polygon':
|
|
365
392
|
assert isinstance(obj, dict)
|
|
366
|
-
rings = from_list(
|
|
393
|
+
rings = from_list(GeometrySchema.from_dict, obj.get("rings"))
|
|
367
394
|
return Polygon(rings)
|
|
368
395
|
|
|
369
396
|
def to_dict(self) -> dict:
|
|
370
397
|
result: dict = {}
|
|
371
|
-
result["rings"] = from_list(lambda x: to_class(
|
|
398
|
+
result["rings"] = from_list(lambda x: to_class(GeometrySchema, x), self.rings)
|
|
372
399
|
return result
|
|
373
400
|
|
|
374
401
|
|
|
@@ -408,7 +435,7 @@ class OcrMarkupAnnotation:
|
|
|
408
435
|
return result
|
|
409
436
|
|
|
410
437
|
|
|
411
|
-
class
|
|
438
|
+
class OCRMarkup:
|
|
412
439
|
annotations: List[OcrMarkupAnnotation]
|
|
413
440
|
average_object_widths: List[float]
|
|
414
441
|
height: int
|
|
@@ -421,13 +448,13 @@ class OcrMarkup:
|
|
|
421
448
|
self.width = width
|
|
422
449
|
|
|
423
450
|
@staticmethod
|
|
424
|
-
def from_dict(obj: Any) -> '
|
|
451
|
+
def from_dict(obj: Any) -> 'OCRMarkup':
|
|
425
452
|
assert isinstance(obj, dict)
|
|
426
453
|
annotations = from_list(OcrMarkupAnnotation.from_dict, obj.get("annotations"))
|
|
427
454
|
average_object_widths = from_list(from_float, obj.get("average_object_widths"))
|
|
428
455
|
height = from_int(obj.get("height"))
|
|
429
456
|
width = from_int(obj.get("width"))
|
|
430
|
-
return
|
|
457
|
+
return OCRMarkup(annotations, average_object_widths, height, width)
|
|
431
458
|
|
|
432
459
|
def to_dict(self) -> dict:
|
|
433
460
|
result: dict = {}
|
|
@@ -634,24 +661,6 @@ class PixelAnnotation:
|
|
|
634
661
|
return result
|
|
635
662
|
|
|
636
663
|
|
|
637
|
-
class PolygonAnnotation:
|
|
638
|
-
rings: List[AnnotationComparerRequestSchema]
|
|
639
|
-
|
|
640
|
-
def __init__(self, rings: List[AnnotationComparerRequestSchema]) -> None:
|
|
641
|
-
self.rings = rings
|
|
642
|
-
|
|
643
|
-
@staticmethod
|
|
644
|
-
def from_dict(obj: Any) -> 'PolygonAnnotation':
|
|
645
|
-
assert isinstance(obj, dict)
|
|
646
|
-
rings = from_list(AnnotationComparerRequestSchema.from_dict, obj.get("rings"))
|
|
647
|
-
return PolygonAnnotation(rings)
|
|
648
|
-
|
|
649
|
-
def to_dict(self) -> dict:
|
|
650
|
-
result: dict = {}
|
|
651
|
-
result["rings"] = from_list(lambda x: to_class(AnnotationComparerRequestSchema, x), self.rings)
|
|
652
|
-
return result
|
|
653
|
-
|
|
654
|
-
|
|
655
664
|
class RectangleAnnotation:
|
|
656
665
|
bottom_right_x: float
|
|
657
666
|
bottom_right_y: float
|
|
@@ -755,11 +764,11 @@ class SegmentationMarkupAnnotation:
|
|
|
755
764
|
magicwand_annotation: Optional[MagicwandAnnotation]
|
|
756
765
|
pen_annotation: Optional[PenAnnotation]
|
|
757
766
|
pixel_annotation: Optional[PixelAnnotation]
|
|
758
|
-
polygon_annotation: Optional[
|
|
767
|
+
polygon_annotation: Optional[Polygon]
|
|
759
768
|
rectangle_annotation: Optional[RectangleAnnotation]
|
|
760
769
|
sausage_annotation: Optional[SausageAnnotation]
|
|
761
770
|
|
|
762
|
-
def __init__(self, annotation_type: AnnotationType, average_width: float, circle_annotation: Optional[CircleAnnotation], id: UUID, label_id: UUID, magicwand_annotation: Optional[MagicwandAnnotation], pen_annotation: Optional[PenAnnotation], pixel_annotation: Optional[PixelAnnotation], polygon_annotation: Optional[
|
|
771
|
+
def __init__(self, annotation_type: AnnotationType, average_width: float, circle_annotation: Optional[CircleAnnotation], id: UUID, label_id: UUID, magicwand_annotation: Optional[MagicwandAnnotation], pen_annotation: Optional[PenAnnotation], pixel_annotation: Optional[PixelAnnotation], polygon_annotation: Optional[Polygon], rectangle_annotation: Optional[RectangleAnnotation], sausage_annotation: Optional[SausageAnnotation]) -> None:
|
|
763
772
|
self.annotation_type = annotation_type
|
|
764
773
|
self.average_width = average_width
|
|
765
774
|
self.circle_annotation = circle_annotation
|
|
@@ -783,7 +792,7 @@ class SegmentationMarkupAnnotation:
|
|
|
783
792
|
magicwand_annotation = from_union([MagicwandAnnotation.from_dict, from_none], obj.get("magicwand_annotation"))
|
|
784
793
|
pen_annotation = from_union([PenAnnotation.from_dict, from_none], obj.get("pen_annotation"))
|
|
785
794
|
pixel_annotation = from_union([PixelAnnotation.from_dict, from_none], obj.get("pixel_annotation"))
|
|
786
|
-
polygon_annotation = from_union([
|
|
795
|
+
polygon_annotation = from_union([Polygon.from_dict, from_none], obj.get("polygon_annotation"))
|
|
787
796
|
rectangle_annotation = from_union([RectangleAnnotation.from_dict, from_none], obj.get("rectangle_annotation"))
|
|
788
797
|
sausage_annotation = from_union([SausageAnnotation.from_dict, from_none], obj.get("sausage_annotation"))
|
|
789
798
|
return SegmentationMarkupAnnotation(annotation_type, average_width, circle_annotation, id, label_id, magicwand_annotation, pen_annotation, pixel_annotation, polygon_annotation, rectangle_annotation, sausage_annotation)
|
|
@@ -803,7 +812,7 @@ class SegmentationMarkupAnnotation:
|
|
|
803
812
|
if self.pixel_annotation is not None:
|
|
804
813
|
result["pixel_annotation"] = from_union([lambda x: to_class(PixelAnnotation, x), from_none], self.pixel_annotation)
|
|
805
814
|
if self.polygon_annotation is not None:
|
|
806
|
-
result["polygon_annotation"] = from_union([lambda x: to_class(
|
|
815
|
+
result["polygon_annotation"] = from_union([lambda x: to_class(Polygon, x), from_none], self.polygon_annotation)
|
|
807
816
|
if self.rectangle_annotation is not None:
|
|
808
817
|
result["rectangle_annotation"] = from_union([lambda x: to_class(RectangleAnnotation, x), from_none], self.rectangle_annotation)
|
|
809
818
|
if self.sausage_annotation is not None:
|
|
@@ -919,10 +928,10 @@ class SegmentationMarkup:
|
|
|
919
928
|
class Source:
|
|
920
929
|
classification_markup: Optional[ClassificationMarkup]
|
|
921
930
|
object_detection_markup: Optional[ObjectDetectionMarkup]
|
|
922
|
-
ocr_markup: Optional[
|
|
931
|
+
ocr_markup: Optional[OCRMarkup]
|
|
923
932
|
segmentation_markup: Optional[SegmentationMarkup]
|
|
924
933
|
|
|
925
|
-
def __init__(self, classification_markup: Optional[ClassificationMarkup], object_detection_markup: Optional[ObjectDetectionMarkup], ocr_markup: Optional[
|
|
934
|
+
def __init__(self, classification_markup: Optional[ClassificationMarkup], object_detection_markup: Optional[ObjectDetectionMarkup], ocr_markup: Optional[OCRMarkup], segmentation_markup: Optional[SegmentationMarkup]) -> None:
|
|
926
935
|
self.classification_markup = classification_markup
|
|
927
936
|
self.object_detection_markup = object_detection_markup
|
|
928
937
|
self.ocr_markup = ocr_markup
|
|
@@ -933,7 +942,7 @@ class Source:
|
|
|
933
942
|
assert isinstance(obj, dict)
|
|
934
943
|
classification_markup = from_union([ClassificationMarkup.from_dict, from_none], obj.get("classification_markup"))
|
|
935
944
|
object_detection_markup = from_union([ObjectDetectionMarkup.from_dict, from_none], obj.get("object_detection_markup"))
|
|
936
|
-
ocr_markup = from_union([
|
|
945
|
+
ocr_markup = from_union([OCRMarkup.from_dict, from_none], obj.get("ocr_markup"))
|
|
937
946
|
segmentation_markup = from_union([SegmentationMarkup.from_dict, from_none], obj.get("segmentation_markup"))
|
|
938
947
|
return Source(classification_markup, object_detection_markup, ocr_markup, segmentation_markup)
|
|
939
948
|
|
|
@@ -944,7 +953,7 @@ class Source:
|
|
|
944
953
|
if self.object_detection_markup is not None:
|
|
945
954
|
result["object_detection_markup"] = from_union([lambda x: to_class(ObjectDetectionMarkup, x), from_none], self.object_detection_markup)
|
|
946
955
|
if self.ocr_markup is not None:
|
|
947
|
-
result["ocr_markup"] = from_union([lambda x: to_class(
|
|
956
|
+
result["ocr_markup"] = from_union([lambda x: to_class(OCRMarkup, x), from_none], self.ocr_markup)
|
|
948
957
|
if self.segmentation_markup is not None:
|
|
949
958
|
result["segmentation_markup"] = from_union([lambda x: to_class(SegmentationMarkup, x), from_none], self.segmentation_markup)
|
|
950
959
|
return result
|
denkproto/json/ocr_markup.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any, List,
|
|
1
|
+
from typing import Optional, Any, List, TypeVar, Callable, Type, cast
|
|
2
2
|
from uuid import UUID
|
|
3
3
|
|
|
4
4
|
|
|
@@ -10,6 +10,25 @@ def from_float(x: Any) -> float:
|
|
|
10
10
|
return float(x)
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
def from_none(x: Any) -> Any:
|
|
14
|
+
assert x is None
|
|
15
|
+
return x
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def from_union(fs, x):
|
|
19
|
+
for f in fs:
|
|
20
|
+
try:
|
|
21
|
+
return f(x)
|
|
22
|
+
except:
|
|
23
|
+
pass
|
|
24
|
+
assert False
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def from_bool(x: Any) -> bool:
|
|
28
|
+
assert isinstance(x, bool)
|
|
29
|
+
return x
|
|
30
|
+
|
|
31
|
+
|
|
13
32
|
def to_float(x: Any) -> float:
|
|
14
33
|
assert isinstance(x, (int, float))
|
|
15
34
|
return x
|
|
@@ -30,50 +49,52 @@ def to_class(c: Type[T], x: Any) -> dict:
|
|
|
30
49
|
return cast(Any, x).to_dict()
|
|
31
50
|
|
|
32
51
|
|
|
33
|
-
def from_none(x: Any) -> Any:
|
|
34
|
-
assert x is None
|
|
35
|
-
return x
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def from_union(fs, x):
|
|
39
|
-
for f in fs:
|
|
40
|
-
try:
|
|
41
|
-
return f(x)
|
|
42
|
-
except:
|
|
43
|
-
pass
|
|
44
|
-
assert False
|
|
45
|
-
|
|
46
|
-
|
|
47
52
|
def from_str(x: Any) -> str:
|
|
48
53
|
assert isinstance(x, str)
|
|
49
54
|
return x
|
|
50
55
|
|
|
51
56
|
|
|
52
57
|
class BoundingBox:
|
|
58
|
+
"""A bounding box with optional rotation information"""
|
|
59
|
+
|
|
60
|
+
angle: Optional[float]
|
|
61
|
+
"""Optional rotation angle"""
|
|
62
|
+
|
|
53
63
|
bottom_right_x: float
|
|
54
64
|
bottom_right_y: float
|
|
65
|
+
full_orientation: Optional[bool]
|
|
66
|
+
"""Optional full orientation flag"""
|
|
67
|
+
|
|
55
68
|
top_left_x: float
|
|
56
69
|
top_left_y: float
|
|
57
70
|
|
|
58
|
-
def __init__(self, bottom_right_x: float, bottom_right_y: float, top_left_x: float, top_left_y: float) -> None:
|
|
71
|
+
def __init__(self, angle: Optional[float], bottom_right_x: float, bottom_right_y: float, full_orientation: Optional[bool], top_left_x: float, top_left_y: float) -> None:
|
|
72
|
+
self.angle = angle
|
|
59
73
|
self.bottom_right_x = bottom_right_x
|
|
60
74
|
self.bottom_right_y = bottom_right_y
|
|
75
|
+
self.full_orientation = full_orientation
|
|
61
76
|
self.top_left_x = top_left_x
|
|
62
77
|
self.top_left_y = top_left_y
|
|
63
78
|
|
|
64
79
|
@staticmethod
|
|
65
80
|
def from_dict(obj: Any) -> 'BoundingBox':
|
|
66
81
|
assert isinstance(obj, dict)
|
|
82
|
+
angle = from_union([from_float, from_none], obj.get("angle"))
|
|
67
83
|
bottom_right_x = from_float(obj.get("bottom_right_x"))
|
|
68
84
|
bottom_right_y = from_float(obj.get("bottom_right_y"))
|
|
85
|
+
full_orientation = from_union([from_bool, from_none], obj.get("full_orientation"))
|
|
69
86
|
top_left_x = from_float(obj.get("top_left_x"))
|
|
70
87
|
top_left_y = from_float(obj.get("top_left_y"))
|
|
71
|
-
return BoundingBox(bottom_right_x, bottom_right_y, top_left_x, top_left_y)
|
|
88
|
+
return BoundingBox(angle, bottom_right_x, bottom_right_y, full_orientation, top_left_x, top_left_y)
|
|
72
89
|
|
|
73
90
|
def to_dict(self) -> dict:
|
|
74
91
|
result: dict = {}
|
|
92
|
+
if self.angle is not None:
|
|
93
|
+
result["angle"] = from_union([to_float, from_none], self.angle)
|
|
75
94
|
result["bottom_right_x"] = to_float(self.bottom_right_x)
|
|
76
95
|
result["bottom_right_y"] = to_float(self.bottom_right_y)
|
|
96
|
+
if self.full_orientation is not None:
|
|
97
|
+
result["full_orientation"] = from_union([from_bool, from_none], self.full_orientation)
|
|
77
98
|
result["top_left_x"] = to_float(self.top_left_x)
|
|
78
99
|
result["top_left_y"] = to_float(self.top_left_y)
|
|
79
100
|
return result
|
|
@@ -101,7 +122,7 @@ class Point:
|
|
|
101
122
|
return result
|
|
102
123
|
|
|
103
124
|
|
|
104
|
-
class
|
|
125
|
+
class GeometrySchema:
|
|
105
126
|
"""A single closed loop (ring) of a polygon, defining either an outer boundary or a hole."""
|
|
106
127
|
|
|
107
128
|
hierarchy: int
|
|
@@ -116,11 +137,11 @@ class OcrMarkupSchema:
|
|
|
116
137
|
self.points = points
|
|
117
138
|
|
|
118
139
|
@staticmethod
|
|
119
|
-
def from_dict(obj: Any) -> '
|
|
140
|
+
def from_dict(obj: Any) -> 'GeometrySchema':
|
|
120
141
|
assert isinstance(obj, dict)
|
|
121
142
|
hierarchy = from_int(obj.get("hierarchy"))
|
|
122
143
|
points = from_list(Point.from_dict, obj.get("points"))
|
|
123
|
-
return
|
|
144
|
+
return GeometrySchema(hierarchy, points)
|
|
124
145
|
|
|
125
146
|
def to_dict(self) -> dict:
|
|
126
147
|
result: dict = {}
|
|
@@ -132,23 +153,23 @@ class OcrMarkupSchema:
|
|
|
132
153
|
class Polygon:
|
|
133
154
|
"""A polygon defined by one or more rings, allowing for holes and nested structures."""
|
|
134
155
|
|
|
135
|
-
rings: List[
|
|
156
|
+
rings: List[GeometrySchema]
|
|
136
157
|
"""Array of polygon rings. The hierarchy field within each ring determines nesting and
|
|
137
158
|
fill/hole status.
|
|
138
159
|
"""
|
|
139
160
|
|
|
140
|
-
def __init__(self, rings: List[
|
|
161
|
+
def __init__(self, rings: List[GeometrySchema]) -> None:
|
|
141
162
|
self.rings = rings
|
|
142
163
|
|
|
143
164
|
@staticmethod
|
|
144
165
|
def from_dict(obj: Any) -> 'Polygon':
|
|
145
166
|
assert isinstance(obj, dict)
|
|
146
|
-
rings = from_list(
|
|
167
|
+
rings = from_list(GeometrySchema.from_dict, obj.get("rings"))
|
|
147
168
|
return Polygon(rings)
|
|
148
169
|
|
|
149
170
|
def to_dict(self) -> dict:
|
|
150
171
|
result: dict = {}
|
|
151
|
-
result["rings"] = from_list(lambda x: to_class(
|
|
172
|
+
result["rings"] = from_list(lambda x: to_class(GeometrySchema, x), self.rings)
|
|
152
173
|
return result
|
|
153
174
|
|
|
154
175
|
|
|
@@ -157,8 +178,6 @@ class Annotation:
|
|
|
157
178
|
id: UUID
|
|
158
179
|
label_id: UUID
|
|
159
180
|
polygon: Optional[Polygon]
|
|
160
|
-
"""A polygon defined by one or more rings, allowing for holes and nested structures."""
|
|
161
|
-
|
|
162
181
|
text: str
|
|
163
182
|
|
|
164
183
|
def __init__(self, bounding_box: Optional[BoundingBox], id: UUID, label_id: UUID, polygon: Optional[Polygon], text: str) -> None:
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
from uuid import UUID
|
|
2
|
-
from typing import Any, Dict, List, TypeVar, Callable, Type, cast
|
|
2
|
+
from typing import Any, Dict, List, Optional, TypeVar, Callable, Type, cast
|
|
3
|
+
from enum import Enum
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
T = TypeVar("T")
|
|
7
|
+
EnumT = TypeVar("EnumT", bound=Enum)
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
def from_int(x: Any) -> int:
|
|
@@ -20,6 +22,11 @@ def from_bool(x: Any) -> bool:
|
|
|
20
22
|
return x
|
|
21
23
|
|
|
22
24
|
|
|
25
|
+
def from_str(x: Any) -> str:
|
|
26
|
+
assert isinstance(x, str)
|
|
27
|
+
return x
|
|
28
|
+
|
|
29
|
+
|
|
23
30
|
def to_class(c: Type[T], x: Any) -> dict:
|
|
24
31
|
assert isinstance(x, c)
|
|
25
32
|
return cast(Any, x).to_dict()
|
|
@@ -30,11 +37,35 @@ def from_list(f: Callable[[Any], T], x: Any) -> List[T]:
|
|
|
30
37
|
return [f(y) for y in x]
|
|
31
38
|
|
|
32
39
|
|
|
33
|
-
def
|
|
34
|
-
assert
|
|
40
|
+
def from_none(x: Any) -> Any:
|
|
41
|
+
assert x is None
|
|
35
42
|
return x
|
|
36
43
|
|
|
37
44
|
|
|
45
|
+
def from_union(fs, x):
|
|
46
|
+
for f in fs:
|
|
47
|
+
try:
|
|
48
|
+
return f(x)
|
|
49
|
+
except:
|
|
50
|
+
pass
|
|
51
|
+
assert False
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def from_float(x: Any) -> float:
|
|
55
|
+
assert isinstance(x, (float, int)) and not isinstance(x, bool)
|
|
56
|
+
return float(x)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def to_float(x: Any) -> float:
|
|
60
|
+
assert isinstance(x, (int, float))
|
|
61
|
+
return x
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def to_enum(c: Type[EnumT], x: Any) -> EnumT:
|
|
65
|
+
assert isinstance(x, c)
|
|
66
|
+
return x.value
|
|
67
|
+
|
|
68
|
+
|
|
38
69
|
class Image:
|
|
39
70
|
blob_id: UUID
|
|
40
71
|
height: int
|
|
@@ -65,7 +96,7 @@ class Image:
|
|
|
65
96
|
return result
|
|
66
97
|
|
|
67
98
|
|
|
68
|
-
class
|
|
99
|
+
class ClassLabelElement:
|
|
69
100
|
id: UUID
|
|
70
101
|
idx: int
|
|
71
102
|
|
|
@@ -74,11 +105,11 @@ class ClassLabel:
|
|
|
74
105
|
self.idx = idx
|
|
75
106
|
|
|
76
107
|
@staticmethod
|
|
77
|
-
def from_dict(obj: Any) -> '
|
|
108
|
+
def from_dict(obj: Any) -> 'ClassLabelElement':
|
|
78
109
|
assert isinstance(obj, dict)
|
|
79
110
|
id = UUID(obj.get("id"))
|
|
80
111
|
idx = from_int(obj.get("idx"))
|
|
81
|
-
return
|
|
112
|
+
return ClassLabelElement(id, idx)
|
|
82
113
|
|
|
83
114
|
def to_dict(self) -> dict:
|
|
84
115
|
result: dict = {}
|
|
@@ -109,29 +140,59 @@ class Config:
|
|
|
109
140
|
return result
|
|
110
141
|
|
|
111
142
|
|
|
112
|
-
class
|
|
113
|
-
|
|
114
|
-
|
|
143
|
+
class OcrCharacterRestrictionPreset:
|
|
144
|
+
characters: str
|
|
145
|
+
value: str
|
|
115
146
|
|
|
116
|
-
def __init__(self,
|
|
117
|
-
self.
|
|
118
|
-
self.
|
|
147
|
+
def __init__(self, characters: str, value: str) -> None:
|
|
148
|
+
self.characters = characters
|
|
149
|
+
self.value = value
|
|
119
150
|
|
|
120
151
|
@staticmethod
|
|
121
|
-
def from_dict(obj: Any) -> '
|
|
152
|
+
def from_dict(obj: Any) -> 'OcrCharacterRestrictionPreset':
|
|
122
153
|
assert isinstance(obj, dict)
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
return
|
|
154
|
+
characters = from_str(obj.get("characters"))
|
|
155
|
+
value = from_str(obj.get("value"))
|
|
156
|
+
return OcrCharacterRestrictionPreset(characters, value)
|
|
126
157
|
|
|
127
158
|
def to_dict(self) -> dict:
|
|
128
159
|
result: dict = {}
|
|
129
|
-
result["
|
|
130
|
-
result["
|
|
160
|
+
result["characters"] = from_str(self.characters)
|
|
161
|
+
result["value"] = from_str(self.value)
|
|
131
162
|
return result
|
|
132
163
|
|
|
133
164
|
|
|
134
|
-
class
|
|
165
|
+
class OcrCharacterRestrictionElement:
|
|
166
|
+
allowed_characters: str
|
|
167
|
+
index: int
|
|
168
|
+
number_of_characters: int
|
|
169
|
+
ocr_character_restriction_preset: OcrCharacterRestrictionPreset
|
|
170
|
+
|
|
171
|
+
def __init__(self, allowed_characters: str, index: int, number_of_characters: int, ocr_character_restriction_preset: OcrCharacterRestrictionPreset) -> None:
|
|
172
|
+
self.allowed_characters = allowed_characters
|
|
173
|
+
self.index = index
|
|
174
|
+
self.number_of_characters = number_of_characters
|
|
175
|
+
self.ocr_character_restriction_preset = ocr_character_restriction_preset
|
|
176
|
+
|
|
177
|
+
@staticmethod
|
|
178
|
+
def from_dict(obj: Any) -> 'OcrCharacterRestrictionElement':
|
|
179
|
+
assert isinstance(obj, dict)
|
|
180
|
+
allowed_characters = from_str(obj.get("allowed_characters"))
|
|
181
|
+
index = from_int(obj.get("index"))
|
|
182
|
+
number_of_characters = from_int(obj.get("number_of_characters"))
|
|
183
|
+
ocr_character_restriction_preset = OcrCharacterRestrictionPreset.from_dict(obj.get("ocr_character_restriction_preset"))
|
|
184
|
+
return OcrCharacterRestrictionElement(allowed_characters, index, number_of_characters, ocr_character_restriction_preset)
|
|
185
|
+
|
|
186
|
+
def to_dict(self) -> dict:
|
|
187
|
+
result: dict = {}
|
|
188
|
+
result["allowed_characters"] = from_str(self.allowed_characters)
|
|
189
|
+
result["index"] = from_int(self.index)
|
|
190
|
+
result["number_of_characters"] = from_int(self.number_of_characters)
|
|
191
|
+
result["ocr_character_restriction_preset"] = to_class(OcrCharacterRestrictionPreset, self.ocr_character_restriction_preset)
|
|
192
|
+
return result
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class Onnx:
|
|
135
196
|
blob_id: UUID
|
|
136
197
|
owned_by_group_id: UUID
|
|
137
198
|
|
|
@@ -140,11 +201,11 @@ class Pytorch:
|
|
|
140
201
|
self.owned_by_group_id = owned_by_group_id
|
|
141
202
|
|
|
142
203
|
@staticmethod
|
|
143
|
-
def from_dict(obj: Any) -> '
|
|
204
|
+
def from_dict(obj: Any) -> 'Onnx':
|
|
144
205
|
assert isinstance(obj, dict)
|
|
145
206
|
blob_id = UUID(obj.get("blob_id"))
|
|
146
207
|
owned_by_group_id = UUID(obj.get("owned_by_group_id"))
|
|
147
|
-
return
|
|
208
|
+
return Onnx(blob_id, owned_by_group_id)
|
|
148
209
|
|
|
149
210
|
def to_dict(self) -> dict:
|
|
150
211
|
result: dict = {}
|
|
@@ -155,9 +216,9 @@ class Pytorch:
|
|
|
155
216
|
|
|
156
217
|
class Snapshot:
|
|
157
218
|
onnx: Onnx
|
|
158
|
-
pytorch:
|
|
219
|
+
pytorch: Onnx
|
|
159
220
|
|
|
160
|
-
def __init__(self, onnx: Onnx, pytorch:
|
|
221
|
+
def __init__(self, onnx: Onnx, pytorch: Onnx) -> None:
|
|
161
222
|
self.onnx = onnx
|
|
162
223
|
self.pytorch = pytorch
|
|
163
224
|
|
|
@@ -165,69 +226,262 @@ class Snapshot:
|
|
|
165
226
|
def from_dict(obj: Any) -> 'Snapshot':
|
|
166
227
|
assert isinstance(obj, dict)
|
|
167
228
|
onnx = Onnx.from_dict(obj.get("onnx"))
|
|
168
|
-
pytorch =
|
|
229
|
+
pytorch = Onnx.from_dict(obj.get("pytorch"))
|
|
169
230
|
return Snapshot(onnx, pytorch)
|
|
170
231
|
|
|
171
232
|
def to_dict(self) -> dict:
|
|
172
233
|
result: dict = {}
|
|
173
234
|
result["onnx"] = to_class(Onnx, self.onnx)
|
|
174
|
-
result["pytorch"] = to_class(
|
|
235
|
+
result["pytorch"] = to_class(Onnx, self.pytorch)
|
|
175
236
|
return result
|
|
176
237
|
|
|
177
238
|
|
|
178
239
|
class NetworkExperiment:
|
|
179
|
-
class_labels: List[
|
|
240
|
+
class_labels: List[ClassLabelElement]
|
|
180
241
|
config: Config
|
|
181
242
|
flavor: str
|
|
243
|
+
id: UUID
|
|
182
244
|
network_typename: str
|
|
245
|
+
ocr_character_restrictions: Optional[List[OcrCharacterRestrictionElement]]
|
|
246
|
+
"""Only present for OCR prediction requests"""
|
|
247
|
+
|
|
183
248
|
snapshot: Snapshot
|
|
184
249
|
|
|
185
|
-
def __init__(self, class_labels: List[
|
|
250
|
+
def __init__(self, class_labels: List[ClassLabelElement], config: Config, flavor: str, id: UUID, network_typename: str, ocr_character_restrictions: Optional[List[OcrCharacterRestrictionElement]], snapshot: Snapshot) -> None:
|
|
186
251
|
self.class_labels = class_labels
|
|
187
252
|
self.config = config
|
|
188
253
|
self.flavor = flavor
|
|
254
|
+
self.id = id
|
|
189
255
|
self.network_typename = network_typename
|
|
256
|
+
self.ocr_character_restrictions = ocr_character_restrictions
|
|
190
257
|
self.snapshot = snapshot
|
|
191
258
|
|
|
192
259
|
@staticmethod
|
|
193
260
|
def from_dict(obj: Any) -> 'NetworkExperiment':
|
|
194
261
|
assert isinstance(obj, dict)
|
|
195
|
-
class_labels = from_list(
|
|
262
|
+
class_labels = from_list(ClassLabelElement.from_dict, obj.get("class_labels"))
|
|
196
263
|
config = Config.from_dict(obj.get("config"))
|
|
197
264
|
flavor = from_str(obj.get("flavor"))
|
|
265
|
+
id = UUID(obj.get("id"))
|
|
198
266
|
network_typename = from_str(obj.get("network_typename"))
|
|
267
|
+
ocr_character_restrictions = from_union([lambda x: from_list(OcrCharacterRestrictionElement.from_dict, x), from_none], obj.get("ocr_character_restrictions"))
|
|
199
268
|
snapshot = Snapshot.from_dict(obj.get("snapshot"))
|
|
200
|
-
return NetworkExperiment(class_labels, config, flavor, network_typename, snapshot)
|
|
269
|
+
return NetworkExperiment(class_labels, config, flavor, id, network_typename, ocr_character_restrictions, snapshot)
|
|
201
270
|
|
|
202
271
|
def to_dict(self) -> dict:
|
|
203
272
|
result: dict = {}
|
|
204
|
-
result["class_labels"] = from_list(lambda x: to_class(
|
|
273
|
+
result["class_labels"] = from_list(lambda x: to_class(ClassLabelElement, x), self.class_labels)
|
|
205
274
|
result["config"] = to_class(Config, self.config)
|
|
206
275
|
result["flavor"] = from_str(self.flavor)
|
|
276
|
+
result["id"] = str(self.id)
|
|
207
277
|
result["network_typename"] = from_str(self.network_typename)
|
|
278
|
+
if self.ocr_character_restrictions is not None:
|
|
279
|
+
result["ocr_character_restrictions"] = from_union([lambda x: from_list(lambda x: to_class(OcrCharacterRestrictionElement, x), x), from_none], self.ocr_character_restrictions)
|
|
208
280
|
result["snapshot"] = to_class(Snapshot, self.snapshot)
|
|
209
281
|
return result
|
|
210
282
|
|
|
211
283
|
|
|
284
|
+
class AnnotationType(Enum):
|
|
285
|
+
IGNORE = "IGNORE"
|
|
286
|
+
NEGATIVE = "NEGATIVE"
|
|
287
|
+
POSITIVE = "POSITIVE"
|
|
288
|
+
ROI = "ROI"
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
class BoundingBox:
|
|
292
|
+
"""A bounding box with optional rotation information"""
|
|
293
|
+
|
|
294
|
+
angle: Optional[float]
|
|
295
|
+
"""Optional rotation angle"""
|
|
296
|
+
|
|
297
|
+
bottom_right_x: float
|
|
298
|
+
bottom_right_y: float
|
|
299
|
+
full_orientation: Optional[bool]
|
|
300
|
+
"""Optional full orientation flag"""
|
|
301
|
+
|
|
302
|
+
top_left_x: float
|
|
303
|
+
top_left_y: float
|
|
304
|
+
|
|
305
|
+
def __init__(self, angle: Optional[float], bottom_right_x: float, bottom_right_y: float, full_orientation: Optional[bool], top_left_x: float, top_left_y: float) -> None:
|
|
306
|
+
self.angle = angle
|
|
307
|
+
self.bottom_right_x = bottom_right_x
|
|
308
|
+
self.bottom_right_y = bottom_right_y
|
|
309
|
+
self.full_orientation = full_orientation
|
|
310
|
+
self.top_left_x = top_left_x
|
|
311
|
+
self.top_left_y = top_left_y
|
|
312
|
+
|
|
313
|
+
@staticmethod
|
|
314
|
+
def from_dict(obj: Any) -> 'BoundingBox':
|
|
315
|
+
assert isinstance(obj, dict)
|
|
316
|
+
angle = from_union([from_float, from_none], obj.get("angle"))
|
|
317
|
+
bottom_right_x = from_float(obj.get("bottom_right_x"))
|
|
318
|
+
bottom_right_y = from_float(obj.get("bottom_right_y"))
|
|
319
|
+
full_orientation = from_union([from_bool, from_none], obj.get("full_orientation"))
|
|
320
|
+
top_left_x = from_float(obj.get("top_left_x"))
|
|
321
|
+
top_left_y = from_float(obj.get("top_left_y"))
|
|
322
|
+
return BoundingBox(angle, bottom_right_x, bottom_right_y, full_orientation, top_left_x, top_left_y)
|
|
323
|
+
|
|
324
|
+
def to_dict(self) -> dict:
|
|
325
|
+
result: dict = {}
|
|
326
|
+
if self.angle is not None:
|
|
327
|
+
result["angle"] = from_union([to_float, from_none], self.angle)
|
|
328
|
+
result["bottom_right_x"] = to_float(self.bottom_right_x)
|
|
329
|
+
result["bottom_right_y"] = to_float(self.bottom_right_y)
|
|
330
|
+
if self.full_orientation is not None:
|
|
331
|
+
result["full_orientation"] = from_union([from_bool, from_none], self.full_orientation)
|
|
332
|
+
result["top_left_x"] = to_float(self.top_left_x)
|
|
333
|
+
result["top_left_y"] = to_float(self.top_left_y)
|
|
334
|
+
return result
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
class Point:
|
|
338
|
+
x: float
|
|
339
|
+
y: float
|
|
340
|
+
|
|
341
|
+
def __init__(self, x: float, y: float) -> None:
|
|
342
|
+
self.x = x
|
|
343
|
+
self.y = y
|
|
344
|
+
|
|
345
|
+
@staticmethod
|
|
346
|
+
def from_dict(obj: Any) -> 'Point':
|
|
347
|
+
assert isinstance(obj, dict)
|
|
348
|
+
x = from_float(obj.get("x"))
|
|
349
|
+
y = from_float(obj.get("y"))
|
|
350
|
+
return Point(x, y)
|
|
351
|
+
|
|
352
|
+
def to_dict(self) -> dict:
|
|
353
|
+
result: dict = {}
|
|
354
|
+
result["x"] = to_float(self.x)
|
|
355
|
+
result["y"] = to_float(self.y)
|
|
356
|
+
return result
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
class GeometrySchema:
|
|
360
|
+
"""A single closed loop (ring) of a polygon, defining either an outer boundary or a hole."""
|
|
361
|
+
|
|
362
|
+
hierarchy: int
|
|
363
|
+
"""Nesting level: 0=outer, 1=hole in level 0, 2=poly in level 1 hole, etc. Even levels are
|
|
364
|
+
filled areas, odd levels are holes.
|
|
365
|
+
"""
|
|
366
|
+
points: List[Point]
|
|
367
|
+
"""Vertices of the ring."""
|
|
368
|
+
|
|
369
|
+
def __init__(self, hierarchy: int, points: List[Point]) -> None:
|
|
370
|
+
self.hierarchy = hierarchy
|
|
371
|
+
self.points = points
|
|
372
|
+
|
|
373
|
+
@staticmethod
|
|
374
|
+
def from_dict(obj: Any) -> 'GeometrySchema':
|
|
375
|
+
assert isinstance(obj, dict)
|
|
376
|
+
hierarchy = from_int(obj.get("hierarchy"))
|
|
377
|
+
points = from_list(Point.from_dict, obj.get("points"))
|
|
378
|
+
return GeometrySchema(hierarchy, points)
|
|
379
|
+
|
|
380
|
+
def to_dict(self) -> dict:
|
|
381
|
+
result: dict = {}
|
|
382
|
+
result["hierarchy"] = from_int(self.hierarchy)
|
|
383
|
+
result["points"] = from_list(lambda x: to_class(Point, x), self.points)
|
|
384
|
+
return result
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
class Polygon:
|
|
388
|
+
"""A polygon defined by one or more rings, allowing for holes and nested structures."""
|
|
389
|
+
|
|
390
|
+
rings: List[GeometrySchema]
|
|
391
|
+
"""Array of polygon rings. The hierarchy field within each ring determines nesting and
|
|
392
|
+
fill/hole status.
|
|
393
|
+
"""
|
|
394
|
+
|
|
395
|
+
def __init__(self, rings: List[GeometrySchema]) -> None:
|
|
396
|
+
self.rings = rings
|
|
397
|
+
|
|
398
|
+
@staticmethod
|
|
399
|
+
def from_dict(obj: Any) -> 'Polygon':
|
|
400
|
+
assert isinstance(obj, dict)
|
|
401
|
+
rings = from_list(GeometrySchema.from_dict, obj.get("rings"))
|
|
402
|
+
return Polygon(rings)
|
|
403
|
+
|
|
404
|
+
def to_dict(self) -> dict:
|
|
405
|
+
result: dict = {}
|
|
406
|
+
result["rings"] = from_list(lambda x: to_class(GeometrySchema, x), self.rings)
|
|
407
|
+
return result
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
class ObjectElement:
|
|
411
|
+
annotation_type: AnnotationType
|
|
412
|
+
average_width: float
|
|
413
|
+
bounding_box: Optional[BoundingBox]
|
|
414
|
+
id: UUID
|
|
415
|
+
label_id: UUID
|
|
416
|
+
polygon: Optional[Polygon]
|
|
417
|
+
|
|
418
|
+
def __init__(self, annotation_type: AnnotationType, average_width: float, bounding_box: Optional[BoundingBox], id: UUID, label_id: UUID, polygon: Optional[Polygon]) -> None:
|
|
419
|
+
self.annotation_type = annotation_type
|
|
420
|
+
self.average_width = average_width
|
|
421
|
+
self.bounding_box = bounding_box
|
|
422
|
+
self.id = id
|
|
423
|
+
self.label_id = label_id
|
|
424
|
+
self.polygon = polygon
|
|
425
|
+
|
|
426
|
+
@staticmethod
|
|
427
|
+
def from_dict(obj: Any) -> 'ObjectElement':
|
|
428
|
+
assert isinstance(obj, dict)
|
|
429
|
+
annotation_type = AnnotationType(obj.get("annotation_type"))
|
|
430
|
+
average_width = from_float(obj.get("average_width"))
|
|
431
|
+
bounding_box = from_union([BoundingBox.from_dict, from_none], obj.get("bounding_box"))
|
|
432
|
+
id = UUID(obj.get("id"))
|
|
433
|
+
label_id = UUID(obj.get("label_id"))
|
|
434
|
+
polygon = from_union([Polygon.from_dict, from_none], obj.get("polygon"))
|
|
435
|
+
return ObjectElement(annotation_type, average_width, bounding_box, id, label_id, polygon)
|
|
436
|
+
|
|
437
|
+
def to_dict(self) -> dict:
|
|
438
|
+
result: dict = {}
|
|
439
|
+
result["annotation_type"] = to_enum(AnnotationType, self.annotation_type)
|
|
440
|
+
result["average_width"] = to_float(self.average_width)
|
|
441
|
+
if self.bounding_box is not None:
|
|
442
|
+
result["bounding_box"] = from_union([lambda x: to_class(BoundingBox, x), from_none], self.bounding_box)
|
|
443
|
+
result["id"] = str(self.id)
|
|
444
|
+
result["label_id"] = str(self.label_id)
|
|
445
|
+
if self.polygon is not None:
|
|
446
|
+
result["polygon"] = from_union([lambda x: to_class(Polygon, x), from_none], self.polygon)
|
|
447
|
+
return result
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
class RequestType(Enum):
|
|
451
|
+
"""Discriminator field to identify the type of prediction request"""
|
|
452
|
+
|
|
453
|
+
OCR = "ocr"
|
|
454
|
+
STANDARD = "standard"
|
|
455
|
+
|
|
456
|
+
|
|
212
457
|
class PredictionRequest:
|
|
213
458
|
created_by_user_id: UUID
|
|
214
459
|
hasura_url: str
|
|
215
460
|
id: UUID
|
|
216
461
|
image: Image
|
|
217
462
|
network_experiment: NetworkExperiment
|
|
463
|
+
objects: Optional[List[ObjectElement]]
|
|
464
|
+
"""Only present for OCR prediction requests"""
|
|
465
|
+
|
|
218
466
|
owned_by_group_id: UUID
|
|
219
467
|
prediction_priority: int
|
|
220
|
-
request_classification_interpretation: bool
|
|
468
|
+
request_classification_interpretation: Optional[bool]
|
|
469
|
+
"""Only present for standard prediction requests"""
|
|
470
|
+
|
|
471
|
+
request_type: RequestType
|
|
472
|
+
"""Discriminator field to identify the type of prediction request"""
|
|
221
473
|
|
|
222
|
-
def __init__(self, created_by_user_id: UUID, hasura_url: str, id: UUID, image: Image, network_experiment: NetworkExperiment, owned_by_group_id: UUID, prediction_priority: int, request_classification_interpretation: bool) -> None:
|
|
474
|
+
def __init__(self, created_by_user_id: UUID, hasura_url: str, id: UUID, image: Image, network_experiment: NetworkExperiment, objects: Optional[List[ObjectElement]], owned_by_group_id: UUID, prediction_priority: int, request_classification_interpretation: Optional[bool], request_type: RequestType) -> None:
|
|
223
475
|
self.created_by_user_id = created_by_user_id
|
|
224
476
|
self.hasura_url = hasura_url
|
|
225
477
|
self.id = id
|
|
226
478
|
self.image = image
|
|
227
479
|
self.network_experiment = network_experiment
|
|
480
|
+
self.objects = objects
|
|
228
481
|
self.owned_by_group_id = owned_by_group_id
|
|
229
482
|
self.prediction_priority = prediction_priority
|
|
230
483
|
self.request_classification_interpretation = request_classification_interpretation
|
|
484
|
+
self.request_type = request_type
|
|
231
485
|
|
|
232
486
|
@staticmethod
|
|
233
487
|
def from_dict(obj: Any) -> 'PredictionRequest':
|
|
@@ -237,10 +491,12 @@ class PredictionRequest:
|
|
|
237
491
|
id = UUID(obj.get("id"))
|
|
238
492
|
image = Image.from_dict(obj.get("image"))
|
|
239
493
|
network_experiment = NetworkExperiment.from_dict(obj.get("network_experiment"))
|
|
494
|
+
objects = from_union([lambda x: from_list(ObjectElement.from_dict, x), from_none], obj.get("objects"))
|
|
240
495
|
owned_by_group_id = UUID(obj.get("owned_by_group_id"))
|
|
241
496
|
prediction_priority = from_int(obj.get("prediction_priority"))
|
|
242
|
-
request_classification_interpretation = from_bool
|
|
243
|
-
|
|
497
|
+
request_classification_interpretation = from_union([from_bool, from_none], obj.get("request_classification_interpretation"))
|
|
498
|
+
request_type = RequestType(obj.get("request_type"))
|
|
499
|
+
return PredictionRequest(created_by_user_id, hasura_url, id, image, network_experiment, objects, owned_by_group_id, prediction_priority, request_classification_interpretation, request_type)
|
|
244
500
|
|
|
245
501
|
def to_dict(self) -> dict:
|
|
246
502
|
result: dict = {}
|
|
@@ -249,9 +505,13 @@ class PredictionRequest:
|
|
|
249
505
|
result["id"] = str(self.id)
|
|
250
506
|
result["image"] = to_class(Image, self.image)
|
|
251
507
|
result["network_experiment"] = to_class(NetworkExperiment, self.network_experiment)
|
|
508
|
+
if self.objects is not None:
|
|
509
|
+
result["objects"] = from_union([lambda x: from_list(lambda x: to_class(ObjectElement, x), x), from_none], self.objects)
|
|
252
510
|
result["owned_by_group_id"] = str(self.owned_by_group_id)
|
|
253
511
|
result["prediction_priority"] = from_int(self.prediction_priority)
|
|
254
|
-
|
|
512
|
+
if self.request_classification_interpretation is not None:
|
|
513
|
+
result["request_classification_interpretation"] = from_union([from_bool, from_none], self.request_classification_interpretation)
|
|
514
|
+
result["request_type"] = to_enum(RequestType, self.request_type)
|
|
255
515
|
return result
|
|
256
516
|
|
|
257
517
|
|
|
@@ -281,7 +281,7 @@ class RingPoint:
|
|
|
281
281
|
return result
|
|
282
282
|
|
|
283
283
|
|
|
284
|
-
class
|
|
284
|
+
class GeometrySchema:
|
|
285
285
|
"""A single closed loop (ring) of a polygon, defining either an outer boundary or a hole."""
|
|
286
286
|
|
|
287
287
|
hierarchy: int
|
|
@@ -296,11 +296,11 @@ class SegmentationMarkupSchema:
|
|
|
296
296
|
self.points = points
|
|
297
297
|
|
|
298
298
|
@staticmethod
|
|
299
|
-
def from_dict(obj: Any) -> '
|
|
299
|
+
def from_dict(obj: Any) -> 'GeometrySchema':
|
|
300
300
|
assert isinstance(obj, dict)
|
|
301
301
|
hierarchy = from_int(obj.get("hierarchy"))
|
|
302
302
|
points = from_list(RingPoint.from_dict, obj.get("points"))
|
|
303
|
-
return
|
|
303
|
+
return GeometrySchema(hierarchy, points)
|
|
304
304
|
|
|
305
305
|
def to_dict(self) -> dict:
|
|
306
306
|
result: dict = {}
|
|
@@ -312,23 +312,23 @@ class SegmentationMarkupSchema:
|
|
|
312
312
|
class PolygonAnnotation:
|
|
313
313
|
"""A polygon defined by one or more rings, allowing for holes and nested structures."""
|
|
314
314
|
|
|
315
|
-
rings: List[
|
|
315
|
+
rings: List[GeometrySchema]
|
|
316
316
|
"""Array of polygon rings. The hierarchy field within each ring determines nesting and
|
|
317
317
|
fill/hole status.
|
|
318
318
|
"""
|
|
319
319
|
|
|
320
|
-
def __init__(self, rings: List[
|
|
320
|
+
def __init__(self, rings: List[GeometrySchema]) -> None:
|
|
321
321
|
self.rings = rings
|
|
322
322
|
|
|
323
323
|
@staticmethod
|
|
324
324
|
def from_dict(obj: Any) -> 'PolygonAnnotation':
|
|
325
325
|
assert isinstance(obj, dict)
|
|
326
|
-
rings = from_list(
|
|
326
|
+
rings = from_list(GeometrySchema.from_dict, obj.get("rings"))
|
|
327
327
|
return PolygonAnnotation(rings)
|
|
328
328
|
|
|
329
329
|
def to_dict(self) -> dict:
|
|
330
330
|
result: dict = {}
|
|
331
|
-
result["rings"] = from_list(lambda x: to_class(
|
|
331
|
+
result["rings"] = from_list(lambda x: to_class(GeometrySchema, x), self.rings)
|
|
332
332
|
return result
|
|
333
333
|
|
|
334
334
|
|
|
@@ -4,7 +4,7 @@ denkproto/DENKbuffer_pb2_grpc.py,sha256=-CPJPM4FOqwvwV8-f1iJlD18UD9juVIIHfdWUecu
|
|
|
4
4
|
denkproto/ImageAnalysis_ProtobufMessages_pb2.py,sha256=iEY0j9ySGUThnqTdYD4uAVr9P3GiC5R02iK53zEOXUQ,21015
|
|
5
5
|
denkproto/ImageAnalysis_ProtobufMessages_pb2.pyi,sha256=5LFtxrmYpJHizDDNGFTkL7-NQ_TkwqCSdq7vcv3lg-c,36243
|
|
6
6
|
denkproto/ImageAnalysis_ProtobufMessages_pb2_grpc.py,sha256=l3agtDjgu4jay6P9TRnHhyhJ-7UdoII27ywhw3k84oo,911
|
|
7
|
-
denkproto/__about__.py,sha256=
|
|
7
|
+
denkproto/__about__.py,sha256=pJbxmrSaZdlmxBIORIdVrmW_p012oX6Otld4fhk0Tnc,23
|
|
8
8
|
denkproto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
denkproto/denkcache_pb2.py,sha256=u0O26m7t4kfu4R1nx1ZcTst4n6pG32pMbhl2PGYivXE,7161
|
|
10
10
|
denkproto/denkcache_pb2.pyi,sha256=8K_Ebyy4mgXrxqJenN8f8LXLvVKOiaZxhmGeYjFZVpY,6357
|
|
@@ -26,14 +26,14 @@ denkproto/validate_pb2.py,sha256=CuGAaHir9X9jniW3QsRKAESjYzoS2U6dLk_J55XmNqU,136
|
|
|
26
26
|
denkproto/validate_pb2.pyi,sha256=fWsdVOR3NJDioCKkCKfxfl4qaEb5xqXXU_WlEbdQx6E,23077
|
|
27
27
|
denkproto/validate_pb2_grpc.py,sha256=XvjuWEgJFJtH1E7HWm7SKpV10PMpOSbonKa2VPHpYy8,889
|
|
28
28
|
denkproto/json/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
|
-
denkproto/json/annotation_comparer_request.py,sha256=
|
|
29
|
+
denkproto/json/annotation_comparer_request.py,sha256=tnoriGgQrth9KqgcrFe5lVql4aSiYhT4SROEYpSrsvY,40138
|
|
30
30
|
denkproto/json/classification_markup.py,sha256=vTu0H7Cb3gU6UUUSg1vDTRlFUorZrjMbcp_yx6UssZA,2461
|
|
31
31
|
denkproto/json/inference_graph_models_generated.py,sha256=GfsGk4bKbL8gyqOScA4x13P8sJrAmv3tEhNU36rbIDs,6313
|
|
32
32
|
denkproto/json/object_detection_markup.py,sha256=T0hcFPq8F_galjDjRC9dbcRVwCSOYtu2jt9wpEeHlQs,4904
|
|
33
|
-
denkproto/json/ocr_markup.py,sha256=
|
|
33
|
+
denkproto/json/ocr_markup.py,sha256=xZs321ZqOUPK-VzWhy3gKCdqt_EyKOs-6FbaJdSvEMQ,7824
|
|
34
34
|
denkproto/json/ocr_prediction_request.py,sha256=PXY_1hmPQcKpHHZyikMFG_S0HKiwbXtRv5oW5x1zHRM,17783
|
|
35
|
-
denkproto/json/prediction_request.py,sha256=
|
|
36
|
-
denkproto/json/segmentation_markup.py,sha256=
|
|
37
|
-
denkproto-1.0.
|
|
38
|
-
denkproto-1.0.
|
|
39
|
-
denkproto-1.0.
|
|
35
|
+
denkproto/json/prediction_request.py,sha256=9AE7KZgQPciRJwMIMkRUMCY85tY6zaaV_Z75XxEF2KQ,18894
|
|
36
|
+
denkproto/json/segmentation_markup.py,sha256=ZU2qYuN1IkZDCjAjr0vEn6nRVdZv24EwRYlmrGEzeVg,19841
|
|
37
|
+
denkproto-1.0.95.dist-info/METADATA,sha256=DsP02yp_tKPj9fLCDlebvs-PUZxDrDLV5w8ybOsq-SQ,110
|
|
38
|
+
denkproto-1.0.95.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
39
|
+
denkproto-1.0.95.dist-info/RECORD,,
|
|
File without changes
|