diff --git a/slate/examples/process_images.py b/slate/examples/process_images.py index 64ac22a0..a2692e42 100644 --- a/slate/examples/process_images.py +++ b/slate/examples/process_images.py @@ -6,56 +6,92 @@ https://mozilla.org/MPL/2.0/. ''' # How to authenticate and process drone images using WebODM -import requests, sys, os, glob, json +import requests, sys, os, glob, json, time +import status_codes if len(sys.argv) < 2: - print("Usage: ./{} ".format(sys.argv[0])) - sys.exit(1) + 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))) + 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) + print("Need at least 2 images") + sys.exit(1) else: - print("Found {} images".format(len(images_list))) + print("Found {} images".format(len(images_list))) res = requests.post('http://localhost:8000/api/token-auth/', - data={'username': 'admin', - 'password': 'admin'}).json() + data={'username': 'admin', + 'password': 'admin'}).json() if 'token' in res: - print("Logged-in!") - token = res['token'] + print("Logged-in!") + token = res['token'] - res = requests.post('http://localhost:8000/api/projects/', - headers={'Authorization': 'JWT {}'.format(token)}, - data={'name': 'Hello WebODM!'}).json() - if 'id' in res: - print("Created project: {}".format(res)) - project_id = res['id'] + res = requests.post('http://localhost:8000/api/projects/', + headers={'Authorization': 'JWT {}'.format(token)}, + data={'name': 'Hello WebODM!'}).json() + 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() + 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'] + print("Created task: {}".format(res)) + task_id = res['id'] - - else: - print("Cannot create project: {}".format(res)) + while True: + time.sleep(3) + res = requests.get('http://localhost:8000/api/projects/{}/tasks/{}/'.format(project_id, task_id), + headers={'Authorization': 'JWT {}'.format(token)}).json() + + if res['status'] == status_codes.COMPLETED: + print("Task has completed!") + break + elif res['status'] == status_codes.FAILED: + print("Task failed: {}".format(res)) + print("Cleaning up...") + requests.delete("http://localhost:8000/api/projects/{}/".format(project_id), + headers={'Authorization': 'JWT {}'.format(token)}) + sys.exit(1) + else: + seconds = res['processing_time'] / 1000 + if seconds < 0: + seconds = 0 + m, s = divmod(seconds, 60) + h, m = divmod(m, 60) + sys.stdout.write("\rProcessing... [%02d:%02d:%02d]" % (h, m, s)) + sys.stdout.flush() + + res = requests.get("http://localhost:8000/api/projects/{}/tasks/{}/download/geotiff/".format(project_id, task_id), + headers={'Authorization': 'JWT {}'.format(token)}, + stream=True) + with open("orthophoto.tif", 'wb') as f: + for chunk in res.iter_content(chunk_size=1024): + if chunk: + f.write(chunk) + + print("Saved ./orthophoto.tif") + + print("Cleaning up...") + requests.delete("http://localhost:8000/api/projects/{}/".format(project_id), + headers={'Authorization': 'JWT {}'.format(token)}) + else: + print("Cannot create project: {}".format(res)) else: - print("Invalid credentials!") + print("Invalid credentials!") diff --git a/slate/examples/status_codes.py b/slate/examples/status_codes.py new file mode 100644 index 00000000..71867326 --- /dev/null +++ b/slate/examples/status_codes.py @@ -0,0 +1,5 @@ +QUEUED = 10 +RUNNING = 20 +FAILED = 30 +COMPLETED = 40 +CANCELED = 50 diff --git a/slate/source/includes/_quickstart.md b/slate/source/includes/_quickstart.md index bdd5fa2b..4bc7efe2 100644 --- a/slate/source/includes/_quickstart.md +++ b/slate/source/includes/_quickstart.md @@ -65,4 +65,37 @@ 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. +
+```python +while True: + res = requests.get('http://localhost:8000/api/projects/{}/tasks/{}/'.format(project_id, task_id), + headers={'Authorization': 'JWT {}'.format(token)}).json() + + if res['status'] == status_codes.COMPLETED: + print("Task has completed!") + break + elif res['status'] == status_codes.FAILED: + print("Task failed: {}".format(res)) + sys.exit(1) + else: + print("Processing, hold on...") + time.sleep(3) +``` + +We periodically check for the Task status using a loop. +
+ +```python +res = requests.get("http://localhost:8000/api/projects/{}/tasks/{}/download/geotiff/".format(project_id, task_id), + headers={'Authorization': 'JWT {}'.format(token)}, + stream=True) + with open("orthophoto.tif", 'wb') as f: + for chunk in res.iter_content(chunk_size=1024): + if chunk: + f.write(chunk) +``` + +Our orthophoto is ready to be downloaded. A variety of other assets, including a dense 3D point cloud and a textured model is also available. + +A TMS layer is also made available at `http://localhost:8000/api/projects/{project_id}/tasks/{task_id}/tiles.json` for inclusion in programs such as Leaflet or Cesium.