Proyecto / index.html
dfernandezl12's picture
Upload 11 files
c1da183 verified
Raw
History Blame Contribute Delete
11.5 kB
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PlantAI - Detección Multimodelo</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/lucide@latest"></script>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
body { font-family: 'Plus Jakarta Sans', sans-serif; }
.glass-effect { background: rgba(255, 255, 255, 0.8); backdrop-filter: blur(12px); }
.gradient-bg { background: linear-gradient(135deg, #f0fdf4 0%, #ffffff 100%); }
</style>
</head>
<body class="gradient-bg min-h-screen text-gray-800">
<nav class="sticky top-0 z-40 w-full border-b border-green-100 bg-white/70 backdrop-blur-md">
<div class="max-w-7xl mx-auto px-4 h-16 flex items-center justify-between">
<div class="flex items-center gap-2">
<div class="bg-green-600 p-1.5 rounded-lg">
<i data-lucide="leaf" class="text-white w-5 h-5"></i>
</div>
<span class="text-xl font-bold tracking-tight text-gray-900">Plant<span class="text-green-600">AI</span></span>
</div>
</div>
</nav>
<main class="max-w-7xl mx-auto px-4 py-8">
<div class="grid grid-cols-1 lg:grid-cols-12 gap-8">
<div class="lg:col-span-4 space-y-6">
<div class="bg-white rounded-3xl shadow-sm border border-green-100 p-6">
<h3 class="text-lg font-bold text-gray-900 mb-4 flex items-center gap-2">
<i data-lucide="activity" class="text-green-600 w-5 h-5"></i>
Estado del Sistema
</h3>
<div class="grid grid-cols-2 gap-4">
<div class="p-4 bg-green-50 rounded-2xl border border-green-100 text-center">
<div class="text-2xl font-bold text-green-700">5</div>
<div class="text-xs font-medium text-green-600 uppercase">Modelos</div>
</div>
<div class="p-4 bg-blue-50 rounded-2xl border border-blue-100 text-center">
<div class="text-2xl font-bold text-blue-700">38</div>
<div class="text-xs font-medium text-blue-600 uppercase">Clases</div>
</div>
</div>
</div>
<div class="bg-green-600 rounded-3xl p-6 text-white shadow-lg">
<h4 class="font-bold text-lg mb-2">Análisis Multimodal</h4>
<p class="text-green-50 text-sm leading-relaxed">
Tu imagen será procesada por 5 arquitecturas diferentes (Básico, CNN, Dropout, Data Augmentation y Escala de Grises) para garantizar la máxima precisión.
</p>
</div>
</div>
<div class="lg:col-span-8 space-y-6">
<div class="bg-white rounded-3xl shadow-sm border border-gray-100 p-8">
<div id="drop-zone" class="relative group border-2 border-dashed border-gray-200 rounded-2xl p-12 text-center transition-all hover:border-green-400 hover:bg-green-50/50 cursor-pointer">
<input type="file" id="file-input" class="hidden" accept="image/*">
<div id="upload-placeholder">
<div class="w-20 h-20 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4">
<i data-lucide="camera" class="text-green-600 w-10 h-10"></i>
</div>
<h3 class="text-xl font-bold text-gray-900 mb-2">Subir imagen de la hoja</h3>
<p class="text-gray-500 text-sm">Haz clic o arrastra para analizar</p>
</div>
<img id="image-preview" class="hidden rounded-2xl max-h-80 mx-auto shadow-xl ring-4 ring-white">
</div>
<button id="predict-btn" disabled class="w-full mt-6 bg-gray-900 text-white py-4 rounded-2xl font-bold hover:bg-green-600 disabled:bg-gray-200 disabled:text-gray-400 transition-all flex items-center justify-center gap-3">
<i data-lucide="zap" class="w-5 h-5"></i>
ANALIZAR EN TODOS LOS MODELOS
</button>
</div>
<div id="results-section" class="hidden space-y-4">
<h3 class="text-xl font-bold text-gray-900 mb-4">Resultados Comparativos</h3>
<div id="comparison-grid" class="grid gap-4">
</div>
</div>
<div id="empty-state" class="bg-gray-50 border border-dashed border-gray-200 rounded-3xl py-20 text-center">
<i data-lucide="layout-grid" class="w-12 h-12 text-gray-300 mx-auto mb-4"></i>
<p class="text-gray-500 font-medium">Sube una imagen para ver el diagnóstico</p>
</div>
</div>
</div>
</main>
<div id="loader" class="hidden fixed inset-0 z-50 bg-white/90 backdrop-blur-md flex flex-col items-center justify-center">
<div class="relative w-24 h-24 mb-6">
<div class="absolute inset-0 border-4 border-green-600 rounded-full border-t-transparent animate-spin"></div>
</div>
<h2 class="text-2xl font-bold text-gray-900">Procesando Modelos...</h2>
</div>
<script>
lucide.createIcons();
const dropZone = document.getElementById('drop-zone');
const fileInput = document.getElementById('file-input');
const preview = document.getElementById('image-preview');
const placeholder = document.getElementById('upload-placeholder');
const predictBtn = document.getElementById('predict-btn');
const grid = document.getElementById('comparison-grid');
const emptyState = document.getElementById('empty-state');
const resultsSection = document.getElementById('results-section');
dropZone.onclick = () => fileInput.click();
fileInput.onchange = (e) => {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (ev) => {
preview.src = ev.target.result;
preview.classList.remove('hidden');
placeholder.classList.add('hidden');
predictBtn.disabled = false;
};
reader.readAsDataURL(file);
}
};
predictBtn.onclick = async () => {
const formData = new FormData();
formData.append('file', fileInput.files[0]);
const loader = document.getElementById('loader');
loader.classList.remove('hidden');
try {
const response = await fetch('/predict_all', { method: 'POST', body: formData });
const results = await response.json();
emptyState.classList.add('hidden');
resultsSection.classList.remove('hidden');
grid.innerHTML = '';
results.forEach(res => {
// Definimos el estado general basado en tu lógica de Python
const isHealthy = res.status === "Sana";
// Usamos colores para la etiqueta de estado, pero azul para la interfaz técnica
const badgeColor = isHealthy ? "green" : "orange";
const labelText = isHealthy ? "SANA / SALUDABLE" : "PROBLEMA DETECTADO";
grid.innerHTML += `
<div class="bg-white border border-gray-200 rounded-2xl p-5 shadow-sm">
<div class="flex justify-between items-start mb-4">
<div>
<h4 class="font-bold text-gray-900">${res.name}</h4>
<span class="text-[10px] bg-gray-100 text-gray-500 px-2 py-0.5 rounded-full uppercase font-bold tracking-tighter">Análisis de Red</span>
</div>
<div class="px-3 py-1 rounded-lg bg-${badgeColor}-50 border border-${badgeColor}-100">
<span class="text-[10px] font-extrabold text-${badgeColor}-700 tracking-tight">${labelText}</span>
</div>
</div>
<div class="space-y-3">
<div>
<div class="text-[10px] text-gray-400 uppercase font-bold mb-1 tracking-widest">Especie y Patología detectada</div>
<div class="text-sm font-semibold text-gray-700 bg-gray-50 p-2.5 rounded-xl border border-gray-100">
${res.prediction}
</div>
</div>
<div>
<div class="flex justify-between text-[10px] mb-1">
<span class="font-bold text-gray-400 uppercase">Nivel de Seguridad</span>
<span class="font-bold text-gray-600">${res.confidence}%</span>
</div>
<div class="w-full bg-gray-100 h-1.5 rounded-full overflow-hidden">
<div class="bg-blue-600 h-full rounded-full transition-all duration-1000 ease-out"
style="width: ${res.confidence}%"></div>
</div>
</div>
</div>
</div>
`;
});
// Re-inicializar iconos de Lucide
lucide.createIcons();
// Scroll suave a resultados
resultsSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
} catch (e) {
alert("Error de conexión con el servidor de IA");
console.error(e);
} finally {
loader.classList.add('hidden');
}
};
</script>
</body>
</html>