Skip to content

Commit fd5fd48

Browse files
authored
Merge pull request #244 from Labelbox/ms/minor-updates
rename to raster to draw
2 parents 63c5cbf + f3ef963 commit fd5fd48

File tree

18 files changed

+119
-71
lines changed

18 files changed

+119
-71
lines changed

CHANGELOG.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,57 @@
11
# Changelog
22

3+
# Version 3.0.0 (2021-08-12)
4+
## Added
5+
* Annotation types
6+
- A set of python objects for working with labelbox data
7+
- Creates a standard interface for both exports and imports
8+
- See example notebooks on how to use under examples/annotation_types
9+
- Note that these types are not yet supported for tiled imagery
10+
* MEA Support
11+
- Beta MEA users can now just use the latest SDK release
12+
* Metadata support
13+
- New metadata features are now fully supported by the SDK
14+
* Easier export
15+
- `project.export_labels()` accepts a boolean indicating whether or not to download the result
16+
- Create annotation objects directly from exports with `project.label_generator()` or `project.video_label_generator()`
17+
- `project.video_label_generator()` asynchronously fetches video annotations
18+
* Retry logic on data uploads
19+
- Bulk creation of data rows will be more reliable
20+
* Datasets
21+
- Determine the number of data rows just by calling `dataset.row_count`.
22+
- Updated threading logic in create_data_rows() to make it compatible with aws lambdas
23+
* Ontology
24+
- `OntologyBuilder`, `Classification`, `Option`, and `Tool` can now be imported from `labelbox` instead of `labelbox.schema.ontology`
25+
26+
## Removed
27+
* Deprecated:
28+
- `project.reviews()`
29+
- `project.create_prediction()`
30+
- `project.create_prediction_model()`
31+
- `project.create_label()`
32+
- `Project.predictions()`
33+
- `Project.active_prediction_model`
34+
- `data_row.predictions`
35+
- `PredictionModel`
36+
- `Prediction`
37+
* Replaced:
38+
- `data_row.metadata()` use `data_row.attachments()` instead
39+
- `data_row.create_metadata()` use `data_row.create_attachments()` instead
40+
- `AssetMetadata` use `AssetAttachment` instead
41+
42+
## Fixes
43+
* Support derived classes of ontology objects when using `from_dict`
44+
* Notebooks:
45+
- Video export bug where the code would fail if the exported projects had tools other than bounding boxes
46+
- MAL demos were broken due to an image download failing.
47+
48+
## Misc
49+
* Data processing dependencies are not installed by default to for users that only want client functionality.
50+
* To install all dependencies required for the data modules (annotation types and mea metric calculation) use `pip install labelbox[data]`
51+
* Decrease wait time between updates for `BulkImportRequest.wait_until_done()`.
52+
* Organization is no longer used to create the LFO in `Project.setup()`
53+
54+
355
# Version 3.0.0-rc3 (2021-08-11)
456
## Updates
557
* Geometry.raster now has a consistent interface and improved functionality

examples/annotation_types/basics.ipynb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@
652652
"##### Geometry Utilities\n",
653653
"* All of the previous objects except TextEntity inherit from the Geometry base class\n",
654654
"* They have the following properties and functions\n",
655-
" 1. raster(height width, kwargs)\n",
655+
" 1. draw(height width, kwargs)\n",
656656
" 2. shape - property\n",
657657
" 3. geometry - property"
658658
]
@@ -714,7 +714,7 @@
714714
"outputs": [],
715715
"source": [
716716
"color = (255,255,255)\n",
717-
"np_mask = polygon_annotation.value.raster(height = im.size[1], width = im.size[0], color = color)\n",
717+
"np_mask = polygon_annotation.value.draw(height = im.size[1], width = im.size[0], color = color)\n",
718718
"Image.fromarray(np.hstack([np_mask, np_data]))"
719719
]
720720
},
@@ -767,9 +767,9 @@
767767
" Polygon(points = [Point(x=x,y=y) for x,y in [[82, 180], [83, 184], [88, 184], [86, 180]]]),\n",
768768
" Polygon(points = [Point(x=x,y=y) for x,y in [[97, 182], [99, 184], [102, 183], [101, 180], [98, 180]]]), \n",
769769
"]\n",
770-
"eye_masks = np.max([eye.raster(height = h, width = w) for eye in eyes], axis = 0)\n",
770+
"eye_masks = np.max([eye.draw(height = h, width = w) for eye in eyes], axis = 0)\n",
771771
"nose = Polygon(points =[ Point(x=x,y=y) for x,y in [[95, 192], [93, 197], [96, 198], [100, 197], [100, 194], [100, 192], [96, 192]]])\n",
772-
"nose_mask = nose.raster(height = h, width = w, color = nose_color)\n",
772+
"nose_mask = nose.draw(height = h, width = w, color = nose_color)\n",
773773
"# Picks the brighter color if there is overlap. \n",
774774
"# If you don't want overlap then just simply create separate masks\n",
775775
"np_seg_mask = np.max([nose_mask, eye_masks], axis = 0)\n",
@@ -801,7 +801,7 @@
801801
"id": "swiss-storm",
802802
"metadata": {},
803803
"source": [
804-
"* Calling `mask.raster()` will return a mask with pixels equal to the specified color"
804+
"* Calling `mask.draw()` will return a mask with pixels equal to the specified color"
805805
]
806806
},
807807
{
@@ -811,8 +811,8 @@
811811
"metadata": {},
812812
"outputs": [],
813813
"source": [
814-
"eye_raster = eye_mask.raster()\n",
815-
"nose_raster = nose_mask.raster()\n",
814+
"eye_raster = eye_mask.draw()\n",
815+
"nose_raster = nose_mask.draw()\n",
816816
"Image.fromarray(np.hstack([eye_raster,nose_raster, np_data]))"
817817
]
818818
},

examples/annotation_types/converters.ipynb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@
367367
" \n",
368368
" for annotation in annotation_lookup[idx]:\n",
369369
" if isinstance(annotation.value, Rectangle):\n",
370-
" frame = annotation.value.raster(canvas = frame.astype(np.uint8), thickness = 10, color= (255,0,0))\n",
370+
" frame = annotation.value.draw(canvas = frame.astype(np.uint8), thickness = 10, color= (255,0,0))\n",
371371
" \n",
372372
" im = Image.fromarray(frame)\n",
373373
" w,h = im.size\n",
@@ -439,7 +439,7 @@
439439
"canvas = np.zeros((h, w, 3), dtype = np.uint8)\n",
440440
"for annotation in label_list[0].annotations:\n",
441441
" if isinstance(annotation.value, Geometry):\n",
442-
" canvas = annotation.value.raster(canvas = canvas)\n",
442+
" canvas = annotation.value.draw(canvas = canvas)\n",
443443
"Image.fromarray(canvas)"
444444
]
445445
},

examples/annotation_types/label_containers.ipynb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,10 @@
132132
" im_h, im_w = 300, 200\n",
133133
" image_url = \"https://picsum.photos/id/1003/200/300\"\n",
134134
" nose_color, eye_color = (0,255,0), (255,0,0)\n",
135-
" nose_mask = Point(x = 96, y = 194).raster(im_h, im_w, thickness = 3)\n",
135+
" nose_mask = Point(x = 96, y = 194).draw(im_h, im_w, thickness = 3)\n",
136136
" eye_masks = [\n",
137-
" Point(x = 84, y = 182).raster(im_h, im_w, thickness = 3),\n",
138-
" Point(x = 99, y = 181).raster(im_h, im_w, thickness = 3),\n",
137+
" Point(x = 84, y = 182).draw(im_h, im_w, thickness = 3),\n",
138+
" Point(x = 99, y = 181).draw(im_h, im_w, thickness = 3),\n",
139139
" ]\n",
140140
" mask_arr = np.max([*eye_masks,nose_mask] , axis = 0)\n",
141141
" mask = MaskData(arr = mask_arr)\n",

examples/label_export/images.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@
165165
"# Draw the annotations onto the source image\n",
166166
"for annotation in label.annotations:\n",
167167
" if isinstance(annotation.value, Geometry):\n",
168-
" image_np = annotation.value.raster(canvas = image_np, color = colors[annotation.name], thickness = 5)\n",
168+
" image_np = annotation.value.draw(canvas = image_np, color = colors[annotation.name], thickness = 5)\n",
169169
"Image.fromarray(image_np.astype(np.uint8))"
170170
]
171171
},

labelbox/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name = "labelbox"
2-
__version__ = "3.0.0-rc3"
2+
__version__ = "3.0.0"
33

44
from labelbox.schema.project import Project
55
from labelbox.client import Client

labelbox/data/annotation_types/geometry/geometry.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ def geometry(self) -> geojson:
3535
pass
3636

3737
@abstractmethod
38-
def raster(self,
39-
height: Optional[int] = None,
40-
width: Optional[int] = None,
41-
canvas: Optional[np.ndarray] = None,
42-
color: Optional[Union[int, Tuple[int, int, int]]] = None,
43-
thickness: Optional[int] = 1) -> np.ndarray:
38+
def draw(self,
39+
height: Optional[int] = None,
40+
width: Optional[int] = None,
41+
canvas: Optional[np.ndarray] = None,
42+
color: Optional[Union[int, Tuple[int, int, int]]] = None,
43+
thickness: Optional[int] = 1) -> np.ndarray:
4444
pass

labelbox/data/annotation_types/geometry/line.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ def geometry(self) -> geojson.MultiLineString:
1616
return geojson.MultiLineString(
1717
[[[point.x, point.y] for point in self.points]])
1818

19-
def raster(self,
20-
height: Optional[int] = None,
21-
width: Optional[int] = None,
22-
canvas: Optional[np.ndarray] = None,
23-
color: Union[int, Tuple[int, int, int]] = (255, 255, 255),
24-
thickness: int = 1) -> np.ndarray:
19+
def draw(self,
20+
height: Optional[int] = None,
21+
width: Optional[int] = None,
22+
canvas: Optional[np.ndarray] = None,
23+
color: Union[int, Tuple[int, int, int]] = (255, 255, 255),
24+
thickness: int = 1) -> np.ndarray:
2525
"""
2626
Draw the line onto a 3d mask
2727
Args:

labelbox/data/annotation_types/geometry/mask.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,28 @@
1111

1212

1313
class Mask(Geometry):
14-
# Raster data can be shared across multiple masks... or not
14+
# Mask data can be shared across multiple masks
1515
mask: MaskData
16-
# RGB or Grayscale
1716
color: Tuple[int, int, int]
1817

1918
@property
2019
def geometry(self):
21-
mask = self.raster(color=1)
20+
mask = self.draw(color=1)
2221
polygons = (
2322
shape(shp)
2423
for shp, val in shapes(mask, mask=None)
2524
# ignore if shape is area of smaller than 1 pixel
2625
if val >= 1)
2726
return MultiPolygon(polygons).__geo_interface__
2827

29-
def raster(self,
30-
height: Optional[int] = None,
31-
width: Optional[int] = None,
32-
canvas: Optional[np.ndarray] = None,
33-
color: Optional[Union[int, Tuple[int, int, int]]] = None,
34-
thickness=None) -> np.ndarray:
28+
def draw(self,
29+
height: Optional[int] = None,
30+
width: Optional[int] = None,
31+
canvas: Optional[np.ndarray] = None,
32+
color: Optional[Union[int, Tuple[int, int, int]]] = None,
33+
thickness=None) -> np.ndarray:
3534
"""
36-
# TODO: Optionally use the color. a color of 1 will result in a binary canvas
37-
38-
39-
Removes all pixels from the segmentation mask that do not equal self.color
35+
Converts the Mask object into a numpy array
4036
4137
Args:
4238
height (int): Optionally resize mask height before drawing.

labelbox/data/annotation_types/geometry/point.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ class Point(Geometry):
1515
def geometry(self) -> geojson.Point:
1616
return geojson.Point([self.x, self.y])
1717

18-
def raster(self,
19-
height: Optional[int] = None,
20-
width: Optional[int] = None,
21-
canvas: Optional[np.ndarray] = None,
22-
color: Union[int, Tuple[int, int, int]] = (255, 255, 255),
23-
thickness: int = 10) -> np.ndarray:
18+
def draw(self,
19+
height: Optional[int] = None,
20+
width: Optional[int] = None,
21+
canvas: Optional[np.ndarray] = None,
22+
color: Union[int, Tuple[int, int, int]] = (255, 255, 255),
23+
thickness: int = 10) -> np.ndarray:
2424
"""
2525
Draw the point onto a 3d mask
2626
Args:

0 commit comments

Comments
 (0)