Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,176 +1,198 @@
|
|
| 1 |
-
# app.py
|
| 2 |
import gradio as gr
|
| 3 |
import easyocr
|
| 4 |
-
import trimesh
|
| 5 |
import numpy as np
|
| 6 |
from PIL import Image
|
| 7 |
import os
|
| 8 |
-
import
|
| 9 |
-
import
|
| 10 |
|
| 11 |
-
# ---
|
| 12 |
-
#
|
| 13 |
-
|
| 14 |
|
| 15 |
-
# Initialize
|
| 16 |
reader = easyocr.Reader(['en'])
|
| 17 |
|
| 18 |
-
# --- LOGIC 1:
|
| 19 |
-
def
|
| 20 |
"""
|
| 21 |
-
|
| 22 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
try:
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
|
|
|
|
|
|
| 51 |
except Exception as e:
|
| 52 |
-
|
| 53 |
-
return None
|
| 54 |
|
| 55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
def scan_menu(image):
|
| 57 |
if image is None:
|
| 58 |
return "Please upload an image.", []
|
| 59 |
|
| 60 |
-
# 1. Read text
|
| 61 |
results = reader.readtext(image)
|
| 62 |
-
|
|
|
|
| 63 |
|
| 64 |
-
# 2. Filter for things that look like food (Simple logic for demo)
|
| 65 |
-
# In a real app, you'd verify against a food database.
|
| 66 |
-
detected_items = [text for text in text_list if len(text) > 3 and not text.isdigit()]
|
| 67 |
-
|
| 68 |
-
if not detected_items:
|
| 69 |
-
return "No readable text found.", []
|
| 70 |
-
|
| 71 |
status = f"β
Found {len(detected_items)} items!"
|
| 72 |
-
# Return status and update the Dropdown choices
|
| 73 |
return status, gr.update(choices=detected_items, value=detected_items[0] if detected_items else None)
|
| 74 |
|
| 75 |
-
# ---
|
| 76 |
-
|
| 77 |
-
# For this demo, we use the WHOLE menu image as the texture for the 3D card.
|
| 78 |
-
# In a pro version, we would crop the specific part of the image.
|
| 79 |
-
if menu_image is None:
|
| 80 |
-
return None, "Please upload a menu first."
|
| 81 |
-
|
| 82 |
-
glb_path = create_3d_card(menu_image, selected_item)
|
| 83 |
-
|
| 84 |
-
return glb_path, f"β¨ 3D Model for '{selected_item}' created! Download to view in AR."
|
| 85 |
-
|
| 86 |
-
# --- LOGIC 4: GOOGLE MAPS SIMULATOR ---
|
| 87 |
-
def search_maps(place_name):
|
| 88 |
-
# Simulating a Google Maps API call
|
| 89 |
-
time.sleep(1) # Fake loading
|
| 90 |
|
| 91 |
-
#
|
| 92 |
-
# We return a placeholder image for the demo
|
| 93 |
-
return [
|
| 94 |
-
("https://cdn-icons-png.flaticon.com/512/1904/1904221.png", "Digital Menu Found")
|
| 95 |
-
], f"π Found location: {place_name}. Menu retrieved."
|
| 96 |
-
|
| 97 |
-
# --- LOGIC 5: AI CHAT ---
|
| 98 |
-
def chat_response(message, history):
|
| 99 |
-
message = message.lower()
|
| 100 |
-
if "price" in message:
|
| 101 |
-
return "Based on the menu scan, prices usually range from $10-$20."
|
| 102 |
-
elif "recommend" in message:
|
| 103 |
-
return "The Burgers seem popular at this location based on reviews!"
|
| 104 |
-
elif "hello" in message:
|
| 105 |
-
return "Hello! Upload a menu or search a place, and I'll help you visualize the food."
|
| 106 |
-
else:
|
| 107 |
-
return "I can help you analyze the menu or generate 3D previews. Just ask!"
|
| 108 |
-
|
| 109 |
-
# --- UI BUILDING (GRADIO) ---
|
| 110 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
| 111 |
|
| 112 |
-
gr.
|
| 113 |
-
"""
|
| 114 |
-
|
| 115 |
-
### AI-Powered Menu Scanner, Google Maps Finder & AR Visualizer
|
| 116 |
-
"""
|
| 117 |
-
)
|
| 118 |
|
| 119 |
with gr.Tabs():
|
| 120 |
|
| 121 |
-
# TAB 1: SCAN
|
| 122 |
-
with gr.TabItem("πΈ Scan
|
| 123 |
with gr.Row():
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
with gr.TabItem("πΊοΈ Google Maps Search"):
|
| 140 |
with gr.Row():
|
| 141 |
-
|
| 142 |
-
|
| 143 |
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
menu_gallery = gr.Gallery(label="Found Menu Images")
|
| 147 |
|
| 148 |
-
# TAB 3:
|
| 149 |
-
with gr.TabItem("
|
| 150 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
|
| 152 |
# --- EVENT HANDLERS ---
|
| 153 |
|
| 154 |
-
# 1. Scan
|
| 155 |
scan_btn.click(
|
| 156 |
fn=scan_menu,
|
| 157 |
inputs=menu_input,
|
| 158 |
outputs=[status_output, food_dropdown]
|
| 159 |
)
|
| 160 |
|
| 161 |
-
# 2.
|
| 162 |
-
|
| 163 |
-
fn=
|
| 164 |
-
inputs=[food_dropdown,
|
| 165 |
-
outputs=[
|
| 166 |
)
|
| 167 |
|
| 168 |
-
# 3.
|
| 169 |
-
|
| 170 |
-
fn=
|
| 171 |
-
inputs=
|
| 172 |
-
outputs=
|
| 173 |
)
|
| 174 |
|
| 175 |
-
# Launch
|
| 176 |
demo.launch()
|
|
|
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import easyocr
|
|
|
|
| 3 |
import numpy as np
|
| 4 |
from PIL import Image
|
| 5 |
import os
|
| 6 |
+
import folium
|
| 7 |
+
from huggingface_hub import InferenceClient
|
| 8 |
|
| 9 |
+
# --- CONFIGURATION ---
|
| 10 |
+
# Replace with your actual token
|
| 11 |
+
HF_TOKEN = "hf_..."
|
| 12 |
|
| 13 |
+
# Initialize Tools
|
| 14 |
reader = easyocr.Reader(['en'])
|
| 15 |
|
| 16 |
+
# --- LOGIC 1: AI HEALTH ANALYZER & IMAGE GENERATOR ---
|
| 17 |
+
def analyze_food(food_name, language, api_key):
|
| 18 |
"""
|
| 19 |
+
Generates a real-world image AND detailed health analysis in the selected language.
|
| 20 |
"""
|
| 21 |
+
if not food_name:
|
| 22 |
+
return None, "Please select a food item.", ""
|
| 23 |
+
|
| 24 |
+
token = api_key if api_key else HF_TOKEN
|
| 25 |
+
client = InferenceClient(token=token)
|
| 26 |
+
|
| 27 |
+
# 1. Generate Image (Visual)
|
| 28 |
+
img_prompt = (
|
| 29 |
+
f"Professional food photography of {food_name}, "
|
| 30 |
+
"8k resolution, hyperrealistic, cinematic lighting, "
|
| 31 |
+
"macro details, steam rising, delicious, gourmet plating, "
|
| 32 |
+
"unreal engine 5 render style, depth of field."
|
| 33 |
+
)
|
| 34 |
+
|
| 35 |
try:
|
| 36 |
+
print(f"Generating image for {food_name}...")
|
| 37 |
+
generated_image = client.text_to_image(
|
| 38 |
+
prompt=img_prompt,
|
| 39 |
+
model="stabilityai/stable-diffusion-xl-base-1.0",
|
| 40 |
+
negative_prompt="cartoon, drawing, anime, text, blurry, low quality",
|
| 41 |
+
width=1024, height=1024
|
| 42 |
+
)
|
| 43 |
+
except Exception as e:
|
| 44 |
+
print(f"Image Error: {e}")
|
| 45 |
+
generated_image = None
|
| 46 |
+
|
| 47 |
+
# 2. Generate Health Info (Text) in Selected Language
|
| 48 |
+
text_prompt = (
|
| 49 |
+
f"Act as a nutritionist. Analyze the food item '{food_name}'. "
|
| 50 |
+
f"Provide the response in {language} language. "
|
| 51 |
+
"Format the response strictly with two sections:\n"
|
| 52 |
+
"1. Health Benefits\n"
|
| 53 |
+
"2. Potential Consequences or Cons (e.g., high calories, allergies).\n"
|
| 54 |
+
"Keep it concise and bulleted."
|
| 55 |
+
)
|
| 56 |
+
|
| 57 |
+
try:
|
| 58 |
+
response = client.text_generation(
|
| 59 |
+
prompt=text_prompt,
|
| 60 |
+
model="tiiuae/falcon-7b-instruct", # Using a fast text model
|
| 61 |
+
max_new_tokens=400,
|
| 62 |
+
temperature=0.7
|
| 63 |
+
)
|
| 64 |
+
health_info = response
|
| 65 |
except Exception as e:
|
| 66 |
+
health_info = f"Could not retrieve health data: {e}"
|
|
|
|
| 67 |
|
| 68 |
+
return generated_image, health_info
|
| 69 |
+
|
| 70 |
+
# --- LOGIC 2: INTERACTIVE MAP (SCROLLABLE) ---
|
| 71 |
+
def get_map_html(location_name="Bahawalpur"):
|
| 72 |
+
"""
|
| 73 |
+
Creates an interactive HTML map centered on a location.
|
| 74 |
+
"""
|
| 75 |
+
# Default coordinates (Bahawalpur)
|
| 76 |
+
start_coords = [29.3544, 71.6911]
|
| 77 |
+
|
| 78 |
+
# If user searches specific place, we could geocode it (Mocking change for demo)
|
| 79 |
+
if location_name.lower() == "islamabad":
|
| 80 |
+
start_coords = [33.6844, 73.0479]
|
| 81 |
+
elif location_name.lower() == "lahore":
|
| 82 |
+
start_coords = [31.5497, 74.3436]
|
| 83 |
+
|
| 84 |
+
# Create Map
|
| 85 |
+
m = folium.Map(location=start_coords, zoom_start=13)
|
| 86 |
+
|
| 87 |
+
# Add Marker
|
| 88 |
+
folium.Marker(
|
| 89 |
+
start_coords,
|
| 90 |
+
popup=f"<i>{location_name}</i>",
|
| 91 |
+
tooltip="Click me!"
|
| 92 |
+
).add_to(m)
|
| 93 |
+
|
| 94 |
+
return m._repr_html_()
|
| 95 |
+
|
| 96 |
+
# --- LOGIC 3: MENU SCANNING ---
|
| 97 |
def scan_menu(image):
|
| 98 |
if image is None:
|
| 99 |
return "Please upload an image.", []
|
| 100 |
|
|
|
|
| 101 |
results = reader.readtext(image)
|
| 102 |
+
# Filter for food-like text (longer than 3 chars, not numbers)
|
| 103 |
+
detected_items = [res[1] for res in results if len(res[1]) > 3 and not res[1].isdigit()]
|
| 104 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
status = f"β
Found {len(detected_items)} items!"
|
|
|
|
| 106 |
return status, gr.update(choices=detected_items, value=detected_items[0] if detected_items else None)
|
| 107 |
|
| 108 |
+
# --- UI LAYOUT ---
|
| 109 |
+
with gr.Blocks(theme=gr.themes.Soft(primary_hue="orange", secondary_hue="gray")) as demo:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
|
| 111 |
+
gr.Markdown("# π₯ MenuVision AI: Health & visual Analyzer")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
|
| 113 |
+
with gr.Row():
|
| 114 |
+
api_input = gr.Textbox(label="Hugging Face Token (Optional)", type="password", placeholder="Paste token here if not hardcoded")
|
| 115 |
+
language_drop = gr.Dropdown(label="π Select Language", choices=["English", "Urdu", "French", "Spanish", "Arabic"], value="English")
|
|
|
|
|
|
|
|
|
|
| 116 |
|
| 117 |
with gr.Tabs():
|
| 118 |
|
| 119 |
+
# --- TAB 1: SCAN & HEALTH ANALYSIS ---
|
| 120 |
+
with gr.TabItem("πΈ Scan & Analyze"):
|
| 121 |
with gr.Row():
|
| 122 |
+
# LEFT COLUMN: INPUT
|
| 123 |
+
with gr.Column(scale=1):
|
| 124 |
+
menu_input = gr.Image(type="numpy", label="1. Upload Menu Photo")
|
| 125 |
+
scan_btn = gr.Button("π Scan Text", variant="secondary")
|
| 126 |
+
|
| 127 |
+
gr.Markdown("---")
|
| 128 |
+
status_output = gr.Textbox(label="Status", interactive=False)
|
| 129 |
+
food_dropdown = gr.Dropdown(label="2. Select Detected Food", choices=[])
|
| 130 |
+
analyze_btn = gr.Button("β¨ Analyze Health & Generate Image", variant="primary")
|
| 131 |
|
| 132 |
+
# RIGHT COLUMN: OUTPUT
|
| 133 |
+
with gr.Column(scale=2):
|
| 134 |
+
# 1. Real World Image
|
| 135 |
+
result_image = gr.Image(label="Real-World Representation", type="pil", height=400)
|
| 136 |
+
|
| 137 |
+
# 2. Health Columns
|
| 138 |
+
gr.Markdown("### π©Ί Nutritional Analysis")
|
| 139 |
+
health_output = gr.Textbox(label="Benefits & Consequences", lines=10)
|
| 140 |
+
|
| 141 |
+
# --- TAB 2: INTERACTIVE MAPS ---
|
| 142 |
+
with gr.TabItem("πΊοΈ Interactive Map"):
|
|
|
|
| 143 |
with gr.Row():
|
| 144 |
+
place_search = gr.Textbox(label="Search Location (e.g., Islamabad)", placeholder="Type a city...")
|
| 145 |
+
map_btn = gr.Button("Update Map")
|
| 146 |
|
| 147 |
+
# This HTML component holds the interactive scrollable map
|
| 148 |
+
map_html = gr.HTML(value=get_map_html(), label="Scrollable Map")
|
|
|
|
| 149 |
|
| 150 |
+
# --- TAB 3: ABOUT ME ---
|
| 151 |
+
with gr.TabItem("π¨βπ» About Developer"):
|
| 152 |
+
with gr.Row():
|
| 153 |
+
with gr.Column(scale=1):
|
| 154 |
+
# Placeholder for your profile pic
|
| 155 |
+
gr.Image("https://cdn-icons-png.flaticon.com/512/4140/4140048.png", width=200, show_label=False, show_download_button=False)
|
| 156 |
+
|
| 157 |
+
with gr.Column(scale=3):
|
| 158 |
+
gr.Markdown("""
|
| 159 |
+
### π Hi, I'm Abdullah!
|
| 160 |
+
|
| 161 |
+
**Computer Engineering Student | AI Enthusiast | Web Developer**
|
| 162 |
+
|
| 163 |
+
I am currently an undergraduate student at **COMSATS University Islamabad**, specializing in Computer Engineering.
|
| 164 |
+
I have a passion for merging **Embedded Systems** with **Generative AI** to create real-world solutions.
|
| 165 |
+
|
| 166 |
+
* **Role:** Intern Web Developer at MyK Global Forwarding.
|
| 167 |
+
* **Focus:** TinyML, IoT, and GenAI Applications.
|
| 168 |
+
* **Location:** Bahawalpur / Islamabad.
|
| 169 |
+
|
| 170 |
+
**About MenuVision AI:**
|
| 171 |
+
This project was designed to help people make better dietary choices by visualizing food from plain text menus and understanding the health implications immediately.
|
| 172 |
+
""")
|
| 173 |
|
| 174 |
# --- EVENT HANDLERS ---
|
| 175 |
|
| 176 |
+
# 1. Scan Button
|
| 177 |
scan_btn.click(
|
| 178 |
fn=scan_menu,
|
| 179 |
inputs=menu_input,
|
| 180 |
outputs=[status_output, food_dropdown]
|
| 181 |
)
|
| 182 |
|
| 183 |
+
# 2. Analyze Button (Image + Health Info)
|
| 184 |
+
analyze_btn.click(
|
| 185 |
+
fn=analyze_food,
|
| 186 |
+
inputs=[food_dropdown, language_drop, api_input],
|
| 187 |
+
outputs=[result_image, health_output]
|
| 188 |
)
|
| 189 |
|
| 190 |
+
# 3. Map Update
|
| 191 |
+
map_btn.click(
|
| 192 |
+
fn=get_map_html,
|
| 193 |
+
inputs=place_search,
|
| 194 |
+
outputs=map_html
|
| 195 |
)
|
| 196 |
|
| 197 |
+
# Launch App
|
| 198 |
demo.launch()
|