Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -44,37 +44,37 @@ current_model = "Model Mini"
|
|
44 |
new_model = "Food Vision"
|
45 |
# ... (class_names, top_ten_dict, last_ten_dict remain the same) ...
|
46 |
class_names = ['apple_pie', 'baby_back_ribs', 'baklava', 'beef_carpaccio', 'beef_tartare',
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
|
67 |
top_ten_dict = {
|
68 |
"class_name": ["edamame", "macarons", "oysters", "pho", "mussels",
|
69 |
"sashimi", "seaweed_salad", "dumplings", "guacamole", "onion_rings"],
|
70 |
"f1-score": [0.964427, 0.900433, 0.853119, 0.852652, 0.850622,
|
71 |
-
|
72 |
}
|
73 |
last_ten_dict = {
|
74 |
"class_name": ["chocolate_mousse", "tuna_tartare", "scallops", "huevos_rancheros",
|
75 |
"foie_gras", "steak", "bread_pudding", "ravioli", "pork_chop", "apple_pie"],
|
76 |
"f1-score": [0.413793, 0.399254, 0.383693, 0.367698, 0.354497,
|
77 |
-
|
78 |
}
|
79 |
|
80 |
# 🔹 Custom CSS for Alignment and Spacing
|
@@ -86,7 +86,7 @@ st.markdown(
|
|
86 |
display: flex;
|
87 |
flex-direction: column;
|
88 |
align-items: center; /* Keep horizontal centering */
|
89 |
-
justify-content: flex-start; /* Align content to the top */
|
90 |
text-align: center;
|
91 |
width: 100%;
|
92 |
min-height: 100px; /* Reduced minimum height */
|
@@ -97,9 +97,9 @@ st.markdown(
|
|
97 |
|
98 |
/* Ensure subheaders within columns have less top margin */
|
99 |
.centered h3 { /* Targets the subheaders like "1. Provide Image" */
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
}
|
104 |
|
105 |
/* Style file uploader (ensure consistent padding) */
|
@@ -112,7 +112,7 @@ st.markdown(
|
|
112 |
margin-bottom: 10px; /* Space below uploader */
|
113 |
}
|
114 |
div[data-testid="stCameraInput"] label { /* Style the camera input label */
|
115 |
-
|
116 |
}
|
117 |
|
118 |
|
@@ -130,46 +130,63 @@ st.markdown(
|
|
130 |
margin-bottom: 10px; /* Reduced space below image */
|
131 |
}
|
132 |
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
|
163 |
-
|
164 |
-
|
165 |
margin-bottom: 5px !important; /* Space between header and caption */
|
166 |
-
|
167 |
|
168 |
-
|
169 |
-
|
170 |
margin-top: -15px !important; /* Pull header closer to divider */
|
171 |
}
|
172 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
173 |
|
174 |
</style>
|
175 |
""",
|
@@ -213,12 +230,12 @@ NUM_CLASSES = 101 # Example number of food classes
|
|
213 |
# --- Data Augmentation Layer ---
|
214 |
# Define data augmentation transformations here
|
215 |
data_augmentation = tf.keras.Sequential([
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
], name="data_augmentation")
|
223 |
|
224 |
# --- Build the Model using Functional API ---
|
@@ -311,7 +328,7 @@ base_model.trainable = True
|
|
311 |
# fine_tune_at = 100 # Example: Unfreeze layers from index 100 onwards
|
312 |
|
313 |
# for layer in base_model.layers[:fine_tune_at]:
|
314 |
-
#
|
315 |
|
316 |
# --- Re-compile the Model with a Lower Learning Rate ---
|
317 |
# Lowering the learning rate is crucial for fine-tuning to avoid
|
@@ -496,8 +513,10 @@ with cols[0]:
|
|
496 |
|
497 |
# --- Column 2: Arrow 1 ---
|
498 |
with cols[1]:
|
499 |
-
#
|
500 |
-
st.markdown('<div class="centered" style="justify-content:
|
|
|
|
|
501 |
|
502 |
|
503 |
# --- Column 3: Model Selection & Prediction ---
|
@@ -517,7 +536,7 @@ with cols[2]:
|
|
517 |
model_image_path = ""
|
518 |
|
519 |
if chosen_model == current_model:
|
520 |
-
model_image_path = "brain.png"
|
521 |
model_path_to_use = "model_mini_Food101.keras"
|
522 |
elif chosen_model == new_model:
|
523 |
model_image_path = "content/creativity_15557951.png"
|
@@ -552,8 +571,10 @@ with cols[2]:
|
|
552 |
|
553 |
# --- Column 4: Arrow 2 ---
|
554 |
with cols[3]:
|
555 |
-
#
|
556 |
-
st.markdown('<div class="centered" style="justify-content:
|
|
|
|
|
557 |
|
558 |
|
559 |
# --- Column 5: Output ---
|
@@ -577,7 +598,7 @@ with cols[4]:
|
|
577 |
st.write(f"Confidence: {probability:.1%}") # Slightly less verbose confidence
|
578 |
|
579 |
elif predict_button:
|
580 |
-
|
581 |
else:
|
582 |
st.info("Result will appear here.")
|
583 |
|
@@ -585,4 +606,4 @@ with cols[4]:
|
|
585 |
|
586 |
|
587 |
# --- Footer or Final Divider ---
|
588 |
-
|
|
|
44 |
new_model = "Food Vision"
|
45 |
# ... (class_names, top_ten_dict, last_ten_dict remain the same) ...
|
46 |
class_names = ['apple_pie', 'baby_back_ribs', 'baklava', 'beef_carpaccio', 'beef_tartare',
|
47 |
+
'beet_salad', 'beignets', 'bibimbap', 'bread_pudding', 'breakfast_burrito',
|
48 |
+
'bruschetta', 'caesar_salad', 'cannoli', 'caprese_salad', 'carrot_cake',
|
49 |
+
'ceviche', 'cheese_plate', 'cheesecake', 'chicken_curry', 'chicken_quesadilla',
|
50 |
+
'chicken_wings', 'chocolate_cake', 'chocolate_mousse', 'churros', 'clam_chowder',
|
51 |
+
'club_sandwich', 'crab_cakes', 'creme_brulee', 'croque_madame', 'cup_cakes',
|
52 |
+
'deviled_eggs', 'donuts', 'dumplings', 'edamame', 'eggs_benedict', 'escargots',
|
53 |
+
'falafel', 'filet_mignon', 'fish_and_chips', 'foie_gras', 'french_fries',
|
54 |
+
'french_onion_soup', 'french_toast', 'fried_calamari', 'fried_rice',
|
55 |
+
'frozen_yogurt', 'garlic_bread', 'gnocchi', 'greek_salad',
|
56 |
+
'grilled_cheese_sandwich', 'grilled_salmon', 'guacamole', 'gyoza', 'hamburger',
|
57 |
+
'hot_and_sour_soup', 'hot_dog', 'huevos_rancheros', 'hummus', 'ice_cream',
|
58 |
+
'lasagna', 'lobster_bisque', 'lobster_roll_sandwich', 'macaroni_and_cheese',
|
59 |
+
'macarons', 'miso_soup', 'mussels', 'nachos', 'omelette', 'onion_rings',
|
60 |
+
'oysters', 'pad_thai', 'paella', 'pancakes', 'panna_cotta', 'peking_duck',
|
61 |
+
'pho', 'pizza', 'pork_chop', 'poutine', 'prime_rib', 'pulled_pork_sandwich',
|
62 |
+
'ramen', 'ravioli', 'red_velvet_cake', 'risotto', 'samosa', 'sashimi',
|
63 |
+
'scallops', 'seaweed_salad', 'shrimp_and_grits', 'spaghetti_bolognese',
|
64 |
+
'spaghetti_carbonara', 'spring_rolls', 'steak', 'strawberry_shortcake',
|
65 |
+
'sushi', 'tacos', 'takoyaki', 'tiramisu', 'tuna_tartare', 'waffles']
|
66 |
|
67 |
top_ten_dict = {
|
68 |
"class_name": ["edamame", "macarons", "oysters", "pho", "mussels",
|
69 |
"sashimi", "seaweed_salad", "dumplings", "guacamole", "onion_rings"],
|
70 |
"f1-score": [0.964427, 0.900433, 0.853119, 0.852652, 0.850622,
|
71 |
+
0.844794, 0.834356, 0.833006, 0.83209, 0.831967]
|
72 |
}
|
73 |
last_ten_dict = {
|
74 |
"class_name": ["chocolate_mousse", "tuna_tartare", "scallops", "huevos_rancheros",
|
75 |
"foie_gras", "steak", "bread_pudding", "ravioli", "pork_chop", "apple_pie"],
|
76 |
"f1-score": [0.413793, 0.399254, 0.383693, 0.367698, 0.354497,
|
77 |
+
0.340426, 0.340045, 0.339785, 0.324826, 0.282407]
|
78 |
}
|
79 |
|
80 |
# 🔹 Custom CSS for Alignment and Spacing
|
|
|
86 |
display: flex;
|
87 |
flex-direction: column;
|
88 |
align-items: center; /* Keep horizontal centering */
|
89 |
+
justify-content: flex-start; /* Align content to the top by default */
|
90 |
text-align: center;
|
91 |
width: 100%;
|
92 |
min-height: 100px; /* Reduced minimum height */
|
|
|
97 |
|
98 |
/* Ensure subheaders within columns have less top margin */
|
99 |
.centered h3 { /* Targets the subheaders like "1. Provide Image" */
|
100 |
+
margin-top: 0px !important;
|
101 |
+
padding-top: 0px !important;
|
102 |
+
margin-bottom: 15px !important; /* Add space below subheader */
|
103 |
}
|
104 |
|
105 |
/* Style file uploader (ensure consistent padding) */
|
|
|
112 |
margin-bottom: 10px; /* Space below uploader */
|
113 |
}
|
114 |
div[data-testid="stCameraInput"] label { /* Style the camera input label */
|
115 |
+
margin-bottom: 10px; /* Space below camera input */
|
116 |
}
|
117 |
|
118 |
|
|
|
130 |
margin-bottom: 10px; /* Reduced space below image */
|
131 |
}
|
132 |
|
133 |
+
/* Align the TOPS of the columns (This might be overridden by .centered justify-content) */
|
134 |
+
div[data-testid="stVerticalBlock"] div[data-testid="stHorizontalBlock"] {
|
135 |
+
align-items: flex-start !important; /* Align column tops */
|
136 |
+
}
|
137 |
|
138 |
+
/* Style the radio buttons */
|
139 |
+
div[data-testid="stRadio"] > label {
|
140 |
+
font-weight: bold;
|
141 |
+
margin-bottom: 5px !important; /* Reduced margin */
|
142 |
+
padding-top: 0 !important;
|
143 |
+
}
|
144 |
+
div[data-testid="stRadio"] > div {
|
145 |
+
display: flex;
|
146 |
+
justify-content: center;
|
147 |
+
gap: 10px; /* Reduced gap */
|
148 |
+
margin-bottom: 10px; /* Add space below radio group */
|
149 |
+
}
|
150 |
|
151 |
+
/* Style the button */
|
152 |
+
div[data-testid="stButton"] > button {
|
153 |
+
width: 80%;
|
154 |
+
margin-top: 15px; /* Reduced margin */
|
155 |
+
}
|
156 |
|
157 |
+
/* Reduce space BELOW the caption ABOVE the columns */
|
158 |
+
div[data-testid="stCaptionContainer"] {
|
159 |
+
padding-bottom: 0px !important;
|
160 |
+
margin-bottom: -10px !important; /* Negative margin pulls following elements up */
|
161 |
+
}
|
162 |
|
163 |
+
/* Reduce space ABOVE the main H2 header for the demo section */
|
164 |
+
h2[data-testid="stHeading"]:has(+ div[data-testid="stCaptionContainer"]) {
|
165 |
margin-bottom: 5px !important; /* Space between header and caption */
|
166 |
+
}
|
167 |
|
168 |
+
/* Reduce space below the final divider before the demo H2 header */
|
169 |
+
hr[data-testid="stDivider"] + h2[data-testid="stHeading"] {
|
170 |
margin-top: -15px !important; /* Pull header closer to divider */
|
171 |
}
|
172 |
|
173 |
+
/* --- NEW CSS for Larger Centered Arrows --- */
|
174 |
+
.arrow-indicator {
|
175 |
+
font-size: 3em; /* Make the arrow much bigger */
|
176 |
+
display: block; /* Ensure it takes up its own line */
|
177 |
+
text-align: center; /* Center the arrow horizontally within its container */
|
178 |
+
line-height: 1; /* Adjust line height if needed */
|
179 |
+
margin: auto; /* Center the block element itself if needed */
|
180 |
+
}
|
181 |
+
|
182 |
+
/* Explicitly center the content vertically for the arrow columns */
|
183 |
+
/* Using :has() is modern CSS, may need alternative for older browsers */
|
184 |
+
.centered:has(.arrow-indicator) {
|
185 |
+
justify-content: center !important; /* Explicitly center content vertically */
|
186 |
+
padding-top: 0 !important; /* Remove any unwanted top padding */
|
187 |
+
min-height: 150px; /* Ensure enough height for centering relative to image */
|
188 |
+
}
|
189 |
+
|
190 |
|
191 |
</style>
|
192 |
""",
|
|
|
230 |
# --- Data Augmentation Layer ---
|
231 |
# Define data augmentation transformations here
|
232 |
data_augmentation = tf.keras.Sequential([
|
233 |
+
layers.RandomFlip("horizontal"),
|
234 |
+
layers.RandomRotation(0.2),
|
235 |
+
layers.RandomZoom(0.2),
|
236 |
+
layers.RandomHeight(0.2),
|
237 |
+
layers.RandomWidth(0.2),
|
238 |
+
# Rescaling might be part of EfficientNet preprocessing, check docs
|
239 |
], name="data_augmentation")
|
240 |
|
241 |
# --- Build the Model using Functional API ---
|
|
|
328 |
# fine_tune_at = 100 # Example: Unfreeze layers from index 100 onwards
|
329 |
|
330 |
# for layer in base_model.layers[:fine_tune_at]:
|
331 |
+
# layer.trainable = False
|
332 |
|
333 |
# --- Re-compile the Model with a Lower Learning Rate ---
|
334 |
# Lowering the learning rate is crucial for fine-tuning to avoid
|
|
|
513 |
|
514 |
# --- Column 2: Arrow 1 ---
|
515 |
with cols[1]:
|
516 |
+
# Use inline style to center content vertically
|
517 |
+
st.markdown('<div class="centered" style="justify-content: center;">', unsafe_allow_html=True)
|
518 |
+
st.markdown('<span class="arrow-indicator">➡️</span>', unsafe_allow_html=True) # Apply arrow-indicator class
|
519 |
+
st.markdown('</div>', unsafe_allow_html=True)
|
520 |
|
521 |
|
522 |
# --- Column 3: Model Selection & Prediction ---
|
|
|
536 |
model_image_path = ""
|
537 |
|
538 |
if chosen_model == current_model:
|
539 |
+
model_image_path = "content/brain.png"
|
540 |
model_path_to_use = "model_mini_Food101.keras"
|
541 |
elif chosen_model == new_model:
|
542 |
model_image_path = "content/creativity_15557951.png"
|
|
|
571 |
|
572 |
# --- Column 4: Arrow 2 ---
|
573 |
with cols[3]:
|
574 |
+
# Use inline style to center content vertically
|
575 |
+
st.markdown('<div class="centered" style="justify-content: center;">', unsafe_allow_html=True)
|
576 |
+
st.markdown('<span class="arrow-indicator">➡️</span>', unsafe_allow_html=True) # Apply arrow-indicator class
|
577 |
+
st.markdown('</div>', unsafe_allow_html=True)
|
578 |
|
579 |
|
580 |
# --- Column 5: Output ---
|
|
|
598 |
st.write(f"Confidence: {probability:.1%}") # Slightly less verbose confidence
|
599 |
|
600 |
elif predict_button:
|
601 |
+
st.error("Prediction failed or image invalid.")
|
602 |
else:
|
603 |
st.info("Result will appear here.")
|
604 |
|
|
|
606 |
|
607 |
|
608 |
# --- Footer or Final Divider ---
|
609 |
+
st.divider() # Optional: remove if you want less space at the bottom
|