Spaces:
Sleeping
Sleeping
Update app.py
Browse filesEnd section of code was cut off
app.py
CHANGED
@@ -101,6 +101,144 @@ st.write(
|
|
101 |
)
|
102 |
st.checkbox("I agree to the terms and conditions", key="terms_accepted")
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
# β
**Process and Upload Image**
|
105 |
if uploaded_file and st.session_state.terms_accepted:
|
106 |
image = Image.open(uploaded_file)
|
@@ -140,4 +278,18 @@ if uploaded_file and st.session_state.terms_accepted:
|
|
140 |
Item={
|
141 |
"user_email": st.session_state.user_email,
|
142 |
"file_name": file_name,
|
143 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
)
|
102 |
st.checkbox("I agree to the terms and conditions", key="terms_accepted")
|
103 |
|
104 |
+
# β
**Process and Upload Image**
|
105 |
+
if uploaded_file and st.session_state.terms_accepted:
|
106 |
+
image = Image.open(uploaded_file)
|
107 |
+
st.image(image, caption="Uploaded Image", use_column_width=True)
|
108 |
+
|
109 |
+
# Show Original Size
|
110 |
+
st.write(f"π Original size: {image.size}")
|
111 |
+
|
112 |
+
# Convert PNG to JPEG if needed
|
113 |
+
if image.format == "PNG":
|
114 |
+
image = image.convert("RGB")
|
115 |
+
|
116 |
+
# Resize image to max 1024x1024 px
|
117 |
+
MAX_SIZE = (1024, 1024)
|
118 |
+
image.thumbnail(MAX_SIZE)
|
119 |
+
|
120 |
+
# Convert Image to Bytes
|
121 |
+
img_bytes = io.BytesIO()
|
122 |
+
image.save(img_bytes, format="JPEG", quality=80) # Reduce quality to save space
|
123 |
+
img_bytes.seek(0)
|
124 |
+
|
125 |
+
# πΉ Generate Unique File Name
|
126 |
+
file_name = f"raw-uploads/{st.session_state.user_email}_{int(time.time())}.jpg"
|
127 |
+
|
128 |
+
# β
**Upload to S3**
|
129 |
+
try:
|
130 |
+
s3.put_object(
|
131 |
+
Bucket=S3_BUCKET_NAME,
|
132 |
+
Key=file_name,
|
133 |
+
Body=img_bytes.getvalue(),
|
134 |
+
ContentType="image/jpeg",
|
135 |
+
)
|
136 |
+
st.success("β
Image uploaded successfully to S3!")
|
137 |
+
|
138 |
+
# β
**Store Metadata in DynamoDB**
|
139 |
+
import streamlit as st
|
140 |
+
import json
|
141 |
+
import os
|
142 |
+
import io
|
143 |
+
import base64
|
144 |
+
import boto3
|
145 |
+
import time
|
146 |
+
from PIL import Image
|
147 |
+
import firebase_admin
|
148 |
+
from firebase_admin import credentials, auth, firestore
|
149 |
+
|
150 |
+
# π Load Secrets from Hugging Face Secrets
|
151 |
+
FIREBASE_CONFIG = json.loads(os.getenv("FIREBASE_CONFIG", "{}"))
|
152 |
+
AWS_ACCESS_KEY = os.getenv("AWS_ACCESS_KEY")
|
153 |
+
AWS_SECRET_KEY = os.getenv("AWS_SECRET_KEY")
|
154 |
+
S3_BUCKET_NAME = os.getenv("S3_BUCKET_NAME", "food-image-crowdsourcing")
|
155 |
+
DYNAMODB_TABLE = os.getenv("DYNAMODB_TABLE", "image_metadata") # β
Corrected Table Name
|
156 |
+
|
157 |
+
# β
Initialize Firebase Admin SDK
|
158 |
+
if FIREBASE_CONFIG:
|
159 |
+
cred = credentials.Certificate(FIREBASE_CONFIG)
|
160 |
+
firebase_admin.initialize_app(cred)
|
161 |
+
else:
|
162 |
+
st.error("β οΈ Firebase configuration is missing! Please check HF Secrets.")
|
163 |
+
|
164 |
+
# β
Initialize AWS Services (S3 & DynamoDB)
|
165 |
+
s3 = boto3.client(
|
166 |
+
"s3",
|
167 |
+
aws_access_key_id=AWS_ACCESS_KEY,
|
168 |
+
aws_secret_access_key=AWS_SECRET_KEY,
|
169 |
+
)
|
170 |
+
|
171 |
+
dynamodb = boto3.resource(
|
172 |
+
"dynamodb",
|
173 |
+
aws_access_key_id=AWS_ACCESS_KEY,
|
174 |
+
aws_secret_access_key=AWS_SECRET_KEY,
|
175 |
+
)
|
176 |
+
metadata_table = dynamodb.Table(DYNAMODB_TABLE) # β
Corrected Table Name
|
177 |
+
|
178 |
+
# πΉ Initialize Session State for Tokens
|
179 |
+
if "tokens" not in st.session_state:
|
180 |
+
st.session_state.tokens = 0
|
181 |
+
if "user_email" not in st.session_state:
|
182 |
+
st.session_state.user_email = None
|
183 |
+
|
184 |
+
# πΉ UI - Page Title
|
185 |
+
st.title("π· Food Crowdsourcing Research App")
|
186 |
+
st.write("Help our research by uploading food images! Earn tokens for future app use.")
|
187 |
+
|
188 |
+
# β
**User Authentication Section**
|
189 |
+
st.sidebar.header("π User Authentication")
|
190 |
+
|
191 |
+
auth_choice = st.sidebar.radio("Select an option", ["Login", "Sign Up", "Logout"])
|
192 |
+
|
193 |
+
if auth_choice == "Sign Up":
|
194 |
+
with st.sidebar.form("signup_form"):
|
195 |
+
email = st.text_input("Email")
|
196 |
+
password = st.text_input("Password", type="password")
|
197 |
+
submit_button = st.form_submit_button("Sign Up")
|
198 |
+
|
199 |
+
if submit_button:
|
200 |
+
try:
|
201 |
+
user = auth.create_user(email=email, password=password)
|
202 |
+
st.success(f"β
Account created! Now login with {email}.")
|
203 |
+
except Exception as e:
|
204 |
+
st.error(f"β οΈ {str(e)}")
|
205 |
+
|
206 |
+
if auth_choice == "Login":
|
207 |
+
with st.sidebar.form("login_form"):
|
208 |
+
email = st.text_input("Email")
|
209 |
+
password = st.text_input("Password", type="password")
|
210 |
+
submit_button = st.form_submit_button("Login")
|
211 |
+
|
212 |
+
if submit_button:
|
213 |
+
try:
|
214 |
+
user = auth.get_user_by_email(email)
|
215 |
+
st.session_state.user_email = email
|
216 |
+
st.success(f"β
Welcome back, {email}!")
|
217 |
+
except Exception as e:
|
218 |
+
st.error(f"β οΈ {str(e)}")
|
219 |
+
|
220 |
+
if auth_choice == "Logout":
|
221 |
+
if st.session_state.user_email:
|
222 |
+
st.session_state.user_email = None
|
223 |
+
st.success("β
Logged out successfully!")
|
224 |
+
|
225 |
+
# πΉ **Ensure User is Logged In**
|
226 |
+
if not st.session_state.user_email:
|
227 |
+
st.warning("β οΈ Please log in to upload images.")
|
228 |
+
st.stop()
|
229 |
+
|
230 |
+
# β
**Image Upload Section**
|
231 |
+
uploaded_file = st.file_uploader("πΈ Upload a food image", type=["jpg", "png", "jpeg"])
|
232 |
+
|
233 |
+
# β
**Terms & Conditions**
|
234 |
+
st.markdown("### **Terms & Conditions**")
|
235 |
+
st.write(
|
236 |
+
"By uploading an image, you agree to transfer full copyright to the research team for AI training purposes. "
|
237 |
+
"You are responsible for ensuring you own the image and it does not violate any copyright laws. "
|
238 |
+
"We do not guarantee when tokens will be redeemable. Keep track of your user ID."
|
239 |
+
)
|
240 |
+
st.checkbox("I agree to the terms and conditions", key="terms_accepted")
|
241 |
+
|
242 |
# β
**Process and Upload Image**
|
243 |
if uploaded_file and st.session_state.terms_accepted:
|
244 |
image = Image.open(uploaded_file)
|
|
|
278 |
Item={
|
279 |
"user_email": st.session_state.user_email,
|
280 |
"file_name": file_name,
|
281 |
+
"upload_time": int(time.time()),
|
282 |
+
}
|
283 |
+
)
|
284 |
+
|
285 |
+
# π **Reward Tokens**
|
286 |
+
st.session_state.tokens += 1
|
287 |
+
st.write("π You earned **1 token** for uploading!")
|
288 |
+
st.success(f"π’ Total tokens: {st.session_state.tokens}")
|
289 |
+
|
290 |
+
except Exception as e:
|
291 |
+
st.error(f"β οΈ Failed to upload image: {str(e)}")
|
292 |
+
|
293 |
+
# β
**Future: Annotation for Additional Token**
|
294 |
+
# If annotation is provided, reward another token
|
295 |
+
|