s1 / index.html
Diegobrons's picture
Add 2 files
b26e859 verified
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ferramenta de Identificação - ReciclaTech</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tf.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/[email protected]"></script>
<style>
.sidebar {
width: 280px;
transition: all 0.3s;
}
.sidebar-collapsed {
width: 80px;
}
.main-content {
margin-left: 280px;
transition: all 0.3s;
}
.main-content-expanded {
margin-left: 80px;
}
.drop-zone {
border: 2px dashed #ccc;
border-radius: 8px;
padding: 40px;
text-align: center;
cursor: pointer;
transition: all 0.3s;
}
.drop-zone.highlight {
border-color: #3b82f6;
background-color: rgba(59, 130, 246, 0.1);
}
.plastic-badge {
font-size: 12px;
padding: 2px 8px;
border-radius: 10px;
font-weight: bold;
}
.plastic-1 { background-color: #FF5733; color: white; }
.plastic-2 { background-color: #33FF57; color: #111; }
.plastic-3 { background-color: #3357FF; color: white; }
.plastic-4 { background-color: #F3FF33; color: #111; }
.plastic-5 { background-color: #FF33F3; color: white; }
.plastic-6 { background-color: #33FFF3; color: #111; }
.plastic-7 { background-color: #8A33FF; color: white; }
.progress-bar {
height: 8px;
background-color: #e0e0e0;
border-radius: 4px;
overflow: hidden;
}
.progress-bar-fill {
height: 100%;
background-color: #3b82f6;
transition: width 0.3s ease;
}
</style>
</head>
<body class="bg-gray-100 font-sans flex">
<!-- Sidebar -->
<div id="sidebar" class="sidebar bg-gray-800 text-white h-screen fixed">
<div class="p-4 flex items-center justify-between border-b border-gray-700">
<div class="flex items-center space-x-2">
<i class="fas fa-recycle text-2xl text-blue-400"></i>
<span id="logo-text" class="font-bold text-lg">ReciclaTech</span>
</div>
<button id="toggle-sidebar" class="text-gray-400 hover:text-white">
<i class="fas fa-bars"></i>
</button>
</div>
<nav class="p-4">
<div class="mb-8">
<div class="text-gray-400 text-xs uppercase font-bold mb-2" id="nav-section-title">Menu Principal</div>
<ul class="space-y-2">
<li>
<a href="#" class="flex items-center space-x-3 p-2 rounded bg-gray-700 text-white">
<i class="fas fa-home w-6 text-center"></i>
<span id="nav-dashboard" class="font-medium">Dashboard</span>
</a>
</li>
<li>
<a href="#" class="flex items-center space-x-3 p-2 rounded hover:bg-gray-700 text-gray-300 hover:text-white">
<i class="fas fa-tasks w-6 text-center"></i>
<span id="nav-processos" class="font-medium">Processos</span>
</a>
</li>
<li>
<a href="#" class="flex items-center space-x-3 p-2 rounded hover:bg-gray-700 text-gray-300 hover:text-white">
<i class="fas fa-warehouse w-6 text-center"></i>
<span id="nav-estoque" class="font-medium">Estoque</span>
</a>
</li>
<li>
<a href="#" class="flex items-center space-x-3 p-2 rounded hover:bg-gray-700 text-gray-300 hover:text-white">
<i class="fas fa-chart-line w-6 text-center"></i>
<span id="nav-relatorios" class="font-medium">Relatórios</span>
</a>
</li>
</ul>
</div>
<div>
<div class="text-gray-400 text-xs uppercase font-bold mb-2" id="tools-section-title">Ferramentas</div>
<ul class="space-y-2">
<li>
<a href="#" class="flex items-center space-x-3 p-2 rounded bg-blue-900 text-white">
<i class="fas fa-camera w-6 text-center"></i>
<span id="nav-identificador" class="font-medium">Identificador</span>
</a>
</li>
<li>
<a href="#" class="flex items-center space-x-3 p-2 rounded hover:bg-gray-700 text-gray-300 hover:text-white">
<i class="fas fa-barcode w-6 text-center"></i>
<span id="nav-etiquetas" class="font-medium">Gerar Etiquetas</span>
</a>
</li>
<li>
<a href="#" class="flex items-center space-x-3 p-2 rounded hover:bg-gray-700 text-gray-300 hover:text-white">
<i class="fas fa-weight w-6 text-center"></i>
<span id="nav-pesagem" class="font-medium">Registro de Pesagem</span>
</a>
</li>
</ul>
</div>
</nav>
<div class="absolute bottom-0 left-0 right-0 p-4 border-t border-gray-700">
<div class="flex items-center space-x-3 p-2 rounded hover:bg-gray-700 text-gray-300 hover:text-white cursor-pointer">
<i class="fas fa-user-circle w-6 text-center"></i>
<span id="nav-perfil" class="font-medium">Perfil do Usuário</span>
</div>
<div class="flex items-center space-x-3 p-2 rounded hover:bg-gray-700 text-gray-300 hover:text-white cursor-pointer">
<i class="fas fa-sign-out-alt w-6 text-center"></i>
<span id="nav-sair" class="font-medium">Sair do Sistema</span>
</div>
</div>
</div>
<!-- Main Content -->
<div id="main-content" class="main-content flex-1 p-6">
<div class="bg-white rounded-lg shadow-md p-6">
<!-- Header -->
<div class="flex justify-between items-center mb-6">
<div>
<h1 class="text-2xl font-bold text-gray-800">Identificador de Plásticos</h1>
<p class="text-gray-600">Ferramenta de classificação automática para materiais eletrônicos</p>
</div>
<div class="flex space-x-3">
<button class="bg-gray-200 hover:bg-gray-300 text-gray-800 px-4 py-2 rounded-lg font-medium flex items-center">
<i class="fas fa-history mr-2"></i> Histórico
</button>
<button class="bg-blue-50 hover:bg-blue-100 text-blue-700 px-4 py-2 rounded-lg font-medium flex items-center">
<i class="fas fa-question-circle mr-2"></i> Ajuda
</button>
</div>
</div>
<!-- Tool Section -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- Upload Section -->
<div class="lg:col-span-2">
<div class="bg-gray-50 rounded-lg p-6">
<h2 class="text-lg font-semibold mb-4">Enviar imagem para análise</h2>
<div id="dropZone" class="drop-zone mb-6">
<i class="fas fa-cloud-upload-alt text-4xl text-gray-400 mb-3"></i>
<h3 class="text-lg font-medium mb-1">Arraste e solte a imagem aqui</h3>
<p class="text-gray-500 mb-4">ou clique para selecionar um arquivo</p>
<button id="selectFileBtn" class="bg-blue-600 hover:bg-blue-700 text-white px-6 py-2 rounded-lg font-medium transition">
Selecionar arquivo
</button>
<input type="file" id="fileInput" accept="image/*" class="hidden">
</div>
<div id="previewContainer" class="hidden">
<div class="flex justify-between items-center mb-3">
<h3 class="text-lg font-medium">Pré-visualização</h3>
<button id="cancelBtn" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i> Cancelar
</button>
</div>
<div class="border border-gray-200 rounded-lg p-4">
<img id="imagePreview" src="#" alt="Pré-visualização da imagem" class="max-w-full h-auto rounded mx-auto">
</div>
<button id="analyzeBtn" class="mt-4 w-full bg-blue-600 hover:bg-blue-700 text-white py-3 rounded-lg font-semibold transition">
<i class="fas fa-search mr-2"></i> Analisar Material
</button>
</div>
<div id="loadingIndicator" class="hidden text-center py-8">
<div class="inline-block animate-spin rounded-full h-10 w-10 border-t-2 border-b-2 border-blue-500 mb-4"></div>
<p class="text-gray-600">Analisando o material plástico...</p>
<p class="text-sm text-gray-500 mt-2">Isso pode levar alguns segundos</p>
</div>
</div>
</div>
<!-- Results Section -->
<div>
<div class="bg-gray-50 rounded-lg p-6 h-full">
<h2 class="text-lg font-semibold mb-4">Resultados da Análise</h2>
<div id="resultsContainer" class="hidden">
<div id="resultsContent" class="space-y-4">
<!-- Results will be inserted here by JavaScript -->
</div>
</div>
<div id="emptyState" class="text-center py-8">
<i class="fas fa-microscope text-4xl text-gray-300 mb-3"></i>
<h3 class="text-gray-500 font-medium">Nenhuma análise realizada</h3>
<p class="text-sm text-gray-400 mt-1">Envie uma imagem para identificar o tipo de plástico</p>
</div>
</div>
</div>
</div>
<!-- Recent Analyses -->
<div class="mt-8">
<h2 class="text-lg font-semibold mb-4">Análises Recentes</h2>
<div class="bg-gray-50 rounded-lg p-4 overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-100">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Data/Hora</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Tipo de Plástico</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Confiança</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Origem</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Ações</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<tr>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">15/06 14:32</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="plastic-badge plastic-1">ABS</span>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="w-16 mr-2">
<div class="progress-bar">
<div class="progress-bar-fill" style="width: 87%"></div>
</div>
</div>
<span class="text-sm text-gray-500">87%</span>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">Teclado Dell</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<button class="text-blue-600 hover:text-blue-800 mr-3">
<i class="fas fa-eye"></i>
</button>
<button class="text-green-600 hover:text-green-800">
<i class="fas fa-tag"></i>
</button>
</td>
</tr>
<tr>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">15/06 13:15</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="plastic-badge plastic-3">PVC</span>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="w-16 mr-2">
<div class="progress-bar">
<div class="progress-bar-fill" style="width: 92%"></div>
</div>
</div>
<span class="text-sm text-gray-500">92%</span>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">Cabo de rede</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<button class="text-blue-600 hover:text-blue-800 mr-3">
<i class="fas fa-eye"></i>
</button>
<button class="text-green-600 hover:text-green-800">
<i class="fas fa-tag"></i>
</button>
</td>
</tr>
<tr>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">15/06 11:42</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="plastic-badge plastic-7">PC</span>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="w-16 mr-2">
<div class="progress-bar">
<div class="progress-bar-fill" style="width: 78%"></div>
</div>
</div>
<span class="text-sm text-gray-500">78%</span>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">Tela LCD</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<button class="text-blue-600 hover:text-blue-800 mr-3">
<i class="fas fa-eye"></i>
</button>
<button class="text-green-600 hover:text-green-800">
<i class="fas fa-tag"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script>
// Model and variables
let model;
let imageToAnalyze;
// DOM elements
const sidebar = document.getElementById('sidebar');
const mainContent = document.getElementById('main-content');
const toggleSidebarBtn = document.getElementById('toggle-sidebar');
const dropZone = document.getElementById('dropZone');
const fileInput = document.getElementById('fileInput');
const selectFileBtn = document.getElementById('selectFileBtn');
const previewContainer = document.getElementById('previewContainer');
const imagePreview = document.getElementById('imagePreview');
const analyzeBtn = document.getElementById('analyzeBtn');
const cancelBtn = document.getElementById('cancelBtn');
const loadingIndicator = document.getElementById('loadingIndicator');
const resultsContainer = document.getElementById('resultsContainer');
const resultsContent = document.getElementById('resultsContent');
const emptyState = document.getElementById('emptyState');
// Toggle sidebar
toggleSidebarBtn.addEventListener('click', () => {
sidebar.classList.toggle('sidebar-collapsed');
mainContent.classList.toggle('main-content-expanded');
// Toggle text elements in sidebar
document.querySelectorAll('[id$="-text"], [id^="nav-"], [id$="-title"]').forEach(el => {
el.classList.toggle('hidden');
});
});
// File selection events
selectFileBtn.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', handleFileSelect);
analyzeBtn.addEventListener('click', analyzeImage);
cancelBtn.addEventListener('click', resetTool);
// Drag and drop events
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropZone.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
['dragenter', 'dragover'].forEach(eventName => {
dropZone.addEventListener(eventName, highlight, false);
});
['dragleave', 'drop'].forEach(eventName => {
dropZone.addEventListener(eventName, unhighlight, false);
});
function highlight() {
dropZone.classList.add('highlight');
}
function unhighlight() {
dropZone.classList.remove('highlight');
}
dropZone.addEventListener('drop', handleDrop, false);
function handleDrop(e) {
const dt = e.dataTransfer;
const files = dt.files;
if (files.length > 0 && files[0].type.match('image.*')) {
handleFile(files[0]);
}
}
function handleFileSelect(e) {
if (e.target.files.length > 0 && e.target.files[0].type.match('image.*')) {
handleFile(e.target.files[0]);
}
}
function handleFile(file) {
const reader = new FileReader();
reader.onload = function(event) {
imagePreview.src = event.target.result;
imageToAnalyze = imagePreview;
previewContainer.style.display = 'block';
dropZone.style.display = 'none';
emptyState.style.display = 'none';
};
reader.readAsDataURL(file);
}
// Load the model when the page loads
async function loadModel() {
try {
console.log('Loading model...');
model = await mobilenet.load();
console.log('Model loaded successfully');
} catch (error) {
console.error('Error loading model:', error);
alert('Erro ao carregar o modelo de IA. Por favor, recarregue a página.');
}
}
// Analyze the image
async function analyzeImage() {
if (!imageToAnalyze) return;
try {
// Show loading indicator
previewContainer.style.display = 'none';
loadingIndicator.style.display = 'block';
resultsContainer.style.display = 'none';
// Wait a bit to show the loading indicator (simulate processing time)
await new Promise(resolve => setTimeout(resolve, 1500));
// Classify the image
const predictions = await model.classify(imageToAnalyze);
// Process results - in a real app, we would have a custom model trained on plastic types
const plasticType = simulatePlasticTypeDetection(predictions);
// Display results
displayResults(plasticType, predictions);
// Add to recent analyses (simulated)
addToRecentAnalyses(plasticType);
} catch (error) {
console.error('Error analyzing image:', error);
showError('Erro ao analisar a imagem. Por favor, tente novamente.');
resetTool();
}
}
// Simulate plastic type detection based on MobileNet predictions
function simulatePlasticTypeDetection(predictions) {
// In a real application, this would be replaced with a custom model trained on plastic types
// Here we're just simulating based on the MobileNet predictions
// Get current time for the analysis
const now = new Date();
const timeString = `${now.getHours()}:${now.getMinutes().toString().padStart(2, '0')}`;
const dateString = `${now.getDate()}/${now.getMonth()+1}`;
// Check if the predictions contain words related to electronics (higher chance of ABS, PC, etc.)
const hasElectronics = predictions.some(p =>
p.className.toLowerCase().includes('computer') ||
p.className.toLowerCase().includes('keyboard') ||
p.className.toLowerCase().includes('monitor') ||
p.className.toLowerCase().includes('electronic')
);
// Check if the predictions contain words related to packaging (higher chance of PP, HIPS, etc.)
const hasPackaging = predictions.some(p =>
p.className.toLowerCase().includes('bottle') ||
p.className.toLowerCase().includes('container') ||
p.className.toLowerCase().includes('packaging')
);
// Check if the predictions contain words related to cables (higher chance of PVC)
const hasCables = predictions.some(p =>
p.className.toLowerCase().includes('cable') ||
p.className.toLowerCase().includes('wire')
);
// Check if the predictions contain words related to screens (higher chance of PC)
const hasScreens = predictions.some(p =>
p.className.toLowerCase().includes('screen') ||
p.className.toLowerCase().includes('monitor') ||
p.className.toLowerCase().includes('display')
);
// Determine the most likely plastic type based on these checks
if (hasElectronics) {
return {
type: 'ABS',
fullName: 'Acrilonitrila Butadieno Estireno',
code: '7',
description: 'Comum em teclados, carcaças de computadores e eletrodomésticos. Resistente ao impacto e fácil de moldar.',
density: '1.04-1.06 g/cm³',
confidence: Math.random() * 0.15 + 0.85, // Random confidence between 85% and 100%
origin: predictions[0].className,
date: dateString,
time: timeString,
badgeClass: 'plastic-1'
};
} else if (hasPackaging) {
return {
type: 'PP',
fullName: 'Polipropileno',
code: '5',
description: 'Presente em baterias, componentes internos e isolantes. Resistente a produtos químicos.',
density: '0.89-0.91 g/cm³',
confidence: Math.random() * 0.15 + 0.85,
origin: predictions[0].className,
date: dateString,
time: timeString,
badgeClass: 'plastic-4'
};
} else if (hasCables) {
return {
type: 'PVC',
fullName: 'Policloreto de Vinila',
code: '3',
description: 'Usado em fios, cabos e revestimentos. Flexível e resistente à chama.',
density: '1.30-1.45 g/cm³',
confidence: Math.random() * 0.15 + 0.85,
origin: predictions[0].className,
date: dateString,
time: timeString,
badgeClass: 'plastic-3'
};
} else if (hasScreens) {
return {
type: 'PC',
fullName: 'Policarbonato',
code: '7',
description: 'Encontrado em CDs, DVDs, lentes e componentes ópticos. Transparente e altamente resistente.',
density: '1.20-1.22 g/cm³',
confidence: Math.random() * 0.15 + 0.85,
origin: predictions[0].className,
date: dateString,
time: timeString,
badgeClass: 'plastic-7'
};
} else {
// Default to HIPS if no specific matches
return {
type: 'HIPS',
fullName: 'Poliestireno de Alto Impacto',
code: '6',
description: 'Usado em monitores, TVs e embalagens. Reconhecível pelo som metálico quando batido.',
density: '1.03-1.06 g/cm³',
confidence: Math.random() * 0.15 + 0.85,
origin: predictions[0].className,
date: dateString,
time: timeString,
badgeClass: 'plastic-2'
};
}
}
// Display the analysis results
function displayResults(plasticType, predictions) {
loadingIndicator.style.display = 'none';
emptyState.style.display = 'none';
// Create results HTML
let html = `
<div class="bg-white border border-gray-200 rounded-lg p-4 mb-4">
<div class="flex justify-between items-start mb-3">
<div>
<span class="${plasticType.badgeClass} plastic-badge">${plasticType.type}</span>
<span class="ml-2 text-sm text-gray-500">Código ${plasticType.code}</span>
</div>
<div class="text-sm text-gray-500">${plasticType.date} ${plasticType.time}</div>
</div>
<h3 class="font-bold text-lg mb-1">${plasticType.fullName}</h3>
<p class="text-sm text-gray-600 mb-3">${plasticType.description}</p>
<div class="flex items-center mb-2">
<div class="w-full mr-2">
<div class="progress-bar">
<div class="progress-bar-fill" style="width: ${Math.round(plasticType.confidence * 100)}%"></div>
</div>
</div>
<span class="text-sm font-medium">${Math.round(plasticType.confidence * 100)}%</span>
</div>
<div class="text-xs text-gray-500 mb-3">Origem identificada: ${plasticType.origin}</div>
<div class="grid grid-cols-2 gap-2">
<button class="bg-blue-50 hover:bg-blue-100 text-blue-700 px-3 py-2 rounded text-sm font-medium">
<i class="fas fa-tag mr-1"></i> Etiquetar
</button>
<button class="bg-gray-50 hover:bg-gray-100 text-gray-700 px-3 py-2 rounded text-sm font-medium">
<i class="fas fa-box mr-1"></i> Armazenar
</button>
</div>
</div>
<div class="bg-white border border-gray-200 rounded-lg p-4">
<h4 class="font-semibold mb-2">Próximos passos recomendados</h4>
<ul class="space-y-2 text-sm">
<li class="flex items-start">
<i class="fas fa-check-circle text-green-500 mt-1 mr-2"></i>
<span>Separar na área de plásticos tipo ${plasticType.code}</span>
</li>
<li class="flex items-start">
<i class="fas fa-check-circle text-green-500 mt-1 mr-2"></i>
<span>Registrar no sistema como ${plasticType.type}</span>
</li>
<li class="flex items-start">
<i class="fas fa-check-circle text-green-500 mt-1 mr-2"></i>
<span>Encaminhar para processo de trituração</span>
</li>
</ul>
</div>
`;
resultsContent.innerHTML = html;
resultsContainer.style.display = 'block';
}
// Simulate adding to recent analyses
function addToRecentAnalyses(plasticType) {
// In a real app, this would be saved to a database
console.log('Analysis saved:', plasticType);
}
// Show error message
function showError(message) {
const html = `
<div class="bg-red-50 border border-red-200 rounded-lg p-4 text-red-700">
<div class="flex items-center">
<i class="fas fa-exclamation-circle mr-2"></i>
<span>${message}</span>
</div>
</div>
`;
resultsContent.innerHTML = html;
resultsContainer.style.display = 'block';
}
// Reset the tool to its initial state
function resetTool() {
fileInput.value = '';
previewContainer.style.display = 'none';
loadingIndicator.style.display = 'none';
resultsContainer.style.display = 'none';
dropZone.style.display = 'block';
emptyState.style.display = 'block';
imageToAnalyze = null;
}
// Initialize the page
document.addEventListener('DOMContentLoaded', () => {
loadModel();
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Diegobrons/s1" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>