| <!DOCTYPE html>
|
| <html lang="en">
|
| <head>
|
| <meta charset="UTF-8">
|
| <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| <title>SkyGuard | Bird vs Drone Classifier</title>
|
| <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
| <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600&display=swap" rel="stylesheet">
|
| <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/js/all.min.js"></script>
|
| </head>
|
| <body>
|
| <div class="container">
|
| <header>
|
| <div class="logo">
|
| <i class="fas fa-shield-alt"></i>
|
| <h1>SkyGuard AI</h1>
|
| </div>
|
| <p>Advanced Aerial Identification System</p>
|
| </header>
|
|
|
| <main>
|
| <div class="glass-card upload-section">
|
| <div class="drop-zone" id="drop-zone">
|
| <i class="fas fa-cloud-upload-alt"></i>
|
| <p>Drag & drop or Click to Upload Image</p>
|
| <input type="file" id="file-input" hidden accept="image/*">
|
| </div>
|
| <button id="predict-btn" class="btn-primary" disabled>Analyze Target</button>
|
| </div>
|
|
|
| <div class="result-section" id="result-section" style="display: none;">
|
| <div class="glass-card result-card">
|
| <div class="image-preview">
|
| <img id="preview-img" src="" alt="Target Analysis">
|
| <div class="scan-line"></div>
|
| </div>
|
| <div class="analysis-info">
|
| <h2>Analysis Results</h2>
|
| <div class="result-item">
|
| <span class="label">Classification:</span>
|
| <span id="res-label" class="value badge">---</span>
|
| </div>
|
| <div class="result-item">
|
| <span class="label">Confidence:</span>
|
| <div class="progress-bar">
|
| <div id="res-conf-bar" class="progress-fill" style="width: 0%"></div>
|
| </div>
|
| <span id="res-conf-text" class="value">0%</span>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
| </main>
|
|
|
| <footer>
|
| <p>© 2026 Deep Learning Aerial Surveillance Project</p>
|
| </footer>
|
| </div>
|
|
|
| <script>
|
| const dropZone = document.getElementById('drop-zone');
|
| const fileInput = document.getElementById('file-input');
|
| const predictBtn = document.getElementById('predict-btn');
|
| const resultSection = document.getElementById('result-section');
|
| const previewImg = document.getElementById('preview-img');
|
| const resLabel = document.getElementById('res-label');
|
| const resConfText = document.getElementById('res-conf-text');
|
| const resConfBar = document.getElementById('res-conf-bar');
|
|
|
| let selectedFile = null;
|
|
|
| dropZone.onclick = () => fileInput.click();
|
|
|
| fileInput.onchange = (e) => {
|
| selectedFile = e.target.files[0];
|
| if (selectedFile) {
|
| const reader = new FileReader();
|
| reader.onload = (e) => {
|
| previewImg.src = e.target.result;
|
| resultSection.style.display = 'block';
|
| predictBtn.disabled = false;
|
|
|
| resLabel.textContent = '---';
|
| resLabel.className = 'value badge';
|
| resConfText.textContent = '0%';
|
| resConfBar.style.width = '0%';
|
| };
|
| reader.readAsDataURL(selectedFile);
|
| }
|
| };
|
|
|
| predictBtn.onclick = async () => {
|
| if (!selectedFile) return;
|
|
|
| predictBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Analyzing...';
|
| predictBtn.disabled = true;
|
|
|
| const formData = new FormData();
|
| formData.append('file', selectedFile);
|
|
|
| try {
|
| const response = await fetch('/predict', {
|
| method: 'POST',
|
| body: formData
|
| });
|
| const data = await response.json();
|
|
|
| if (data.error) {
|
| alert(data.error);
|
| } else {
|
| resLabel.textContent = data.label;
|
| resLabel.classList.add(data.label.toLowerCase());
|
| resConfText.textContent = data.confidence;
|
| resConfBar.style.width = data.confidence;
|
|
|
|
|
| resultSection.scrollIntoView({ behavior: 'smooth' });
|
| }
|
| } catch (error) {
|
| console.error('Error:', error);
|
| alert('Analysis failed. Check console for details.');
|
| } finally {
|
| predictBtn.innerHTML = 'Analyze Target';
|
| predictBtn.disabled = false;
|
| }
|
| };
|
|
|
|
|
| dropZone.ondragover = (e) => {
|
| e.preventDefault();
|
| dropZone.classList.add('active');
|
| };
|
| dropZone.ondragleave = () => dropZone.classList.remove('active');
|
| dropZone.ondrop = (e) => {
|
| e.preventDefault();
|
| dropZone.classList.remove('active');
|
| fileInput.files = e.dataTransfer.files;
|
| fileInput.onchange({ target: fileInput });
|
| };
|
| </script>
|
| </body>
|
| </html>
|
|
|