Skip to content

Commit

Permalink
i can’t get no satisfaction (#107)
Browse files Browse the repository at this point in the history
* i can’t get no satisfaction

* cleanboi

* hmm

* spicy

* cleanbois

* injecto the key

* addressing review comments

* derp

* comments, comments, comments, comments, comments

* yote

* yote2

* okok
  • Loading branch information
squishykid authored Nov 12, 2018
1 parent 511ac69 commit 4d5e7c5
Show file tree
Hide file tree
Showing 12 changed files with 496 additions and 167 deletions.
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ passlib = "*"
gunicorn = "*"
zappa = "*"
cognitive-face = "*"
pytest-mock = "*"

[requires]
python_version = "3.6"
99 changes: 54 additions & 45 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 18 additions & 39 deletions biz/css/emotion_recognition.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,20 @@
import cognitive_face as CF
import locale


class SatisfactionScore:
def __init__(self):
KEY = 'fcef05be3b9f440f9e38dfb675b07de6'
BASE = 'https://westcentralus.api.cognitive.microsoft.com/face/v1.0'
self._cognitive_face = CF
self._cognitive_face.Key.set(KEY)
self._cognitive_face.BaseUrl.set(BASE)

def detect_from_url(self, url):
return self.detect(url)

def detect_from_local_file(self, filepath):
# with open(filepath, "rb") as image:
# image_as_bytes = image.read()
locale.getdefaultlocale()

f = open(filepath, "rb")
image_as_bytes = f.read()
f.close()
"""
Adapter for the microsoft face recignition
return self.detect(image_as_bytes)
Author: David Niwczyk and Robin Wohlers-Reichel
Date: 11/11/2018
"""

def detect(self, image, face_id=True,
landmarks=False, attributes='emotion,glasses'):
return self._cognitive_face.face.detect(
image, face_id, landmarks, attributes
)


if __name__ == "__main__":
css = SatisfactionScore()

print(css.detect_from_url("""
https://raw.githubusercontent.com/Microsoft/
Cognitive-Face-Windows/master/Data/detection1.jpg"""))

# print(css.detect_from_local_file("face.jpg"))
import cognitive_face as CF
import config


def detect_from_url(url): # pragma: no cover
"""
Hit the CF api for the image at 'url'.
"""
KEY = config.cf_api_key()
BASE = 'https://westcentralus.api.cognitive.microsoft.com/face/v1.0'
CF.Key.set(KEY)
CF.BaseUrl.set(BASE)
return CF.face.detect(url, True, False, 'emotion,glasses')
4 changes: 4 additions & 0 deletions config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ def connection_string(): # pragma: no cover
def is_running_on_lambda():
root = os.environ.get("LAMBDA_TASK_ROOT", '')
return len(root) > 0


def cf_api_key(): # pragma: no cover
return os.environ.get("CF_API_KEY", 'fcef05be3b9f440f9e38dfb675b07de6')
138 changes: 121 additions & 17 deletions events/satisfaction_lambda.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,144 @@
"""
Lambda which converts images into css
Triggers on s3 bucket event
Upload the image to Azure
Put the CSS into the db
Author: Robin Wohlers-Reichel
Date: 11/11/2018
"""

import urllib.parse
import boto3
from biz.css.emotion_recognition import SatisfactionScore
from biz.css.reduction import apply_reduction
import biz.css.emotion_recognition as er
import biz.css.reduction as r
import biz.css.manage_satisfaction as ms
import biz.css.file_storage as fs
from psycopg2 import pool
import config

print('Loading function')
s3 = boto3.client('s3')
__pool = None


# second parameter is the context, but currently unused
def customer_satisfaction(event, _):
def get_pool_lazy(): # pragma: no cover
"""
Get a database pool, but in a way we can override for tests
"""
# pylint: disable=global-statement
global __pool
if __pool is None:
__pool = pool.ThreadedConnectionPool(1, 1, config.connection_string())
return __pool


def get_details(event):
"""
Get details of the event being passed into the lambda
:param event: Event object passed into the lambda
:return: Name of the bucket and key of file (filename)
"""
bucket = event['Records'][0]['s3']['bucket']['name']
key = urllib.parse.unquote_plus(
event['Records'][0]['s3']['object']['key'],
encoding='utf-8'
)
return (bucket, key)


def generate_url(s3client, bucket, key): # pragma: no cover
"""
Generate a short-lived public url for the specified key
:param s3client: AWS S3 client to use to generate url
:param bucket: The bucket the object resides in
:param key: The key of the object
:return: Public url to the object
"""
return s3client.generate_presigned_url(
ClientMethod='get_object',
ExpiresIn='60',
Params={
'Bucket': bucket,
'Key': key
}
)


def css_for_image_at_url(url):
"""
Calculate the css for an image at `url`
:param url: The url to use
:return: CSS score
"""
css = er.detect_from_url(url)
print("Cognitive Face Result: {}".format(css))
return r.apply_reduction(css)


def save_css(p, css, eid, rid):
"""
Save the CSS to the database
:param p: Database pool
:param css: CSS Score
:param eid: Event ID
:param rid: Reservation ID
"""
conn = p.getconn()
try:
ms.create_satisfaction(conn, css, eid, rid)
conn.commit()
except Exception as e:
conn.rollback()
raise e
finally:
p.putconn(conn)


url = s3.generate_presigned_url(
ClientMethod='get_object',
ExpiresIn='600',
Params={
'Bucket': bucket,
'Key': key
}
# second parameter is the context, but currently unused
def calculate_css_from_image(event, _):
"""
The lambda event handler entry point
:param event: Information about the trigger
"""
bucket, key = get_details(event)
eid = None
rid = None
try:
eid, rid = fs.deconstruct_filename(key)
except ValueError as e:
print(e)
print('Error deconstructing filename {} into \
event id and reservation id.'.format(key))
return dict(
event_id=eid,
reservation_id=rid,
css=None,
result='invalid_filename'
)

print('detecting from url:{}.'.format(url))
css = SatisfactionScore().detect_from_url(url)
print(css)
reduced = apply_reduction(css)
print(reduced)
print('Calculate CSS for Event={}, Reservation={}'.format(eid, rid))

return css
url = None
try:
url = generate_url(s3, bucket, key)
except Exception as e:
print(e)
print('Error getting object {} from bucket {}.\
Make sure they exist and your bucket is in the \
same region as this function.'.format(key, bucket))
raise e

reduced = css_for_image_at_url(url)
save_css(get_pool_lazy(), reduced, eid, rid)
return dict(
event_id=eid,
reservation_id=rid,
css=reduced,
result='success'
)
Loading

0 comments on commit 4d5e7c5

Please sign in to comment.