model-demo / app.py
hotal's picture
Create app.py
845eb23 verified
import os
import cv2
import qrcode
import numpy as np
import gradio as gr
import mediapipe as mp
import tensorflow as tf
from PIL import Image, ImageOps
# --- 1. Load the Pre-trained TFLite Model ---
# We assume 'model.tflite' is uploaded alongside this script
interpreter = tf.lite.Interpreter(model_path="model.tflite")
interpreter.allocate_tensors()
# Get input and output details
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
print("Interpreter is ready for edge predictions!")
# --- 2. Setup MediaPipe for Background Removal ---
mp_selfie_segmentation = mp.solutions.selfie_segmentation
segmenter = mp_selfie_segmentation.SelfieSegmentation(model_selection=0)
def remove_background(image_pil):
"""
Uses MediaPipe to segment the person from the background and replaces the background with white.
"""
# Convert PIL image to numpy array (RGB)
image_np = np.array(image_pil.convert("RGB"), copy=True)
# Get the segmentation mask
results = segmenter.process(image_np)
mask = results.segmentation_mask
# Create a condition: If probability > 0.5, it's a hand/person
condition = np.stack((mask,) * 3, axis=-1) > 0.5
# Create a solid white background
bg_image = np.ones(image_np.shape, dtype=np.uint8) * 255
# Combine: Keep original if condition is true, else use white background
output_image = np.where(condition, image_np, bg_image)
# Return as PIL Image
return Image.fromarray(output_image).convert("L")
# --- 3. Prediction Logic ---
def predict_rps(image):
if image is None:
return None, None
# STEP 1: Remove Background
clean_image = remove_background(image)
# STEP 2: Smart Crop & Resize to 300x300
processed_image = ImageOps.fit(clean_image, (300, 300), Image.Resampling.LANCZOS)
# STEP 3: Prepare for Model
input_data = np.array(processed_image, dtype=np.float32)
input_data = np.expand_dims(input_data, axis=-1) / 255.0
input_data = np.expand_dims(input_data, axis=0)
# STEP 4: Inference using Interpreter
interpreter.set_tensor(input_details[0]['index'], input_data)
interpreter.invoke()
output_data = interpreter.get_tensor(output_details[0]['index'])
# STEP 5: Format Results
class_names = ['Rock ✊', 'Paper ✋', 'Scissors ✌️']
prediction_dict = {class_names[i]: float(output_data[0][i]) for i in range(3)}
return processed_image, prediction_dict
# --- 4. QR Code Helper ---
def generate_qr_code(url):
if not url:
return None
qr = qrcode.QRCode(version=1, box_size=10, border=4)
qr.add_data(url)
qr.make(fit=True)
return qr.make_image(fill_color="black", back_color="white").get_image()
# --- 5. Gradio UI ---
with gr.Blocks(theme="default", title="Edge AI: ✊Rock - ✋Paper - ✌️Scissors") as demo:
gr.Markdown("# Edge AI: ✊Rock - ✋Paper - ✌️Scissors")
gr.Markdown("This model is running on TFLite! Take a photo of your hand.")
with gr.Row():
with gr.Column():
input_img = gr.Image(
type="pil",
label="Snap a Photo",
sources=["webcam", "upload"]
)
predict_btn = gr.Button("Predict", variant="primary")
with gr.Column():
output_img = gr.Image(label="What the AI Sees")
output_label = gr.Label(num_top_classes=3, label="Prediction")
predict_btn.click(
fn=predict_rps,
inputs=input_img,
outputs=[output_img, output_label]
)
# QR Code section
gr.Markdown("---")
with gr.Row():
qr_display = gr.Image(label="Share this app", show_download_button=False, height=300, width=300)
url_state = gr.Textbox(visible=False)
# In Hugging Face Spaces, we just want to display the URL.
# The JS injection might behave differently inside an iframe, but we'll keep it simple.
demo.load(
fn=generate_qr_code,
inputs=[url_state],
outputs=[qr_display],
js="() => window.location.href"
)
if __name__ == "__main__":
demo.launch()