Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions codelabs/flex_and_vision/README.md
Original file line number Diff line number Diff line change
@@ -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 <your-cloud-storage-bucket> 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.
9 changes: 9 additions & 0 deletions codelabs/flex_and_vision/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app

runtime_config:
python_version: 3

env_variables:
CLOUD_STORAGE_BUCKET: <your-cloud-storage-bucket>
128 changes: 128 additions & 0 deletions codelabs/flex_and_vision/main.py
Original file line number Diff line number Diff line change
@@ -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: <pre>{}</pre>
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]
5 changes: 5 additions & 0 deletions codelabs/flex_and_vision/requirements.txt
Original file line number Diff line number Diff line change
@@ -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
20 changes: 20 additions & 0 deletions codelabs/flex_and_vision/templates/homepage.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<h1>Google Cloud Platform - Face Detection Sample</h1>

<p>This Python Flask application demonstrates App Engine Flexible, Google Cloud
Storage, Datastore, and the Cloud Vision API.</p>

<br>

<html>
<body>
<form action="upload_photo" method="POST" enctype="multipart/form-data">
Upload File: <input type="file" name="file"><br>
<input type="submit" name="submit" value="Submit">
</form>
{% for image_entity in image_entities %}
<img src="{{image_entity['image_public_url']}}" width=200 height=200>
<p>{{image_entity['blob_name']}} was uploaded {{image_entity['timestamp']}}.</p>
<p>Joy Likelihood for Face: {{image_entity['joy']}}</p>
{% endfor %}
</body>
</html>