tdurzynski's picture
Update app.py
1f27a2f verified
raw
history blame
5.82 kB
import streamlit as st
import json
import os
import boto3
from PIL import Image
import firebase_admin
from firebase_admin import credentials, auth
import pandas as pd
# Load AWS credentials using correct HF Secrets
AWS_ACCESS_KEY = os.getenv("AWS_ACCESS_KEY")
AWS_SECRET_KEY = os.getenv("AWS_SECRET_KEY")
AWS_REGION = os.getenv("AWS_REGION", "us-east-1")
S3_BUCKET_NAME = os.getenv("S3_BUCKET_NAME", "food-image-crowdsourcing")
DYNAMODB_TABLE = os.getenv("DYNAMODB_TABLE", "image_metadata")
# Load Firebase credentials
FIREBASE_CONFIG = json.loads(os.getenv("FIREBASE_CONFIG", "{}"))
# Initialize Firebase Admin SDK (Prevent multiple initialization)
if not firebase_admin._apps:
cred = credentials.Certificate(FIREBASE_CONFIG)
firebase_admin.initialize_app(cred)
# Initialize AWS Services (S3 & DynamoDB)
s3 = boto3.client(
"s3",
aws_access_key_id=AWS_ACCESS_KEY,
aws_secret_access_key=AWS_SECRET_KEY,
)
dynamodb = boto3.resource(
"dynamodb",
region_name=AWS_REGION,
aws_access_key_id=AWS_ACCESS_KEY,
aws_secret_access_key=AWS_SECRET_KEY,
)
metadata_table = dynamodb.Table(DYNAMODB_TABLE)
# Food Intellisense List
FOOD_SUGGESTIONS = [
"Apple", "Banana", "Pizza", "Burger", "Pasta", "Sushi", "Tacos", "Salad",
"Chicken Curry", "Steak", "Fish & Chips", "Dumplings", "Kimchi", "Pancakes",
"Biryani", "Croissant", "Baguette", "Miso Soup", "Ramen", "Pierogi"
] # Extend this list with diverse cuisines
# Unit options for food weight/volume
UNIT_OPTIONS = ["grams", "ounces", "teaspoons", "tablespoons", "cups", "slices", "pieces"]
# Streamlit Layout - Authentication Section
st.sidebar.title("πŸ”‘ User Authentication")
auth_option = st.sidebar.radio("Select an option", ["Login", "Sign Up", "Logout"])
if auth_option == "Sign Up":
email = st.sidebar.text_input("Email")
password = st.sidebar.text_input("Password", type="password")
if st.sidebar.button("Sign Up"):
try:
user = auth.create_user(email=email, password=password)
st.sidebar.success("βœ… User created successfully! Please log in.")
except Exception as e:
st.sidebar.error(f"Error: {e}")
if auth_option == "Login":
email = st.sidebar.text_input("Email")
password = st.sidebar.text_input("Password", type="password")
if st.sidebar.button("Login"):
try:
user = auth.get_user_by_email(email)
st.session_state["user_id"] = user.uid
st.session_state["tokens"] = 0 # Initialize token count
st.sidebar.success("βœ… Logged in successfully!")
except Exception as e:
st.sidebar.error(f"Login failed: {e}")
if auth_option == "Logout" and "user_id" in st.session_state:
del st.session_state["user_id"]
st.sidebar.success("βœ… Logged out successfully!")
# Ensure user is logged in before uploading
if "user_id" not in st.session_state:
st.warning("⚠️ Please log in to upload images.")
st.stop()
# Streamlit Layout - Three Panel Design
st.title("🍽️ Food Image Review & Annotation")
col1, col2 = st.columns([1, 1])
# Compliance & Disclaimer Section
st.markdown("### **Terms & Conditions**")
st.write(
"By uploading an image, you agree to transfer full copyright to the research team for AI training purposes."
" You are responsible for ensuring you own the image and it does not violate any copyright laws."
" We do not guarantee when tokens will be redeemable. Keep track of your user ID."
)
terms_accepted = st.checkbox("I agree to the terms and conditions", key="terms_accepted")
if not terms_accepted:
st.warning("⚠️ You must agree to the terms before proceeding.")
st.stop()
# Upload Image
uploaded_file = st.file_uploader("Upload an image of your food", type=["jpg", "png", "jpeg"])
if uploaded_file:
original_img = Image.open(uploaded_file)
st.session_state["original_image"] = original_img
st.session_state["tokens"] += 1 # Earn 1 token for upload
# If an image has been uploaded, process and display it
if "original_image" in st.session_state:
original_img = st.session_state["original_image"]
def resize_image(image, max_size=512):
aspect_ratio = image.width / image.height
if image.width > image.height:
new_width = max_size
new_height = int(max_size / aspect_ratio)
else:
new_height = max_size
new_width = int(max_size * aspect_ratio)
return image.resize((new_width, new_height))
processed_img = resize_image(original_img)
col1, col2 = st.columns(2)
with col1:
st.subheader("πŸ“· Original Image")
st.image(original_img, caption=f"Original ({original_img.width}x{original_img.height} pixels)", use_container_width=True)
with col2:
st.subheader("πŸ–ΌοΈ Processed Image")
st.image(processed_img, caption=f"Processed ({processed_img.width}x{processed_img.height} pixels)", use_container_width=True)
st.session_state["processed_image"] = processed_img
# Display earned tokens
st.success(f"πŸŽ‰ Tokens Earned: {st.session_state['tokens']}")
# Annotation Table
st.subheader("πŸ“ Add Annotations")
if "annotations" not in st.session_state:
st.session_state["annotations"] = []
new_food_item = st.selectbox("Food Item", FOOD_SUGGESTIONS + ["Other..."])
if new_food_item == "Other...":
new_food_item = st.text_input("Enter custom food item")
new_quantity = st.number_input("Quantity", min_value=0, step=1)
new_unit = st.selectbox("Unit", UNIT_OPTIONS)
if st.button("Add Annotation"):
st.session_state["annotations"].append({
"name": new_food_item,
"quantity": new_quantity,
"unit": new_unit
})
st.session_state["tokens"] += 1 # Earn 1 token per annotation
st.table(st.session_state["annotations"])