Skip to content

Commit 0809416

Browse files
author
gdj0nes
committed
ADDL video mal notebook
1 parent f15f3ab commit 0809416

File tree

2 files changed

+364
-9
lines changed

2 files changed

+364
-9
lines changed

examples/model_assisted_labeling/image_mal.ipynb

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,7 @@
2323
"metadata": {},
2424
"outputs": [],
2525
"source": [
26-
"!pip install labelbox\n",
27-
"!pip install requests\n",
28-
"!pip install ndjson\n",
29-
"!pip install scikit-image\n",
30-
"!pip install PILLOW\n",
31-
"!pip install tensorflow\n",
32-
"!pip install opencv-python"
26+
"!pip install labelbox requests ndjson scikit-image PILLOW tensorflow opencv-python"
3327
]
3428
},
3529
{
@@ -534,7 +528,7 @@
534528
],
535529
"metadata": {
536530
"kernelspec": {
537-
"display_name": "Python 3",
531+
"display_name": "Python 3 (ipykernel)",
538532
"language": "python",
539533
"name": "python3"
540534
},
@@ -548,7 +542,7 @@
548542
"name": "python",
549543
"nbconvert_exporter": "python",
550544
"pygments_lexer": "ipython3",
551-
"version": "3.8.8"
545+
"version": "3.8.2"
552546
}
553547
},
554548
"nbformat": 4,
Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "stupid-court",
6+
"metadata": {},
7+
"source": [
8+
"# Video MAL"
9+
]
10+
},
11+
{
12+
"cell_type": "markdown",
13+
"id": "intellectual-idaho",
14+
"metadata": {},
15+
"source": [
16+
"* Upload model inferences for video tasks\n",
17+
"* Support types\n",
18+
" * bounding box"
19+
]
20+
},
21+
{
22+
"cell_type": "code",
23+
"execution_count": 1,
24+
"id": "voluntary-minister",
25+
"metadata": {},
26+
"outputs": [],
27+
"source": [
28+
"%%capture\n",
29+
"!pip install labelbox"
30+
]
31+
},
32+
{
33+
"cell_type": "code",
34+
"execution_count": 2,
35+
"id": "committed-richards",
36+
"metadata": {},
37+
"outputs": [],
38+
"source": [
39+
"import os\n",
40+
"import uuid\n",
41+
"from io import BytesIO\n",
42+
"from typing import Dict, Any, Tuple\n",
43+
"\n",
44+
"from labelbox import Client, LabelingFrontend\n",
45+
"from labelbox.schema.ontology import OntologyBuilder, Tool, Classification, Option"
46+
]
47+
},
48+
{
49+
"cell_type": "code",
50+
"execution_count": 4,
51+
"id": "thirty-grocery",
52+
"metadata": {},
53+
"outputs": [],
54+
"source": [
55+
"API_KEY = os.environ.get(\"LABELBOX_API_KEY\")\n",
56+
"if not API_KEY:\n",
57+
" raise EnvironmentError(\"Missing API Key\")"
58+
]
59+
},
60+
{
61+
"cell_type": "code",
62+
"execution_count": 5,
63+
"id": "conservative-marsh",
64+
"metadata": {},
65+
"outputs": [],
66+
"source": [
67+
"# Only update this if you have an on-prem deployment\n",
68+
"ENDPOINT = \"https://api.labelbox.com/graphql\""
69+
]
70+
},
71+
{
72+
"cell_type": "code",
73+
"execution_count": 6,
74+
"id": "affecting-myanmar",
75+
"metadata": {},
76+
"outputs": [],
77+
"source": [
78+
"client = Client(\n",
79+
" api_key=API_KEY,\n",
80+
" endpoint=ENDPOINT\n",
81+
")"
82+
]
83+
},
84+
{
85+
"cell_type": "markdown",
86+
"id": "blessed-venture",
87+
"metadata": {},
88+
"source": [
89+
"### Project Setup"
90+
]
91+
},
92+
{
93+
"cell_type": "code",
94+
"execution_count": 7,
95+
"id": "suburban-crowd",
96+
"metadata": {},
97+
"outputs": [],
98+
"source": [
99+
"# We want to try out a few different tools here.\n",
100+
"ontology_builder = OntologyBuilder(\n",
101+
" tools=[\n",
102+
" Tool(tool=Tool.Type.BBOX, name=\"jellyfish\")\n",
103+
" ]\n",
104+
")"
105+
]
106+
},
107+
{
108+
"cell_type": "code",
109+
"execution_count": 8,
110+
"id": "modern-program",
111+
"metadata": {},
112+
"outputs": [],
113+
"source": [
114+
"# Lets setup a project to label\n",
115+
"# Note see Ontology, Project, and Project_setup notebooks for more information on this section.\n",
116+
"project = client.create_project(name=\"video_mal_project\")\n",
117+
"dataset = client.create_dataset(name=\"video_mal_dataset\")\n",
118+
"dataset.create_data_row(\n",
119+
" row_data=\"https://storage.labelbox.com/cjhfn5y6s0pk507024nz1ocys%2Fb8837f3b-b071-98d9-645e-2e2c0302393b-jellyfish2-100-110.mp4\")\n",
120+
"editor = next(\n",
121+
" client.get_labeling_frontends(where=LabelingFrontend.name == \"Editor\")\n",
122+
")\n",
123+
"project.setup(editor, ontology_builder.asdict())\n",
124+
"project.datasets.connect(dataset)"
125+
]
126+
},
127+
{
128+
"cell_type": "code",
129+
"execution_count": 9,
130+
"id": "vietnamese-kingdom",
131+
"metadata": {},
132+
"outputs": [
133+
{
134+
"data": {
135+
"text/plain": [
136+
"True"
137+
]
138+
},
139+
"execution_count": 9,
140+
"metadata": {},
141+
"output_type": "execute_result"
142+
}
143+
],
144+
"source": [
145+
"project.enable_model_assisted_labeling()"
146+
]
147+
},
148+
{
149+
"cell_type": "markdown",
150+
"id": "portable-grenada",
151+
"metadata": {},
152+
"source": [
153+
"#### Grab featureSchemaIds"
154+
]
155+
},
156+
{
157+
"cell_type": "code",
158+
"execution_count": 10,
159+
"id": "abstract-fifteen",
160+
"metadata": {},
161+
"outputs": [
162+
{
163+
"name": "stdout",
164+
"output_type": "stream",
165+
"text": [
166+
"{'jellyfish': 'cky3dt2lja37d0z9t26wf3qo5'}\n"
167+
]
168+
}
169+
],
170+
"source": [
171+
"# When we created a project with the ontology defined above, all of the ids were assigned.\n",
172+
"# So lets reconstruct the ontology builder with all of the ids.\n",
173+
"ontology = ontology_builder.from_project(project)\n",
174+
"# We want all of the feature schemas to be easily accessible by name.\n",
175+
"schema_lookup = {tool.name: tool.feature_schema_id for tool in ontology.tools}\n",
176+
"print(schema_lookup)"
177+
]
178+
},
179+
{
180+
"cell_type": "markdown",
181+
"id": "portuguese-arthur",
182+
"metadata": {},
183+
"source": [
184+
"## Import Format\n",
185+
"\n",
186+
"* [Documentation](https://docs.labelbox.com/docs/bounding-box-json)\n",
187+
"\n",
188+
"\n",
189+
"```\n",
190+
"Each row of the import is a unique instance\n",
191+
"\n",
192+
"schemaId: <featureSchemaId>\n",
193+
"dataRow:\n",
194+
" id: <dataRowId>\n",
195+
"Instance:\n",
196+
" [Segments]:\n",
197+
" [KeyFrames]:\n",
198+
" frame:\n",
199+
" bbox:\n",
200+
" top:\n",
201+
" bottom:\n",
202+
" height:\n",
203+
" width:\n",
204+
"```\n",
205+
"\n",
206+
"**segments**: A segment represents a continuous section where an object is visible. If an instance disappears then the segment ends. If it re-appears, a new segment is created.\n",
207+
"\n",
208+
"**keyframes**: Key frames identify the location of an instance. Between keyframes, the location of the instance is interpolated.\n",
209+
"\n",
210+
"**bbox**: The coordinates of the bounding box"
211+
]
212+
},
213+
{
214+
"cell_type": "code",
215+
"execution_count": 11,
216+
"id": "5fc417c5",
217+
"metadata": {},
218+
"outputs": [],
219+
"source": [
220+
"segments = [\n",
221+
" {\n",
222+
" \"keyframes\": [\n",
223+
" {\n",
224+
" \"frame\": 1,\n",
225+
" \"bbox\": {\n",
226+
" \"top\": 80,\n",
227+
" \"left\": 80,\n",
228+
" \"height\": 80,\n",
229+
" \"width\": 80\n",
230+
" }\n",
231+
" },\n",
232+
" {\n",
233+
" \"frame\": 20,\n",
234+
" \"bbox\": {\n",
235+
" \"top\": 125,\n",
236+
" \"left\": 125,\n",
237+
" \"height\": 200,\n",
238+
" \"width\": 300\n",
239+
" }\n",
240+
" }\n",
241+
" ]\n",
242+
" },\n",
243+
" {\n",
244+
" \"keyframes\": [\n",
245+
" {\n",
246+
" \"frame\": 27,\n",
247+
" \"bbox\": {\n",
248+
" \"top\": 80,\n",
249+
" \"left\": 50,\n",
250+
" \"height\": 80,\n",
251+
" \"width\": 50\n",
252+
" }\n",
253+
" }\n",
254+
" ]\n",
255+
" }\n",
256+
"]"
257+
]
258+
},
259+
{
260+
"cell_type": "markdown",
261+
"id": "convertible-entry",
262+
"metadata": {},
263+
"source": [
264+
"##### Create helper functions to make this much easier"
265+
]
266+
},
267+
{
268+
"cell_type": "code",
269+
"execution_count": 12,
270+
"id": "developing-beauty",
271+
"metadata": {},
272+
"outputs": [],
273+
"source": [
274+
"def create_video_bbox_ndjson(datarow_id: str, schema_id: str, segments: Dict[str, Any]) -> Dict[str, Any]:\n",
275+
" return {\n",
276+
" \"uuid\": str(uuid.uuid4()),\n",
277+
" \"schemaId\": schema_id,\n",
278+
" \"dataRow\": {\"id\": datarow_id},\n",
279+
" \"segments\": segments\n",
280+
" }"
281+
]
282+
},
283+
{
284+
"cell_type": "code",
285+
"execution_count": 13,
286+
"id": "asian-savings",
287+
"metadata": {},
288+
"outputs": [],
289+
"source": [
290+
"uploads = []\n",
291+
"\n",
292+
"for data_row in dataset.data_rows():\n",
293+
" uploads.append(create_video_bbox_ndjson(data_row.uid, schema_lookup['jellyfish'], segments))"
294+
]
295+
},
296+
{
297+
"cell_type": "markdown",
298+
"id": "perfect-seafood",
299+
"metadata": {},
300+
"source": [
301+
"### Upload the annotations"
302+
]
303+
},
304+
{
305+
"cell_type": "code",
306+
"execution_count": 14,
307+
"id": "entire-community",
308+
"metadata": {},
309+
"outputs": [],
310+
"source": [
311+
"# Let's upload!\n",
312+
"# Validate must be set to false for video bounding boxes\n",
313+
"upload_task = project.upload_annotations(name=f\"upload-job-{uuid.uuid4()}\",\n",
314+
" annotations=uploads,\n",
315+
" validate=False)"
316+
]
317+
},
318+
{
319+
"cell_type": "code",
320+
"execution_count": 15,
321+
"id": "hollywood-faculty",
322+
"metadata": {},
323+
"outputs": [
324+
{
325+
"name": "stdout",
326+
"output_type": "stream",
327+
"text": [
328+
"[]\n"
329+
]
330+
}
331+
],
332+
"source": [
333+
"# Wait for upload to finish (Will take up to five minutes)\n",
334+
"upload_task.wait_until_done()\n",
335+
"# Review the upload status\n",
336+
"print(upload_task.errors)"
337+
]
338+
}
339+
],
340+
"metadata": {
341+
"kernelspec": {
342+
"display_name": "Python 3 (ipykernel)",
343+
"language": "python",
344+
"name": "python3"
345+
},
346+
"language_info": {
347+
"codemirror_mode": {
348+
"name": "ipython",
349+
"version": 3
350+
},
351+
"file_extension": ".py",
352+
"mimetype": "text/x-python",
353+
"name": "python",
354+
"nbconvert_exporter": "python",
355+
"pygments_lexer": "ipython3",
356+
"version": "3.8.2"
357+
}
358+
},
359+
"nbformat": 4,
360+
"nbformat_minor": 5
361+
}

0 commit comments

Comments
 (0)