tdurzynski commited on
Commit
71458f9
·
verified ·
1 Parent(s): a4315e9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +105 -91
app.py CHANGED
@@ -63,6 +63,7 @@ except Exception as e:
63
  else:
64
  st.stop()
65
 
 
66
  FOOD_SUGGESTIONS = [
67
  "Ajvar", "Angel Wings", "Apple", "Apple Pie", "Apfelstrudel", "Arancini", "Asparagus", "Babka", "Bagel","Baguette", "Baklava",
68
  "Banana", "Banana Bread", "Banh Mi", "Banitsa", "Barbecue Ribs", "BBQ Chicken", "BBQ Chicken Pizza", "BBQ Ribs", "Bean Buritto",
@@ -106,9 +107,9 @@ UNIT_OPTIONS = ["grams", "ounce(s)", "teaspoon(s)", "tablespoon(s)", "cup(s)", "
106
 
107
  # Cooking methods
108
  COOKING_METHODS = [
109
- "Baked", "Boiled", "Braised", "Breaded and fried", "Broiled", "Creamy", "Deep-fried", "Dried",
110
  "Fried", "Grilled", "Grilled minced", "Marinated", "Microwaved", "Pan-seared", "Poached", "Raw",
111
- "Roasted", "Sautéed", "Slow-cooked", "Smoked", "Steamed", "Stewed", "Stir-fried", "Takeout/Restaurant", "Unknown"
112
  ]
113
 
114
  # Helper functions
@@ -139,8 +140,8 @@ def resize_image(image, max_size=512, quality=85):
139
  # Resize the image
140
  resized_img = image.resize((new_width, new_height), Image.LANCZOS)
141
  else:
142
- # If image is already smaller than max_size, don't resize
143
- return image
144
 
145
  # Convert to RGB if image has alpha channel (for JPEG conversion)
146
  if resized_img.mode == 'RGBA':
@@ -194,7 +195,9 @@ def upload_to_s3(image, user_id, folder="", force_quality=None):
194
  else:
195
  # Higher quality for raw uploads, compressed for processed
196
  quality = 95 if folder == "raw-uploads" else 85
197
-
 
 
198
  image.save(buffer, format="JPEG", quality=quality, optimize=True)
199
  buffer.seek(0)
200
 
@@ -279,7 +282,11 @@ def reset_form_fields():
279
 
280
  def add_food_item(food_name, portion_size, portion_unit, cooking_method, ingredients):
281
  """Add a food item to the session state"""
282
- if food_name and portion_size and portion_unit and cooking_method:
 
 
 
 
283
  # Add the food item to the session state
284
  st.session_state["food_items"].append({
285
  "food_name": food_name,
@@ -453,7 +460,8 @@ if "original_image" in st.session_state:
453
  with col2:
454
  portion_unit = st.selectbox("Unit", options=UNIT_OPTIONS)
455
 
456
- cooking_method = st.selectbox("Cooking Method", options=[""] + COOKING_METHODS)
 
457
 
458
  ingredients = st_tags.st_tags(
459
  label="Main Ingredients (Add up to 5)",
@@ -472,95 +480,101 @@ if "original_image" in st.session_state:
472
  st.session_state["custom_food_name"] = custom_food_name
473
  st.rerun()
474
 
475
- # Separate section for quick-add common foods
476
- if "original_image" in st.session_state:
477
- with st.expander("🚀 Quick Add Common Foods"):
478
- st.info("Click to quickly add common food items with default values")
479
- quick_add_cols = st.columns(3)
480
-
481
- common_foods = [
482
- {"name": "French Fries", "portion": 100, "unit": "grams", "cooking": "Fried", "ingredients": ["Potatoes", "Salt", "Oil"]},
483
- {"name": "Hamburger", "portion": 1, "unit": "pieces", "cooking": "Grilled", "ingredients": ["Beef", "Bun", "Lettuce", "Tomato"]},
484
- {"name": "Salad", "portion": 150, "unit": "grams", "cooking": "Raw", "ingredients": ["Lettuce", "Tomato", "Cucumber"]}
485
- ]
486
-
487
- for i, food in enumerate(common_foods):
488
- with quick_add_cols[i % 3]:
489
- if st.button(f"+ {food['name']}", key=f"quick_{i}"):
490
- add_food_item(
491
- food['name'],
492
- food['portion'],
493
- food['unit'],
494
- food['cooking'],
495
- food['ingredients']
496
- )
497
- st.rerun()
498
-
499
- # Divider before submit button
500
  st.markdown("---")
501
 
502
- # Submit all foods button - outside the form
503
- if st.button("📤 Submit All Food Items", disabled=len(st.session_state["food_items"]) == 0):
504
- if not st.session_state["food_items"]:
505
- st.error("❌ Please add at least one food item before submitting")
506
- else:
507
- with st.spinner("Processing your submission..."):
508
- all_saved = True
509
- total_tokens = 0
510
-
511
- # Determine image quality (simplified version)
512
- image_quality = "high" if original_img.width >= 1000 and original_img.height >= 1000 else "standard"
513
-
514
- # Upload both original and processed images to correct S3 folders
515
- raw_s3_path = upload_to_s3(original_img, st.session_state["user_id"], folder="raw-uploads")
516
- processed_s3_path = upload_to_s3(processed_img, st.session_state["user_id"], folder="processed-512x512")
517
-
518
- if raw_s3_path and processed_s3_path:
519
- # Save each food item with the processed image path
520
- for food_item in st.session_state["food_items"]:
521
- # Check if metadata is complete
522
- has_metadata = True # Already validated
523
-
524
- # Check if the food is in a unique category (simplified)
525
- is_unique_category = food_item["food_name"] not in ["Pizza", "Burger", "Pasta", "Salad"]
526
-
527
- # Calculate tokens for this item
528
- tokens_awarded = calculate_tokens(image_quality, has_metadata, is_unique_category)
529
- total_tokens += tokens_awarded
530
-
531
- # Convert float to Decimal for DynamoDB
532
- portion_size_decimal = Decimal(str(food_item["portion_size"]))
533
-
534
- # Save metadata to DynamoDB with processed image path
535
- success = save_metadata(
536
- st.session_state["user_id"],
537
- processed_s3_path, # Use the processed image path
538
- food_item["food_name"],
539
- portion_size_decimal, # Use Decimal type
540
- food_item["portion_unit"],
541
- food_item["cooking_method"],
542
- food_item["ingredients"],
543
- tokens_awarded
544
- )
545
 
546
- if not success:
547
- all_saved = False
548
- break
 
 
 
 
 
 
 
 
549
 
550
- if all_saved:
551
- st.session_state["tokens"] += total_tokens
552
- st.session_state["uploads_count"] += 1
553
- st.success(f"✅ All food items uploaded successfully! You earned {total_tokens} tokens.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
554
 
555
- # Clear the form and image for a new submission
556
- st.session_state.pop("original_image", None)
557
- st.session_state.pop("processed_image", None)
558
- st.session_state["food_items"] = []
559
- st.rerun()
 
 
 
 
 
 
 
560
  else:
561
- st.error("Failed to save some items. Please try again.")
562
- else:
563
- st.error("Failed to upload images. Please try again.")
564
 
565
  # Display earned tokens
566
  st.sidebar.markdown("---")
@@ -584,4 +598,4 @@ if st.sidebar.button("Token Rewards System"):
584
  if st.sidebar.button("Terms of Service"):
585
  with open("TERMS_OF_SERVICE.md", "r") as f:
586
  terms = f.read()
587
- st.sidebar.markdown(terms)
 
63
  else:
64
  st.stop()
65
 
66
+ # Food Intellisense List
67
  FOOD_SUGGESTIONS = [
68
  "Ajvar", "Angel Wings", "Apple", "Apple Pie", "Apfelstrudel", "Arancini", "Asparagus", "Babka", "Bagel","Baguette", "Baklava",
69
  "Banana", "Banana Bread", "Banh Mi", "Banitsa", "Barbecue Ribs", "BBQ Chicken", "BBQ Chicken Pizza", "BBQ Ribs", "Bean Buritto",
 
107
 
108
  # Cooking methods
109
  COOKING_METHODS = [
110
+ "Unknown", "Baked", "Boiled", "Braised", "Breaded and fried", "Broiled", "Creamy", "Deep-fried", "Dried",
111
  "Fried", "Grilled", "Grilled minced", "Marinated", "Microwaved", "Pan-seared", "Poached", "Raw",
112
+ "Roasted", "Sautéed", "Slow-cooked", "Smoked", "Steamed", "Stewed", "Stir-fried", "Takeout/Restaurant"
113
  ]
114
 
115
  # Helper functions
 
140
  # Resize the image
141
  resized_img = image.resize((new_width, new_height), Image.LANCZOS)
142
  else:
143
+ # If image is already smaller than max_size, return a copy to avoid modifying original
144
+ resized_img = image.copy()
145
 
146
  # Convert to RGB if image has alpha channel (for JPEG conversion)
147
  if resized_img.mode == 'RGBA':
 
195
  else:
196
  # Higher quality for raw uploads, compressed for processed
197
  quality = 95 if folder == "raw-uploads" else 85
198
+
199
+ # Don't compress the image again if it's already been through resize_image
200
+ # Just save with the appropriate quality
201
  image.save(buffer, format="JPEG", quality=quality, optimize=True)
202
  buffer.seek(0)
203
 
 
282
 
283
  def add_food_item(food_name, portion_size, portion_unit, cooking_method, ingredients):
284
  """Add a food item to the session state"""
285
+ # Set cooking method to "Unknown" if empty
286
+ if not cooking_method:
287
+ cooking_method = "Unknown"
288
+
289
+ if food_name and portion_size and portion_unit: # Cooking method no longer required
290
  # Add the food item to the session state
291
  st.session_state["food_items"].append({
292
  "food_name": food_name,
 
460
  with col2:
461
  portion_unit = st.selectbox("Unit", options=UNIT_OPTIONS)
462
 
463
+ # Set Cooking Method with "Unknown" as the default (index 0)
464
+ cooking_method = st.selectbox("Cooking Method (optional)", options=COOKING_METHODS, index=0)
465
 
466
  ingredients = st_tags.st_tags(
467
  label="Main Ingredients (Add up to 5)",
 
480
  st.session_state["custom_food_name"] = custom_food_name
481
  st.rerun()
482
 
483
+ # Make submit button more prominent
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
484
  st.markdown("---")
485
 
486
+ # More prominent submit button with instructions
487
+ st.markdown("### 📤 Submit Your Food Annotations")
488
+ st.info("⚠️ After adding all your food items, click the button below to save your submission and earn tokens.")
489
+
490
+ # Create a larger, more visible submit button
491
+ submit_col1, submit_col2, submit_col3 = st.columns([1, 2, 1])
492
+ with submit_col2:
493
+ if st.button("📤 SUBMIT ALL FOOD ITEMS",
494
+ disabled=len(st.session_state["food_items"]) == 0,
495
+ use_container_width=True,
496
+ type="primary"):
497
+ if not st.session_state["food_items"]:
498
+ st.error("❌ Please add at least one food item before submitting")
499
+ else:
500
+ with st.spinner("Processing your submission..."):
501
+ all_saved = True
502
+ total_tokens = 0
503
+
504
+ # Determine image quality (simplified version)
505
+ image_quality = "high" if original_img.width >= 1000 and original_img.height >= 1000 else "standard"
506
+
507
+ # Get original image file size for comparison
508
+ original_size = get_image_size_kb(original_img)
509
+
510
+ # Ensure we have a properly processed image with the right settings
511
+ # Force resize and compression with settings that guarantee size reduction
512
+ processed_img = resize_image(original_img, max_size=512, quality=85)
513
+ processed_size = get_image_size_kb(processed_img)
514
+
515
+ # If the processed image isn't smaller enough, reduce quality further
516
+ if processed_size > original_size * 0.8: # Ensure at least 20% reduction
517
+ processed_img = resize_image(original_img, max_size=512, quality=70)
518
+ processed_size = get_image_size_kb(processed_img)
 
 
 
 
 
 
 
 
 
 
519
 
520
+ # If still not small enough, try more aggressive compression
521
+ if processed_size > original_size * 0.8:
522
+ processed_img = resize_image(original_img, max_size=480, quality=60)
523
+
524
+ # Upload original to raw-uploads folder
525
+ raw_s3_path = upload_to_s3(original_img, st.session_state["user_id"],
526
+ folder="raw-uploads", force_quality=95)
527
+
528
+ # Upload only one processed image to processed-512x512 folder
529
+ processed_s3_path = upload_to_s3(processed_img, st.session_state["user_id"],
530
+ folder="processed-512x512", force_quality=85)
531
 
532
+ if raw_s3_path and processed_s3_path:
533
+ # Save each food item with the processed image path
534
+ for food_item in st.session_state["food_items"]:
535
+ # Check if metadata is complete
536
+ has_metadata = True # Already validated
537
+
538
+ # Check if the food is in a unique category (simplified)
539
+ is_unique_category = food_item["food_name"] not in ["Pizza", "Burger", "Pasta", "Salad"]
540
+
541
+ # Calculate tokens for this item
542
+ tokens_awarded = calculate_tokens(image_quality, has_metadata, is_unique_category)
543
+ total_tokens += tokens_awarded
544
+
545
+ # Convert float to Decimal for DynamoDB
546
+ portion_size_decimal = Decimal(str(food_item["portion_size"]))
547
+
548
+ # Save metadata to DynamoDB with processed image path
549
+ success = save_metadata(
550
+ st.session_state["user_id"],
551
+ processed_s3_path, # Use the processed image path
552
+ food_item["food_name"],
553
+ portion_size_decimal, # Use Decimal type
554
+ food_item["portion_unit"],
555
+ food_item["cooking_method"],
556
+ food_item["ingredients"],
557
+ tokens_awarded
558
+ )
559
+
560
+ if not success:
561
+ all_saved = False
562
+ break
563
 
564
+ if all_saved:
565
+ st.session_state["tokens"] += total_tokens
566
+ st.session_state["uploads_count"] += 1
567
+ st.success(f" All food items uploaded successfully! You earned {total_tokens} tokens.")
568
+
569
+ # Clear the form and image for a new submission
570
+ st.session_state.pop("original_image", None)
571
+ st.session_state.pop("processed_image", None)
572
+ st.session_state["food_items"] = []
573
+ st.rerun()
574
+ else:
575
+ st.error("Failed to save some items. Please try again.")
576
  else:
577
+ st.error("Failed to upload images. Please try again.")
 
 
578
 
579
  # Display earned tokens
580
  st.sidebar.markdown("---")
 
598
  if st.sidebar.button("Terms of Service"):
599
  with open("TERMS_OF_SERVICE.md", "r") as f:
600
  terms = f.read()
601
+ st.sidebar.markdown(terms)