generated from nyu-software-engineering/final-project
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from software-students-spring2024/Jacklyn22
Original codes added and new html pages added.
- Loading branch information
Showing
18 changed files
with
899 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
version: '3.8' | ||
|
||
services: | ||
web-app: | ||
build: | ||
context: ./web-app | ||
dockerfile: ./Dockerfile | ||
ports: | ||
- "10000:5000" | ||
env_file: | ||
- .env | ||
depends_on: | ||
- db | ||
|
||
machine-learning-client: | ||
build: | ||
context: ./machine-learning-client | ||
dockerfile: ./Dockerfile | ||
ports: | ||
- "5002:5002" | ||
env_file: | ||
- .env | ||
depends_on: | ||
- db | ||
|
||
|
||
db: | ||
image: mongo | ||
ports: | ||
- "27017:27017" | ||
volumes: | ||
- ./data:/data/db | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# in Docker, it is common to base a new image on a previously-created image | ||
# Use an official Python runtime image as a parent image to base this image on | ||
FROM python:3 | ||
# Set the working directory within the image to /app | ||
WORKDIR /main | ||
# the ADD command is how you add files from your local machine into a Docker image | ||
# Copy the current directory contents into the container at /app | ||
ADD . /main | ||
# Install any needed packages specified in requirements.txt | ||
# in Python, a requirements.txt file is a way of indicating dependencies in a way that the package manager, pip, can understand | ||
RUN pip install --trusted-host pypi.python.org -r requirements.txt | ||
# by default Docker containers are closed off to the external world | ||
# Make port 80 available to the world outside this container | ||
EXPOSE 5002 | ||
# Define an environment variable... this will be available to programs running inside the container | ||
ENV NAME World | ||
# Run app.py when the container launches | ||
CMD ["python", "main.py"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[[source]] | ||
url = "https://pypi.org/simple" | ||
verify_ssl = true | ||
name = "pypi" | ||
|
||
[packages] | ||
pylint = "*" | ||
black = "*" | ||
|
||
[dev-packages] | ||
|
||
[requires] | ||
python_version = "3.10" |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import os | ||
from flask import Flask, request, jsonify | ||
import requests | ||
import pymongo | ||
from pymongo import MongoClient | ||
import json | ||
from dotenv import load_dotenv | ||
from bson import ObjectId | ||
|
||
import logging | ||
|
||
logging.basicConfig(level=logging.DEBUG) | ||
logger = logging.getLogger(__name__) | ||
|
||
# Use receipt-OCR.py to get response1.json | ||
# (can only do this a couple times an hour with the test API key) | ||
|
||
# Load response1.json | ||
with open("response1.json", "r") as f: | ||
data = json.load(f) | ||
|
||
print('Receipt Keys:', data['receipts'][0].keys()) | ||
items = data['receipts'][0]['items'] | ||
print() | ||
print(f"Your purchase at {data['receipts'][0]['merchant_name']}") | ||
|
||
for item in items: | ||
print(f"{item['description']} - {data['receipts'][0]['currency']} {item['amount']}") | ||
print("-" * 20) | ||
print(f"Subtotal: {data['receipts'][0]['currency']} {data['receipts'][0]['subtotal']}") | ||
print(f"Tax: {data['receipts'][0]['currency']} {data['receipts'][0]['tax']}") | ||
print("-" * 20) | ||
print(f"Total: {data['receipts'][0]['currency']} {data['receipts'][0]['total']}") | ||
# print(data['receipts']) | ||
|
||
|
||
# load credentials and configuration options from .env file | ||
# if you do not yet have a file named .env, make one based on the templatpip e in env.example | ||
load_dotenv() # take environment variables from .env. | ||
|
||
# instantiate the app | ||
app = Flask(__name__) | ||
app.secret_key = 'a_unique_and_secret_key' | ||
# # turn on debugging if in development mode | ||
if os.getenv("FLASK_ENV", "development") == "development": | ||
# # turn on debugging, if in development | ||
app.debug = True # debug mnode | ||
|
||
# connect to the database | ||
cxn = pymongo.MongoClient(os.getenv("MONGO_URI")) | ||
db = cxn[os.getenv("MONGO_DBNAME")] # store a reference to the database | ||
|
||
@app.route('/predict', methods=['POST']) | ||
def pretdict_endpoint(): | ||
# Get the image data from the request | ||
request_data = request.get_json() # Extract JSON data from the request | ||
if 'Object_ID' not in request_data: | ||
return jsonify({'error': 'Object_ID not found in request data'}), 400 | ||
|
||
Object_ID = ObjectId(request_data['Object_ID']) | ||
logger.debug('OBJECT_ID MESSAGE:', Object_ID) | ||
#image = db.receipts.find_one({"_id": Object_ID})['image'] | ||
|
||
# Here, you would add the code to perform OCR on the image | ||
# For now, let's assume you have a function called perform_ocr that does this | ||
|
||
# Uncomment next line to perform OCR | ||
data = perform_ocr(Object_ID) | ||
#data = json.load(open("response1.json", "r")) | ||
|
||
# Connect to your collection (replace 'mycollection' with your collection name) | ||
collection = db['receipts'] | ||
|
||
# Prepare the data to be inserted into the database | ||
receipt = data['receipts'][0] | ||
receipt_data = { | ||
'receipt_name': receipt['merchant_name'], | ||
'currency': receipt['currency'], | ||
'items': [{'description': item['description'], 'amount': item['amount']} for item in receipt['items']], | ||
'total': receipt['total'], | ||
'tax': receipt['tax'], | ||
'tip': receipt['tip'], | ||
'subtotal': receipt['subtotal'], | ||
} | ||
logger.debug(receipt_data) | ||
|
||
# Update the document with given ObjectId | ||
collection.update_one({'_id': Object_ID}, {'$set': receipt_data}) | ||
inserted_id = Object_ID | ||
|
||
# Return the inserted_id as a JSON response | ||
return jsonify({'_id': str(inserted_id)}) | ||
|
||
def perform_ocr(Object_ID): | ||
logger.debug("starting perform_ocr function...") # debug | ||
url = "https://ocr.asprise.com/api/v1/receipt" | ||
image_data = db.receipts.find_one({"_id": Object_ID})['image'] | ||
file_path = f"receipt_{Object_ID}.jpg" # Set the file path to save the image | ||
logger.debug("file path: %s", file_path) # debug | ||
with open(file_path, "wb") as f: | ||
f.write(image_data) | ||
file_path = file_path.replace('\x00', '') # Remove any null bytes from the file path | ||
|
||
|
||
# Get response (can only do this a couple times with the test API key) | ||
res = requests.post(url, | ||
data = { | ||
'api_key': 'TEST', | ||
'recognizer': 'auto', | ||
'ref_no': 'ocr_python_123' | ||
}, | ||
|
||
files = { | ||
'file': open(file_path, "rb") | ||
}) | ||
|
||
with open("response.json", "w") as f: | ||
f.write(res.text) | ||
|
||
return res.json() | ||
|
||
if __name__ == '__main__': | ||
app.run(host='0.0.0.0', port=5002) # Run the app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
pymongo | ||
pylint | ||
black | ||
requests | ||
Flask | ||
python-dotenv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
{ | ||
"ocr_type" : "receipts", | ||
"request_id" : "P_72.80.97.228_luxbmz9s_bz6", | ||
"ref_no" : "ocr_python_123", | ||
"file_name" : "RestaurantReceipt1.png", | ||
"request_received_on" : 1712965847825, | ||
"success" : true, | ||
"image_width" : 812, | ||
"image_height" : 1354, | ||
"image_rotation" : 0, | ||
"recognition_completed_on" : 1712965848215, | ||
"receipts" : [ { | ||
"merchant_name" : "HARBOR LANE CAFE", | ||
"merchant_address" : "HARBOR LANE CAFE", | ||
"merchant_phone" : null, | ||
"merchant_website" : null, | ||
"merchant_tax_reg_no" : null, | ||
"merchant_company_reg_no" : null, | ||
"region" : null, | ||
"mall" : null, | ||
"country" : "US", | ||
"state" : "IL", | ||
"city" : "CHICAGO", | ||
"receipt_no" : null, | ||
"date" : "2019-11-20", | ||
"time" : null, | ||
"items" : [ { | ||
"amount" : 14.98, | ||
"category" : null, | ||
"description" : "Tacos Del Mal Shrimp", | ||
"flags" : "", | ||
"qty" : 1, | ||
"remarks" : null, | ||
"tags" : null, | ||
"unitPrice" : null | ||
}, { | ||
"amount" : 12.50, | ||
"category" : null, | ||
"description" : "Especial Salad Chicken", | ||
"flags" : "", | ||
"qty" : 1, | ||
"remarks" : null, | ||
"tags" : null, | ||
"unitPrice" : null | ||
}, { | ||
"amount" : 1.99, | ||
"category" : null, | ||
"description" : "Fountain Beverage", | ||
"flags" : "", | ||
"qty" : 1, | ||
"remarks" : null, | ||
"tags" : null, | ||
"unitPrice" : null | ||
} ], | ||
"currency" : "USD", | ||
"total" : 31.39, | ||
"subtotal" : 29.47, | ||
"tax" : 1.92, | ||
"service_charge" : null, | ||
"tip" : null, | ||
"payment_method" : null, | ||
"payment_details" : null, | ||
"credit_card_type" : null, | ||
"credit_card_number" : null, | ||
"ocr_text" : " HARBOR LANE CAFE\n 3941 GREEN OAKS BLVD\n CHICAGO, IL\n SALE\n 11/20/2019 11:05 AM\n BATCH #: 01A2A\n APPR #: 34362\n TRACE #: 9\n VISA 3483\n 1 Tacos Del Mal Shrimp $14.98\n 1 Especial Salad Chicken $12.50\n 1 Fountain Beverage $1.99\n SUBTOTAL: $29.47\n TAX: $1.92\n TOTAL: $31.39\n TIP:\n TOTAL:\n APPROVED\n THANK YOU\n CUSTOMER COPY", | ||
"ocr_confidence" : 98.50, | ||
"width" : 596, | ||
"height" : 1111, | ||
"avg_char_width" : 16.9954, | ||
"avg_line_height" : 28.3333, | ||
"conf_amount" : 83, | ||
"source_locations" : { | ||
"date" : [ [ { | ||
"x" : 46, | ||
"y" : 216 | ||
}, { | ||
"x" : 240, | ||
"y" : 216 | ||
}, { | ||
"x" : 240, | ||
"y" : 246 | ||
}, { | ||
"x" : 46, | ||
"y" : 246 | ||
} ] ], | ||
"total" : [ [ { | ||
"x" : 275, | ||
"y" : 696 | ||
}, { | ||
"x" : 381, | ||
"y" : 696 | ||
}, { | ||
"x" : 381, | ||
"y" : 726 | ||
}, { | ||
"x" : 275, | ||
"y" : 726 | ||
} ] ], | ||
"subtotal" : [ [ { | ||
"x" : 276, | ||
"y" : 615 | ||
}, { | ||
"x" : 384, | ||
"y" : 615 | ||
}, { | ||
"x" : 384, | ||
"y" : 646 | ||
}, { | ||
"x" : 276, | ||
"y" : 646 | ||
} ] ], | ||
"merchant_name" : [ [ { | ||
"x" : 40, | ||
"y" : 13 | ||
}, { | ||
"x" : 357, | ||
"y" : 15 | ||
}, { | ||
"x" : 357, | ||
"y" : 47 | ||
}, { | ||
"x" : 40, | ||
"y" : 46 | ||
} ] ], | ||
"doc" : [ [ { | ||
"x" : 24, | ||
"y" : -40 | ||
}, { | ||
"x" : 679, | ||
"y" : -40 | ||
}, { | ||
"x" : 679, | ||
"y" : 1181 | ||
}, { | ||
"x" : 24, | ||
"y" : 1181 | ||
} ] ], | ||
"tax" : [ [ { | ||
"x" : 277, | ||
"y" : 656 | ||
}, { | ||
"x" : 361, | ||
"y" : 656 | ||
}, { | ||
"x" : 361, | ||
"y" : 685 | ||
}, { | ||
"x" : 277, | ||
"y" : 685 | ||
} ] ], | ||
"merchant_address" : [ [ { | ||
"x" : 24, | ||
"y" : 11 | ||
}, { | ||
"x" : 373, | ||
"y" : 13 | ||
}, { | ||
"x" : 373, | ||
"y" : 49 | ||
}, { | ||
"x" : 24, | ||
"y" : 48 | ||
} ] ] | ||
} | ||
} ] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# docs: https://hub.docker.com/_/python | ||
FROM python:3.8-slim-buster | ||
|
||
WORKDIR /web_app | ||
|
||
COPY requirements.txt ./ | ||
RUN pip install --no-cache-dir -r requirements.txt | ||
|
||
COPY . . | ||
|
||
EXPOSE 10000 | ||
CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[[source]] | ||
url = "https://pypi.org/simple" | ||
verify_ssl = true | ||
name = "pypi" | ||
|
||
[packages] | ||
pylint = "*" | ||
black = "*" | ||
|
||
[dev-packages] | ||
|
||
[requires] | ||
python_version = "3.10" |
Oops, something went wrong.