import gradio as gr
import tensorflow as tf
import numpy as np
from PIL import Image
import json
import requests
import io
import base64
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "-1" # Disable GPU
# ===== CONFIGURACIÓN =====
PLANTNET_CONFIG = {
"base_url": "https://my-api.plantnet.org/v2/identify/all",
"api_key": "2b10GtUDt6p1whX94wlEiR3CG",
"timeout": 10,
"lang": "es" # Español
}
# ===== VARIABLES GLOBALES =====
MODEL_LOADED = False
model = None
labels = []
# ===== FUNCIONES DE UTILIDAD =====
def load_model():
global model, labels, MODEL_LOADED
try:
model = tf.keras.models.load_model("flores_modelo (2).h5")
with open("clases_orden_oxford.json", "r") as f:
class_indices = json.load(f)
labels = [None] * len(class_indices)
for class_name, idx in class_indices.items():
labels[idx] = class_name.replace("_", " ").title()
MODEL_LOADED = True
except Exception as e:
print(f"Error al cargar el modelo: {e}")
MODEL_LOADED = False
def image_to_base64(image_path):
try:
with open(image_path, "rb") as img_file:
return base64.b64encode(img_file.read()).decode('utf-8')
except:
return None
def preprocess_image(image):
image = image.resize((224, 224))
img_array = np.array(image) / 255.0
if img_array.shape[-1] == 4:
img_array = img_array[..., :3]
return np.expand_dims(img_array, axis=0)
# ===== INTEGRACIÓN CON PLANTNET =====
def get_flower_info_from_plantnet(flower_name, image_array):
try:
image_pil = Image.fromarray((image_array[0] * 255).astype(np.uint8))
img_byte_arr = io.BytesIO()
image_pil.save(img_byte_arr, format='JPEG')
img_byte_arr.seek(0)
url = f"{PLANTNET_CONFIG['base_url']}?api-key={PLANTNET_CONFIG['api_key']}&lang={PLANTNET_CONFIG['lang']}"
files = {'images': ('image.jpg', img_byte_arr, 'image/jpeg')}
data = {'organs': 'flower'}
response = requests.post(url, files=files, data=data, timeout=PLANTNET_CONFIG['timeout'])
if response.status_code == 200:
return parse_plantnet_response(response.json(), flower_name)
else:
print(f"Error en PlantNet: {response.status_code}")
return get_fallback_info(flower_name)
except requests.exceptions.Timeout:
print("Tiempo de espera agotado en PlantNet")
return get_fallback_info(flower_name)
except Exception as e:
print(f"PlantNet error: {e}")
return get_fallback_info(flower_name)
def parse_plantnet_response(data, flower_name):
if 'results' in data and len(data['results']) > 0:
results = data['results'][:3]
info = f"""
🌸 {flower_name}
📊 Identificación Científica
"""
for i, result in enumerate(results, 1):
species = result.get('species', {})
scientific_name = species.get('scientificNameWithoutAuthor', 'N/A')
authorship = species.get('scientificNameAuthorship', '')
common_names = species.get('commonNames', [])
family = species.get('family', {}).get('scientificNameWithoutAuthor', 'N/A')
genus = species.get('genus', {}).get('scientificNameWithoutAuthor', 'N/A')
score = result.get('score', 0)
common_names_str = ', '.join(common_names[:3]) if common_names else 'No disponible'
info += f"""
#{i}
{scientific_name} {authorship}
Nombres comunes: {common_names_str}
Familia: {family}
Género: {genus}
"""
info += """
🌿 Cuidados Generales
☀️
Luz: Luz solar directa o indirecta
💧
Riego: Mantener húmedo, evitar exceso
🌡️
Temperatura: Evitar cambios bruscos
🌱
Suelo: Bien drenado y rico en nutrientes
"""
return info
return get_fallback_info(flower_name)
def get_fallback_info(flower_name):
return f"""
🌸 {flower_name}
PlantNet no disponible
📖 Información General
Identificado por nuestro modelo de IA entrenado en el conjunto de datos Oxford 102 Flowers.
🌺 Características
- Estructuras reproductivas de la planta
- Varios colores y formas
- Evolucionadas para atraer polinizadores
🎯 Cuidados Básicos
- Buena iluminación según la especie
- Riego regular sin exceso
- Temperatura estable
- Fertilización adecuada
"""
# ===== LÓGICA DE PREDICCIÓN =====
def predict(image):
if not image:
return "No se cargó ninguna imagen", "0%", """
⚠️ Imagen requerida
Por favor, carga una imagen de una flor para iniciar la identificación.
"""
if not MODEL_LOADED:
return "Error en el modelo", "0%", """
🚫 Modelo no disponible
No se pudo cargar el modelo de clasificación. Verifica los archivos del modelo.
"""
try:
img_array = preprocess_image(image)
preds = model.predict(img_array)
class_idx = np.argmax(preds[0])
confidence = preds[0][class_idx]
label_name = labels[class_idx]
flower_details = get_flower_info_from_plantnet(label_name, img_array)
return label_name, f"{confidence:.2%}", flower_details
except Exception as e:
return "Error", "0%", f"""
❌ Error de predicción
Error durante el procesamiento: {str(e)}
"""
# ===== CSS PARA EL FONDO DE LA APLICACIÓN =====
custom_css = """
.gradio-container {
background: #1E2A44;
min-height: 100vh;
}
"""
# ===== JAVASCRIPT PARA OPTIMIZACIÓN DE CÁMARA =====
camera_js_improved = """
"""
# ===== APLICACIÓN PRINCIPAL =====
# Cargar el modelo al inicio
load_model()
img3_b64 = image_to_base64("img3.png")
img2_b64 = image_to_base64("img2.png")
with gr.Blocks(theme=gr.themes.Soft(), css=custom_css, title="🌸 Flower ") as demo:
header_html = f'''
{'
' if img3_b64 else '
'}
IDENTIFICADOR DE FLORES
Identifica cualquier flor en cuestión de segundos
Oxford 102 Flowers + PlantNet
{'
' if img2_b64 else '
'}
'''
gr.HTML(header_html)
with gr.Row():
with gr.Column(scale=1):
image_input = gr.Image(type="pil", label="📷 Cargar Imagen de Flor", height=350, sources=["upload", "webcam", "clipboard"])
predict_btn = gr.Button("🔍 Identificar Flor", variant="primary")
gr.HTML(f'📊 Estado del Sistema
Modelo: {"✅ Activo" if MODEL_LOADED else "❌ Error"}
Clases: {len(labels)}
')
with gr.Column(scale=1):
result_label = gr.Textbox(label="🌼 Flor Identificada", interactive=False, placeholder="El nombre de la flor aparecerá aquí...")
result_conf = gr.Textbox(label="📊 Confianza", interactive=False, placeholder="El nivel de confianza aparecerá aquí...")
flower_info_output = gr.HTML(value='🌸 ¡Bienvenido!
Carga una imagen de una flor para iniciar la identificación.
')
predict_btn.click(fn=predict, inputs=image_input, outputs=[result_label, result_conf, flower_info_output])
gr.HTML(camera_js_improved)
if __name__ == "__main__":
demo.launch(share=False)