Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -7,6 +7,7 @@ import boto3
|
|
7 |
from PIL import Image
|
8 |
import firebase_admin
|
9 |
from firebase_admin import credentials, auth
|
|
|
10 |
|
11 |
# Load AWS credentials using correct HF Secrets
|
12 |
AWS_ACCESS_KEY = os.getenv("AWS_ACCESS_KEY")
|
@@ -38,6 +39,16 @@ dynamodb = boto3.resource(
|
|
38 |
)
|
39 |
metadata_table = dynamodb.Table(DYNAMODB_TABLE)
|
40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
# Streamlit Layout - Authentication Section
|
42 |
st.sidebar.title("π User Authentication")
|
43 |
auth_option = st.sidebar.radio("Select an option", ["Login", "Sign Up", "Logout"])
|
@@ -74,7 +85,7 @@ if "user_id" not in st.session_state:
|
|
74 |
|
75 |
# Streamlit Layout - Three Panel Design
|
76 |
st.title("π½οΈ Food Image Review & Annotation")
|
77 |
-
col1, col2
|
78 |
|
79 |
# Compliance & Disclaimer Section
|
80 |
st.markdown("### **Terms & Conditions**")
|
@@ -101,49 +112,57 @@ def resize_image(image, new_width=512):
|
|
101 |
if "original_image" in st.session_state:
|
102 |
original_img = st.session_state["original_image"]
|
103 |
processed_img = resize_image(original_img)
|
104 |
-
|
105 |
# πΌοΈ Panel 1: Original Image
|
106 |
with col1:
|
107 |
st.subheader("π· Original Image")
|
108 |
-
st.image(original_img, caption=f"Uploaded ({original_img.width}x{original_img.height} pixels)",
|
109 |
|
110 |
# πΌοΈ Panel 2: Resized Image (512x512 Maintaining Aspect Ratio)
|
111 |
with col2:
|
112 |
st.subheader("πΌοΈ Processed Image")
|
113 |
-
st.image(processed_img, caption=f"Processed ({processed_img.width}x{processed_img.height} pixels)",
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
from PIL import Image
|
8 |
import firebase_admin
|
9 |
from firebase_admin import credentials, auth
|
10 |
+
import pandas as pd
|
11 |
|
12 |
# Load AWS credentials using correct HF Secrets
|
13 |
AWS_ACCESS_KEY = os.getenv("AWS_ACCESS_KEY")
|
|
|
39 |
)
|
40 |
metadata_table = dynamodb.Table(DYNAMODB_TABLE)
|
41 |
|
42 |
+
# Food Intellisense List
|
43 |
+
FOOD_SUGGESTIONS = [
|
44 |
+
"Apple", "Banana", "Pizza", "Burger", "Pasta", "Sushi", "Tacos", "Salad",
|
45 |
+
"Chicken Curry", "Steak", "Fish & Chips", "Dumplings", "Kimchi", "Pancakes",
|
46 |
+
"Biryani", "Croissant", "Baguette", "Miso Soup", "Ramen", "Pierogi"
|
47 |
+
] # Extend this list with diverse cuisines
|
48 |
+
|
49 |
+
# Unit options for food weight/volume
|
50 |
+
UNIT_OPTIONS = ["grams", "ounces", "teaspoons", "tablespoons", "cups", "pieces"]
|
51 |
+
|
52 |
# Streamlit Layout - Authentication Section
|
53 |
st.sidebar.title("π User Authentication")
|
54 |
auth_option = st.sidebar.radio("Select an option", ["Login", "Sign Up", "Logout"])
|
|
|
85 |
|
86 |
# Streamlit Layout - Three Panel Design
|
87 |
st.title("π½οΈ Food Image Review & Annotation")
|
88 |
+
col1, col2 = st.columns([1, 1])
|
89 |
|
90 |
# Compliance & Disclaimer Section
|
91 |
st.markdown("### **Terms & Conditions**")
|
|
|
112 |
if "original_image" in st.session_state:
|
113 |
original_img = st.session_state["original_image"]
|
114 |
processed_img = resize_image(original_img)
|
115 |
+
|
116 |
# πΌοΈ Panel 1: Original Image
|
117 |
with col1:
|
118 |
st.subheader("π· Original Image")
|
119 |
+
st.image(original_img, caption=f"Uploaded ({original_img.width}x{original_img.height} pixels)", use_column_width=True)
|
120 |
|
121 |
# πΌοΈ Panel 2: Resized Image (512x512 Maintaining Aspect Ratio)
|
122 |
with col2:
|
123 |
st.subheader("πΌοΈ Processed Image")
|
124 |
+
st.image(processed_img, caption=f"Processed ({processed_img.width}x{processed_img.height} pixels)", use_column_width=True)
|
125 |
+
|
126 |
+
# π Annotation Table
|
127 |
+
st.subheader("π Add Annotations")
|
128 |
+
|
129 |
+
if "annotations" not in st.session_state:
|
130 |
+
st.session_state["annotations"] = []
|
131 |
+
|
132 |
+
# Create dataframe for annotations
|
133 |
+
annotation_df = pd.DataFrame(st.session_state["annotations"], columns=["Food Item", "Unit", "Quantity", "Ingredients"])
|
134 |
+
|
135 |
+
# Food input with intellisense
|
136 |
+
food_item = st.selectbox("Select food item or type custom:", FOOD_SUGGESTIONS + ["Other"])
|
137 |
+
if food_item == "Other":
|
138 |
+
food_item = st.text_input("Enter food item manually:")
|
139 |
+
|
140 |
+
unit = st.selectbox("Select unit:", UNIT_OPTIONS)
|
141 |
+
quantity = st.number_input("Enter quantity:", min_value=0.1, step=0.1)
|
142 |
+
|
143 |
+
# Dynamic ingredient input
|
144 |
+
ingredients = st.text_area("Enter ingredients (one per line):")
|
145 |
+
ingredient_list = [i.strip() for i in ingredients.split("\n") if i.strip()]
|
146 |
+
|
147 |
+
if st.button("Add Food Item"):
|
148 |
+
if food_item and unit and quantity:
|
149 |
+
st.session_state["annotations"].append([food_item, unit, quantity, ingredient_list])
|
150 |
+
st.success(f"β
Added {food_item} successfully!")
|
151 |
+
|
152 |
+
# Display annotation table
|
153 |
+
st.dataframe(pd.DataFrame(st.session_state["annotations"], columns=["Food Item", "Unit", "Quantity", "Ingredients"]))
|
154 |
+
|
155 |
+
# Save Annotations to DynamoDB
|
156 |
+
if st.button("Save Annotations"):
|
157 |
+
metadata_table.update_item(
|
158 |
+
Key={"image_id": uploaded_file.name},
|
159 |
+
UpdateExpression="SET user_id = :u, annotations = :a, processing_status = :p, s3_url = :s, tokens_earned = :t",
|
160 |
+
ExpressionAttributeValues={
|
161 |
+
":u": st.session_state["user_id"],
|
162 |
+
":a": st.session_state["annotations"],
|
163 |
+
":p": "processed",
|
164 |
+
":s": f"s3://{S3_BUCKET_NAME}/raw-uploads/{uploaded_file.name}",
|
165 |
+
":t": len(st.session_state["annotations"])
|
166 |
+
},
|
167 |
+
)
|
168 |
+
st.success("β
Annotations saved successfully!")
|