diff --git a/codelabs/flex_and_vision/README.md b/codelabs/flex_and_vision/README.md new file mode 100644 index 00000000000..526680972db --- /dev/null +++ b/codelabs/flex_and_vision/README.md @@ -0,0 +1,106 @@ +# Python Google Cloud Vision sample for Google App Engine Flexible Environment + +This sample demonstrates how to use the [Google Cloud Vision API](https://cloud.google.com/vision/), [Google Cloud Storage](https://cloud.google.com/storage/), and [Google Cloud Datastore](https://cloud.google.com/datastore/) on [Google App Engine Flexible Environment](https://cloud.google.com/appengine). + +## Setup + +Create a new project with the [Google Cloud Platform console](https://console.cloud.google.com/). +Make a note of your project ID, which may be different than your project name. + +Make sure to [Enable Billing](https://pantheon.corp.google.com/billing?debugUI=DEVELOPERS) +for your project. + +Download the [Google Cloud SDK](https://cloud.google.com/sdk/docs/) to your +local machine. Alternatively, you could use the [Cloud Shell](https://cloud.google.com/shell/docs/quickstart), which comes with the Google Cloud SDK pre-installed. + +Initialize the Google Cloud SDK (skip if using Cloud Shell): + + gcloud init + +Create your App Engine application: + + gcloud app create + +Set an environment variable for your project ID, replacing `[YOUR_PROJECT_ID]` +with your project ID: + + export PROJECT_ID=[YOUR_PROJECT_ID] + +## Getting the sample code + +Run the following command to clone the Github repository: + + git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git + +Change directory to the sample code location: + + cd python-docs-samples/codelabs/flex_and_vision + +## Authentication + +Enable the APIs: + + gcloud service-management enable vision.googleapis.com + gcloud service-management enable storage-component.googleapis.com + gcloud service-management enable datastore.googleapis.com + +Create a Service Account to access the Google Cloud APIs when testing locally: + + gcloud iam service-accounts create hackathon \ + --display-name "My Hackathon Service Account" + +Give your newly created Service Account appropriate permissions: + + gcloud projects add-iam-policy-binding ${PROJECT_ID} \ + --member serviceAccount:hackathon@${PROJECT_ID}.iam.gserviceaccount.com \ + --role roles/owner + +After creating your Service Account, create a Service Account key: + + gcloud iam service-accounts keys create ~/key.json --iam-account \ + hackathon@${PROJECT_ID}.iam.gserviceaccount.com + +Set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable to point to where +you just put your Service Account key: + + export GOOGLE_APPLICATION_CREDENTIALS="/home/${USER}/key.json" + +## Running locally + +Create a virtual environment and install dependencies: + + virtualenv -p python3 env + source env/bin/activate + pip install -r requirements.txt + +Create a Cloud Storage bucket. It is recommended that you name it the same as +your project ID: + + gsutil mb gs://${PROJECT_ID} + +Set the environment variable `CLOUD_STORAGE_BUCKET`: + + export CLOUD_STORAGE_BUCKET=${PROJECT_ID} + +Start your application locally: + + python main.py + +Visit `localhost:8080` to view your application running locally. Press `Control-C` +on your command line when you are finished. + +When you are ready to leave your virtual environment: + + deactivate + +## Deploying to App Engine + +Open `app.yaml` and replace with the name of your +Cloud Storage bucket. + +Deploy your application to App Engine using `gcloud`. Please note that this may +take several minutes. + + gcloud app deploy + +Visit `https://[YOUR_PROJECT_ID].appspot.com` to view your deployed application. diff --git a/codelabs/flex_and_vision/app.yaml b/codelabs/flex_and_vision/app.yaml new file mode 100644 index 00000000000..5a2efe3ed5d --- /dev/null +++ b/codelabs/flex_and_vision/app.yaml @@ -0,0 +1,9 @@ +runtime: python +env: flex +entrypoint: gunicorn -b :$PORT main:app + +runtime_config: + python_version: 3 + +env_variables: + CLOUD_STORAGE_BUCKET: diff --git a/codelabs/flex_and_vision/main.py b/codelabs/flex_and_vision/main.py new file mode 100644 index 00000000000..3425b120166 --- /dev/null +++ b/codelabs/flex_and_vision/main.py @@ -0,0 +1,128 @@ +# Copyright 2017 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# [START app] +from datetime import datetime +import logging +import os + +from flask import Flask, redirect, render_template, request + +from google.cloud import datastore +from google.cloud import storage +from google.cloud import vision + + +CLOUD_STORAGE_BUCKET = os.environ.get('CLOUD_STORAGE_BUCKET') + + +app = Flask(__name__) + + +@app.route('/') +def homepage(): + # Create a Cloud Datastore client. + datastore_client = datastore.Client() + + # Use the Cloud Datastore client to fetch information from Datastore about + # each photo. + query = datastore_client.query(kind='Faces') + image_entities = list(query.fetch()) + + # Return a Jinja2 HTML template and pass in image_entities as a parameter. + return render_template('homepage.html', image_entities=image_entities) + + +@app.route('/upload_photo', methods=['GET', 'POST']) +def upload_photo(): + photo = request.files['file'] + + # Create a Cloud Storage client. + storage_client = storage.Client() + + # Get the bucket that the file will be uploaded to. + bucket = storage_client.get_bucket(CLOUD_STORAGE_BUCKET) + + # Create a new blob and upload the file's content. + blob = bucket.blob(photo.filename) + blob.upload_from_string( + photo.read(), content_type=photo.content_type) + + # Make the blob publicly viewable. + blob.make_public() + + # Create a Cloud Vision client. + vision_client = vision.Client() + + # Use the Cloud Vision client to detect a face for our image. + source_uri = 'gs://{}/{}'.format(CLOUD_STORAGE_BUCKET, blob.name) + image = vision_client.image(source_uri=source_uri) + faces = image.detect_faces(limit=1) + + # If a face is detected, save to Datastore the likelihood that the face + # displays 'joy,' as determined by Google's Machine Learning algorithm. + if len(faces) > 0: + face = faces[0] + + # Convert the face.emotions.joy enum type to a string, which will be + # something like 'Likelihood.VERY_LIKELY'. Parse that string by the + # period to extract only the 'VERY_LIKELY' portion. + face_joy = str(face.emotions.joy).split('.')[1] + else: + face_joy = 'Unknown' + + # Create a Cloud Datastore client. + datastore_client = datastore.Client() + + # Fetch the current date / time. + current_datetime = datetime.now() + + # The kind for the new entity. + kind = 'Faces' + + # The name/ID for the new entity. + name = blob.name + + # Create the Cloud Datastore key for the new entity. + key = datastore_client.key(kind, name) + + # Construct the new entity using the key. Set dictionary values for entity + # keys blob_name, storage_public_url, timestamp, and joy. + entity = datastore.Entity(key) + entity['blob_name'] = blob.name + entity['image_public_url'] = blob.public_url + entity['timestamp'] = current_datetime + entity['joy'] = face_joy + + # Save the new entity to Datastore. + datastore_client.put(entity) + + # Redirect to the home page. + return redirect('/') + + +@app.errorhandler(500) +def server_error(e): + logging.exception('An error occurred during a request.') + return """ + An internal error occurred:
{}
+ See logs for full stacktrace. + """.format(e), 500 + + +if __name__ == '__main__': + # This is used when running locally. Gunicorn is used to run the + # application on Google App Engine. See entrypoint in app.yaml. + app.run(host='127.0.0.1', port=8080, debug=True) +# [END app] diff --git a/codelabs/flex_and_vision/requirements.txt b/codelabs/flex_and_vision/requirements.txt new file mode 100644 index 00000000000..27bde93a4a6 --- /dev/null +++ b/codelabs/flex_and_vision/requirements.txt @@ -0,0 +1,5 @@ +Flask==0.12 +gunicorn==19.6.0 +google-cloud-vision==0.22.0 +google-cloud-storage==0.22.0 +google-cloud-datastore==0.22.0 diff --git a/codelabs/flex_and_vision/templates/homepage.html b/codelabs/flex_and_vision/templates/homepage.html new file mode 100644 index 00000000000..5e36e051ef7 --- /dev/null +++ b/codelabs/flex_and_vision/templates/homepage.html @@ -0,0 +1,20 @@ +

Google Cloud Platform - Face Detection Sample

+ +

This Python Flask application demonstrates App Engine Flexible, Google Cloud +Storage, Datastore, and the Cloud Vision API.

+ +
+ + + +
+ Upload File:
+ +
+ {% for image_entity in image_entities %} + +

{{image_entity['blob_name']}} was uploaded {{image_entity['timestamp']}}.

+

Joy Likelihood for Face: {{image_entity['joy']}}

+ {% endfor %} + +