From a992fea83dad7a40c6999bb41f6b055f25ec9fc0 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Thu, 16 Feb 2017 18:37:27 -0500 Subject: [PATCH] Expanded docs, examples, modified API to return full Task object definition instead of just ID --- app/api/tasks.py | 4 +-- app/urls.py | 2 +- slate/examples/process_images.py | 36 ++++++++++++++++++++++- slate/source/includes/_quickstart.md | 43 +++++++++++++++++++++++----- 4 files changed, 73 insertions(+), 12 deletions(-) diff --git a/app/api/tasks.py b/app/api/tasks.py index 34d98577..410086b2 100644 --- a/app/api/tasks.py +++ b/app/api/tasks.py @@ -136,10 +136,8 @@ class TaskViewSet(viewsets.ViewSet): serializer.is_valid(raise_exception=True) serializer.save() - return Response({"id": task.id}, status=status.HTTP_201_CREATED) + return Response(serializer.data, status=status.HTTP_201_CREATED) - # on transaction fail - raise exceptions.ValidationError(detail="Cannot create task, input provided is not valid.") def update(self, request, pk=None, project_pk=None, partial=False): get_and_check_project(request, project_pk, ('change_project', )) diff --git a/app/urls.py b/app/urls.py index 2634fb01..26fe5eb2 100644 --- a/app/urls.py +++ b/app/urls.py @@ -15,7 +15,7 @@ urlpatterns = [ url(r'^processingnode/([\d]+)/$', views.processing_node, name='processing_node'), url(r'^api/', include("app.api.urls")), - url(r'^apiviewer/', get_swagger_view(title='WebODM API')) + url(r'^apiviewer/', get_swagger_view(title='WebODM API')), ] # Test cases call boot() independently diff --git a/slate/examples/process_images.py b/slate/examples/process_images.py index 36a4fd45..64ac22a0 100644 --- a/slate/examples/process_images.py +++ b/slate/examples/process_images.py @@ -6,10 +6,27 @@ https://mozilla.org/MPL/2.0/. ''' # How to authenticate and process drone images using WebODM -import requests +import requests, sys, os, glob, json + +if len(sys.argv) < 2: + print("Usage: ./{} ".format(sys.argv[0])) + sys.exit(1) + +types = ("*.jpg", "*.jpeg", "*.JPG", "*.JPEG") +images_list = [] +for t in types: + images_list.extend(glob.glob(os.path.join(sys.argv[1], t))) + +if len(images_list) < 1: + print("Need at least 2 images") + sys.exit(1) +else: + print("Found {} images".format(len(images_list))) + res = requests.post('http://localhost:8000/api/token-auth/', data={'username': 'admin', 'password': 'admin'}).json() + if 'token' in res: print("Logged-in!") token = res['token'] @@ -20,6 +37,23 @@ if 'token' in res: if 'id' in res: print("Created project: {}".format(res)) project_id = res['id'] + + images = [('images', (os.path.basename(file), open(file, 'rb'), 'image/jpg')) for file in images_list] + options = json.dumps([ + {'name': "use-opensfm-pointcloud", 'value': True}, + {'name': "orthophoto-resolution", 'value': 24}, + ]) + res = requests.post('http://localhost:8000/api/projects/{}/tasks/'.format(project_id), + headers={'Authorization': 'JWT {}'.format(token)}, + files=images, + data={ + 'options': options + }).json() + + print("Created task: {}".format(res)) + task_id = res['id'] + + else: print("Cannot create project: {}".format(res)) else: diff --git a/slate/source/includes/_quickstart.md b/slate/source/includes/_quickstart.md index d970717b..bdd5fa2b 100644 --- a/slate/source/includes/_quickstart.md +++ b/slate/source/includes/_quickstart.md @@ -17,23 +17,52 @@ $ pip install requests + + ```python import requests res = requests.post('http://localhost:8000/api/token-auth/', data={'username': 'admin', 'password': 'admin'}).json() +token = res['token'] ``` First, we authenticate with WebODM. A `token` is returned when authentication is successful.
```python -if 'token' in res: - token = res['token'] - res = requests.post('http://localhost:8000/api/projects/', - headers={'Authorization': 'JWT {}'.format(token)}, - data={'name': 'Hello WebODM!'}).json() +res = requests.post('http://localhost:8000/api/projects/', + headers={'Authorization': 'JWT {}'.format(token)}, + data={'name': 'Hello WebODM!'}).json() +project_id = res['id'] ``` -Then we need to create a Project. We pass our `token` via the `Authorization` header. If we forget to pass this header, the system will not authenticate us and will refuse to process the request. `name` is the name we assign to the project. -
\ No newline at end of file +Then we need to create a Project. We pass our `token` via the `Authorization` header. If we forget to pass this header, the system will not authenticate us and will refuse to process the request. We assign a `name` to the project. +
+ +```python +images = [ + ('images', ('image1.jpg', open('image1.jpg', 'rb'), 'image/jpg')), + ('images', ('image2.jpg', open('image2.jpg', 'rb'), 'image/jpg')), + # ... +] +options = json.dumps([ + {'name': "use-opensfm-pointcloud", 'value': True}, + {'name': "orthophoto-resolution", 'value': 24}, +]) + +res = requests.post('http://localhost:8000/api/projects/{}/tasks/'.format(project_id), + headers={'Authorization': 'JWT {}'.format(token)}, + files=images, + data={ + 'options': options + }).json() + +task_id = res['id'] +``` + +We can then create a Task. The only required parameter is a list of multiple, multipart-encoded `images`. Processing will start automatically +as soon as a Processing Node is available. It is possible to specify additional options by passing an `options` value, which is a JSON-encoded list of name/value pairs. Several other options are available. See the Task reference for more information. +