juancmamacias/yolo-multi-class-annotator
0
1// JavaScript específico para el visualizador de datasets2 3let currentSession = "";4 5function loadSession() {6 const select = document.getElementById('sessionSelect');7 const selectedSession = select.value;8 9 if (selectedSession) {10 window.location.href = '/visualizer?session=' + selectedSession;11 } else {12 window.location.href = '/visualizer';13 }14}15 16function refreshData() {17 if (currentSession) {18 loadSession();19 }20}21 22// Función para inicializar el visualizador23function initializeVisualizer(session) {24 currentSession = session || '';25 26 // Cargar datos si hay sesión seleccionada27 if (currentSession) {28 loadSessionData(currentSession);29 }30}31 32async function loadSessionData(sessionName) {33 try {34 const response = await fetch('/api/session/' + sessionName + '/visualize');35 const data = await response.json();36 37 if (data.success) {38 displaySessionData(data);39 } else {40 showError('Error cargando sesión: ' + data.message);41 }42 } catch (error) {43 showError('Error de conexión: ' + error.message);44 }45}46 47function displaySessionData(data) {48 // Mostrar estadísticas49 document.getElementById('totalImages').textContent = data.total_images;50 document.getElementById('totalLabels').textContent = data.total_labels;51 const avgLabels = data.total_images > 0 ? (data.total_labels / data.total_images).toFixed(1) : '0.0';52 document.getElementById('avgLabels').textContent = avgLabels;53 document.getElementById('statsContainer').style.display = 'block';54 55 // Mostrar galería de imágenes56 let galleryHTML = '<div class="gallery">';57 58 if (data.images && data.images.length > 0) {59 data.images.forEach((image, index) => {60 galleryHTML += `61 <div class="image-card">62 <div class="image-container">63 <canvas id="canvas_${index}" width="${image.width}" height="${image.height}" 64 style="max-width: 100%; height: 250px; object-fit: contain; border: 1px solid #ddd;">65 </canvas>66 </div>67 <div class="image-info">68 <h4>📄 ${image.name}</h4>69 <p>🏷️ Labels: ${image.labels || 0}</p>70 <p>📏 Resolución: ${image.width}x${image.height}</p>71 </div>72 </div>73 `;74 });75 } else {76 galleryHTML += '<div style="grid-column: 1 / -1; text-align: center; padding: 40px;"><h3>📷 No hay imágenes en esta sesión</h3></div>';77 }78 79 galleryHTML += '</div>';80 document.getElementById('contentContainer').innerHTML = galleryHTML;81 82 // Dibujar las imágenes y las anotaciones en los canvas83 if (data.images && data.images.length > 0) {84 data.images.forEach((image, index) => {85 drawImageWithAnnotations(image, index);86 });87 }88}89 90function drawImageWithAnnotations(imageData, index) {91 const canvas = document.getElementById(`canvas_${index}`);92 if (!canvas) return;93 94 const ctx = canvas.getContext('2d');95 const img = new Image();96 97 img.onload = function() {98 // Dibujar la imagen99 ctx.drawImage(img, 0, 0, canvas.width, canvas.height);100 101 // Dibujar las anotaciones102 if (imageData.annotations && imageData.annotations.length > 0) {103 imageData.annotations.forEach(annotation => {104 drawBoundingBox(ctx, annotation, canvas.width, canvas.height, imageData.width, imageData.height);105 });106 }107 };108 109 img.onerror = function() {110 // Si la imagen no se puede cargar, mostrar placeholder111 ctx.fillStyle = '#f8f9fa';112 ctx.fillRect(0, 0, canvas.width, canvas.height);113 ctx.fillStyle = '#6c757d';114 ctx.font = '16px Arial';115 ctx.textAlign = 'center';116 ctx.fillText('Imagen no encontrada', canvas.width/2, canvas.height/2);117 };118 119 img.src = `/image/${currentSession}/${imageData.name}`;120}121 122function drawBoundingBox(ctx, annotation, canvasWidth, canvasHeight, imageWidth, imageHeight) {123 // Escalar las coordenadas al tamaño del canvas124 const scaleX = canvasWidth / imageWidth;125 const scaleY = canvasHeight / imageHeight;126 127 const x1 = annotation.x1 * scaleX;128 const y1 = annotation.y1 * scaleY;129 const x2 = annotation.x2 * scaleX;130 const y2 = annotation.y2 * scaleY;131 132 // Colores por clase133 const colors = ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff', '#00ffff'];134 const color = colors[annotation.class_id % colors.length] || '#ff0000';135 136 // Dibujar el rectángulo137 ctx.strokeStyle = color;138 ctx.lineWidth = 2;139 ctx.strokeRect(x1, y1, x2 - x1, y2 - y1);140 141 // Dibujar la etiqueta de clase142 ctx.fillStyle = color;143 ctx.font = '12px Arial';144 ctx.fillText(`Clase ${annotation.class_id}`, x1, y1 - 5);145 146 // Fondo semi-transparente para el texto147 ctx.globalAlpha = 0.7;148 ctx.fillRect(x1, y1 - 20, 60, 15);149 ctx.globalAlpha = 1.0;150 ctx.fillStyle = 'white';151 ctx.fillText(`Clase ${annotation.class_id}`, x1 + 2, y1 - 8);152}153 154function showError(message) {155 document.getElementById('contentContainer').innerHTML = `156 <div class="no-session">157 <h3>❌ Error</h3>158 <p>${message}</p>159 <button onclick="refreshData()" class="controls button">🔄 Intentar de nuevo</button>160 </div>161 `;162}163 