diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..9df3bff --- /dev/null +++ b/Procfile @@ -0,0 +1,3 @@ +web: gunicorn cat_or_not +heroku ps:scale web=1 +export GOOGLE_APPLICATION_CREDENTIALS="authentication.json" diff --git a/README.md b/README.md index 6c9d621..56dd934 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Cat or Not - artifact repository +# First prototype ### Monday 15:30 group ## How to use this repository? @@ -8,3 +9,6 @@ In case of an artifact not passing a quality control, person responsible will be ## Version Control Document It is located in a [repository's wiki](https://git.wmi.amu.edu.pl/s434650/CatOrNot/wiki/Version+History+Document). It will be updated with each accepted artifact. + +## Heroku application +https://lit-wildwood-10245.herokuapp.com/ diff --git a/__pycache__/cat_or_not.cpython-36.pyc b/__pycache__/cat_or_not.cpython-36.pyc new file mode 100644 index 0000000..63f3e4d Binary files /dev/null and b/__pycache__/cat_or_not.cpython-36.pyc differ diff --git a/__pycache__/cat_recognition.cpython-36.pyc b/__pycache__/cat_recognition.cpython-36.pyc new file mode 100644 index 0000000..5f0382d Binary files /dev/null and b/__pycache__/cat_recognition.cpython-36.pyc differ diff --git a/__pycache__/config.cpython-36.pyc b/__pycache__/config.cpython-36.pyc new file mode 100644 index 0000000..442ed48 Binary files /dev/null and b/__pycache__/config.cpython-36.pyc differ diff --git a/__pycache__/forms.cpython-36.pyc b/__pycache__/forms.cpython-36.pyc new file mode 100644 index 0000000..18070b2 Binary files /dev/null and b/__pycache__/forms.cpython-36.pyc differ diff --git a/__pycache__/hello.cpython-36.pyc b/__pycache__/hello.cpython-36.pyc new file mode 100644 index 0000000..47f8c9f Binary files /dev/null and b/__pycache__/hello.cpython-36.pyc differ diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..f5b34f4 --- /dev/null +++ b/app/__init__.py @@ -0,0 +1,7 @@ +from flask import Flask +from config import Config + +app = Flask(__name__) +app.config.from_object(Config) + +from app import routes diff --git a/app/__pycache__/__init__.cpython-36.pyc b/app/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000..10c727a Binary files /dev/null and b/app/__pycache__/__init__.cpython-36.pyc differ diff --git a/app/__pycache__/cat_recognition.cpython-36.pyc b/app/__pycache__/cat_recognition.cpython-36.pyc new file mode 100644 index 0000000..9289b2a Binary files /dev/null and b/app/__pycache__/cat_recognition.cpython-36.pyc differ diff --git a/app/__pycache__/forms.cpython-36.pyc b/app/__pycache__/forms.cpython-36.pyc new file mode 100644 index 0000000..8e14a92 Binary files /dev/null and b/app/__pycache__/forms.cpython-36.pyc differ diff --git a/app/__pycache__/picture_downloader.cpython-36.pyc b/app/__pycache__/picture_downloader.cpython-36.pyc new file mode 100644 index 0000000..1fd1e52 Binary files /dev/null and b/app/__pycache__/picture_downloader.cpython-36.pyc differ diff --git a/app/__pycache__/routes.cpython-36.pyc b/app/__pycache__/routes.cpython-36.pyc new file mode 100644 index 0000000..32d5883 Binary files /dev/null and b/app/__pycache__/routes.cpython-36.pyc differ diff --git a/app/cat_recognition.py b/app/cat_recognition.py new file mode 100644 index 0000000..b65d418 --- /dev/null +++ b/app/cat_recognition.py @@ -0,0 +1,20 @@ +# Imports the Google Cloud client library +from google.cloud import vision +from google.cloud.vision import types + +def is_cat(content): + labels = fetch_data(content) + if labels[0].description == "cat": + return True + else: + return False + +def fetch_data(content): + # Instantiates a client + client = vision.ImageAnnotatorClient() + # Tell Google Vision that our content is of type Image + image = types.Image(content=content) + # Performs label detection on the image file + response = client.label_detection(image=image) + # Return array of labels + return response.label_annotations diff --git a/app/forms.py b/app/forms.py new file mode 100644 index 0000000..ab65d4c --- /dev/null +++ b/app/forms.py @@ -0,0 +1,7 @@ +from flask_wtf import FlaskForm +from wtforms import StringField, PasswordField, BooleanField, SubmitField +from wtforms.validators import DataRequired + +class UploadForm(FlaskForm): + url = StringField('Link', validators=[DataRequired()]) + submit = SubmitField('Cat or not?') diff --git a/app/picture_downloader.py b/app/picture_downloader.py new file mode 100644 index 0000000..3304f35 --- /dev/null +++ b/app/picture_downloader.py @@ -0,0 +1,10 @@ +import requests + +def get_image_from_url(url): + f = open('pic.jpg','wb') + f.write(requests.get(url).content) + f.close() + f = open('pic.jpg','rb') + file = f.read() + f.close() + return file diff --git a/app/routes.py b/app/routes.py new file mode 100644 index 0000000..feedcbd --- /dev/null +++ b/app/routes.py @@ -0,0 +1,18 @@ +from flask import Flask +from flask import render_template +from app.forms import UploadForm +from app import app +from app import cat_recognition as cat +from app import picture_downloader as downloader + +@app.route('/', methods=['GET', 'POST']) +def index(): + form = UploadForm() + if form.validate_on_submit(): + content = downloader.get_image_from_url(form.url.data) + if cat.is_cat(content): + return "Cat!" + else: + return "Not!" + + return render_template('index.html', form=form) diff --git a/app/templates/base.html b/app/templates/base.html new file mode 100644 index 0000000..519c49c --- /dev/null +++ b/app/templates/base.html @@ -0,0 +1,23 @@ + + + + {% if title %} + {{ title }} | Cat or Not + {% else %} + Cat or Not + {% endif %} + + + + {% with messages = get_flashed_messages() %} + {% if messages %} + + {% endif %} + {% endwith %} + {% block content %}{% endblock %} + + diff --git a/app/templates/index.html b/app/templates/index.html new file mode 100644 index 0000000..18c65da --- /dev/null +++ b/app/templates/index.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} + +{% block content %} +

Check if the picture is cat or not!

+
+ {{ form.hidden_tag() }} +

+ {{ form.url.label }}
+ {{ form.url }} +

+

{{ form.submit() }}

+
+{% endblock %} diff --git a/authentication.json b/authentication.json new file mode 100644 index 0000000..c2beba1 --- /dev/null +++ b/authentication.json @@ -0,0 +1,12 @@ +{ + "type": "service_account", + "project_id": "quiet-odyssey-225116", + "private_key_id": "f2553a958e511debcf46d10957e3c7fbdb906aa1", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDfmChqO8VSfmEi\nSNeGhgq3jCe5iCk67yoaatQ9kYd10pmVST6OjJ3nmxd1iYAAYCB59wV4V19C67oj\n5x0bxhhKITilS94bNhZJFB4FjwMIGrDXe9SGcZwSwrB+ggFhvZGNQjYWDe7rrJ/V\nXemA8kO/wfVYUgHsjWXm3VKEeP4G0j8mndA+PP2T/aJNIWok5IA/emqr305YNMvd\n+C8TB6htf4Pqe1ZDHNyrGzYKUy1KbMAdtBXgmpVCKeo4XdlV1s0y7tVnCN+4MUM5\nVAP1fD9985fh84Zw+nMt6//pxGORwnvTNDjPjPwqEwQbV02YcfYMKPjXWSDFxv+v\nOqDUwAsjAgMBAAECggEAaQNRl/NSjZgFjtCfSPMTfXk5/w1QL/m70IR0AiajdFbh\nAxhPZSvtzaUts2pMz+BV4HKAAzEl8Iw99DbLmQvExKwtqpSjUCxq8w+bugic5+WB\nQPNLsYkSQE1oD0KH25vpDGsYc+s/VzjQKKnezUz7PMifrkd119/hCDjSVJ1u0Ux0\nit7ZsoLFzWWorC1CVUPHMqUtlgF8L85w4Yfma7X64yoPNvomI4MFV8E9UfUoZBY0\n02x8mBNX9fjIHzNXkyF6OD8O1IMkrADaJbdmcfgMwBWtarIEsNIiUQsFnFeaN69b\nf26NTQQux9jgMJnMu9V1TNdG6K6TshIw8a/uB4lmYQKBgQD8AUg0Qu9tS8Y4AQfq\nd/0frLIitmnzVs0Lt3TFIw1OjUrfki5gStAEVGhIN2SXLF6lWjqrtk43xQFjzuKr\nL9kuN76MbYDnITuew+9VJPnmA2EiTspcVPNph44FqPSNOar9GCCY7QB6ue+fm5bq\nFyPaHfoKuRmwbvHqVgI2L2HJbQKBgQDjI5OEWYxfJLC6StpEmmOY8W19ZQPTXBKt\nfLSEsDuAjrC2kT6ladXezYuYy/VSAbjdCYbJ1yDABNILDZky0ZSD2midtnqe3z0v\nTKBudkxEDYgRKvgQxMY89N6JpSOedY3v63cOvRwPbVi4sF+REbRu4e+OVsIlpXaK\n/IcINZdczwKBgQCNl87RBnbuqy+xkeq3tDl2DZt9Y47+WdwV5Dto9LvqUfsqyUDj\ne8WLWT3Krc0IH7cCI0Np7aHfNgME6F51nwnhLRMUZgaSVxrfpumXppH+yhFOrISJ\nAnZN6gtDZN4bZ7aKRH80TZ4CVuyrekl+OAg96q/uTHiBqKSmbTMK7O59tQKBgCMD\n3f7eKySTrGbbmTBQOKBgP4fAJcnUfNCf09hMrq+Pz7AlTeoEGcNCHo4MiyH8P/pb\nOJsu/c58L8EidIaABowZBF2jvt10/qKnBmhg9jrbdylmXV2AaCsHeLLxcT9BUgM1\nYmI0Rvod2jqGfgUIHK+nRt3DhCR3kIG2kj5yvIXDAoGAVNd8sw08+U4JMg0TPK71\nhWNeXyNc9aLpehqdIVQPs6KdhlVcoFHKLCDASzMUxNtU27b3Nqgh5dBS4YbNKXoa\n5UZUvxa2Khw1/rT9wTcaIap0kfh1SOZseSfpNUy5mrSKnnVkIn1NKmI0a+mN0gcT\nD706pAo2V7oFEQFocuua1yY=\n-----END PRIVATE KEY-----\n", + "client_email": "c00lerxo@quiet-odyssey-225116.iam.gserviceaccount.com", + "client_id": "106421721962581253770", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/c00lerxo%40quiet-odyssey-225116.iam.gserviceaccount.com" +} diff --git a/cat_or_not.py b/cat_or_not.py new file mode 100644 index 0000000..e13c02e --- /dev/null +++ b/cat_or_not.py @@ -0,0 +1 @@ +from app import app as application diff --git a/config.py b/config.py new file mode 100644 index 0000000..5bf854f --- /dev/null +++ b/config.py @@ -0,0 +1,4 @@ +import os + +class Config(object): + SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess' diff --git a/pic.jpg b/pic.jpg new file mode 100644 index 0000000..773ae83 Binary files /dev/null and b/pic.jpg differ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..c6c1951 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,26 @@ +cachetools==3.0.0 +certifi==2018.11.29 +chardet==3.0.4 +Click==7.0 +Flask==1.0.2 +Flask-WTF==0.14.2 +google-api-core==1.6.0 +google-auth==1.6.1 +google-cloud-vision==0.35.1 +googleapis-common-protos==1.5.5 +grpcio==1.17.0 +gunicorn==19.9.0 +idna==2.8 +itsdangerous==1.1.0 +Jinja2==2.10 +MarkupSafe==1.1.0 +protobuf==3.6.1 +pyasn1==0.4.4 +pyasn1-modules==0.2.2 +pytz==2018.7 +requests==2.21.0 +rsa==4.0 +six==1.12.0 +urllib3==1.24.1 +Werkzeug==0.14.1 +WTForms==2.2.1