Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>VisionAI | Object Detection Platform</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"> | |
| <style> | |
| /* CSS Variables for Easy Theming */ | |
| :root { | |
| --background-color: #121212; | |
| --surface-color: #1E1E1E; | |
| --primary-text-color: #E0E0E0; | |
| --secondary-text-color: #A0A0A0; | |
| --accent-color: #007BFF; | |
| --accent-hover-color: #0056b3; | |
| --border-color: #333333; | |
| --error-color: #CF6679; | |
| --success-color: #4CAF50; | |
| --shadow: 0 8px 24px rgba(0, 0, 0, 0.2); | |
| --border-radius: 12px; | |
| } | |
| /* Base & Body Styles */ | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| body { | |
| font-family: 'Inter', sans-serif; | |
| background-color: var(--background-color); | |
| color: var(--primary-text-color); | |
| display: flex; | |
| flex-direction: column; | |
| min-height: 100vh; | |
| align-items: center; | |
| padding: 20px; | |
| } | |
| /* Header */ | |
| header { | |
| width: 100%; | |
| max-width: 900px; | |
| padding: 20px 0; | |
| margin-bottom: 2rem; | |
| border-bottom: 1px solid var(--border-color); | |
| text-align: left; | |
| } | |
| header h1 { | |
| font-size: 1.8rem; | |
| font-weight: 600; | |
| letter-spacing: -0.5px; | |
| } | |
| header span { | |
| color: var(--accent-color); | |
| } | |
| /* Main Container */ | |
| .container { | |
| width: 100%; | |
| max-width: 900px; | |
| flex-grow: 1; | |
| } | |
| /* Card Style for content blocks */ | |
| .card { | |
| background-color: var(--surface-color); | |
| padding: 40px; | |
| border-radius: var(--border-radius); | |
| box-shadow: var(--shadow); | |
| border: 1px solid var(--border-color); | |
| margin-bottom: 30px; | |
| transition: all 0.3s ease; | |
| } | |
| .card h2 { | |
| font-size: 1.5rem; | |
| font-weight: 600; | |
| margin-bottom: 10px; | |
| } | |
| .card p { | |
| color: var(--secondary-text-color); | |
| margin-bottom: 25px; | |
| line-height: 1.6; | |
| } | |
| /* Upload Form & Area */ | |
| .upload-area { | |
| border: 2px dashed var(--border-color); | |
| border-radius: var(--border-radius); | |
| padding: 40px; | |
| text-align: center; | |
| cursor: pointer; | |
| transition: border-color 0.3s ease, background-color 0.3s ease; | |
| position: relative; | |
| } | |
| .upload-area:hover { | |
| border-color: var(--accent-color); | |
| background-color: rgba(0, 123, 255, 0.05); | |
| } | |
| .upload-area input[type="file"] { | |
| position: absolute; | |
| width: 100%; | |
| height: 100%; | |
| top: 0; | |
| left: 0; | |
| opacity: 0; | |
| cursor: pointer; | |
| } | |
| .upload-icon svg { | |
| width: 50px; | |
| height: 50px; | |
| stroke: var(--secondary-text-color); | |
| margin-bottom: 15px; | |
| transition: stroke 0.3s ease; | |
| } | |
| .upload-area:hover .upload-icon svg { | |
| stroke: var(--accent-color); | |
| } | |
| .upload-text { | |
| font-weight: 500; | |
| } | |
| .upload-text span { | |
| color: var(--accent-color); | |
| font-weight: 600; | |
| } | |
| #file-name { | |
| margin-top: 15px; | |
| color: var(--success-color); | |
| font-weight: 500; | |
| font-style: italic; | |
| } | |
| /* Submit Button */ | |
| .btn { | |
| background-color: var(--accent-color); | |
| color: white; | |
| border: none; | |
| padding: 12px 30px; | |
| font-size: 1rem; | |
| font-weight: 600; | |
| border-radius: 8px; | |
| cursor: pointer; | |
| transition: background-color 0.3s ease, transform 0.2s ease; | |
| display: inline-block; | |
| margin-top: 25px; | |
| width: 100%; | |
| max-width: 300px; | |
| } | |
| .btn:hover { | |
| background-color: var(--accent-hover-color); | |
| transform: translateY(-2px); | |
| } | |
| /* Loader */ | |
| .loader-container { | |
| display: none; /* Hidden by default */ | |
| text-align: center; | |
| } | |
| .loader { | |
| border: 4px solid var(--border-color); | |
| border-top: 4px solid var(--accent-color); | |
| border-radius: 50%; | |
| width: 50px; | |
| height: 50px; | |
| animation: spin 1s linear infinite; | |
| margin: 20px auto; | |
| } | |
| @keyframes spin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| /* Result & Error Display */ | |
| .result-display h2 { | |
| text-align: center; | |
| } | |
| .result-display img { | |
| max-width: 100%; | |
| border-radius: var(--border-radius); | |
| margin-top: 20px; | |
| border: 1px solid var(--border-color); | |
| } | |
| .error-message { | |
| background-color: rgba(207, 102, 121, 0.1); | |
| border: 1px solid var(--error-color); | |
| color: var(--error-color); | |
| padding: 20px; | |
| border-radius: var(--border-radius); | |
| text-align: center; | |
| font-weight: 600; | |
| } | |
| /* Footer */ | |
| footer { | |
| width: 100%; | |
| max-width: 900px; | |
| text-align: center; | |
| padding: 20px 0; | |
| margin-top: auto; | |
| color: var(--secondary-text-color); | |
| font-size: 0.9rem; | |
| border-top: 1px solid var(--border-color); | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <h1>VisionAI <span>/</span> Object Detection</h1> | |
| </header> | |
| <main class="container"> | |
| <section class="card" id="uploader-card"> | |
| <h2>Upload Image</h2> | |
| <p>Select or drag and drop an image file. The model will detect and highlight objects within it.</p> | |
| <form id="upload-form" action="/predict_web" method="post" enctype="multipart/form-data"> | |
| <div class="upload-area"> | |
| <input type="file" name="file" id="file-input" accept="image/*" required> | |
| <div class="upload-icon"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="17 8 12 3 7 8"></polyline><line x1="12" y1="3" x2="12" y2="15"></line></svg> | |
| </div> | |
| <p class="upload-text">Drag & drop your image here, or <span>browse files</span>.</p> | |
| <div id="file-name"></div> | |
| </div> | |
| <div style="text-align: center;"> | |
| <button type="submit" class="btn">Detect Objects</button> | |
| </div> | |
| </form> | |
| </section> | |
| <section class="card loader-container" id="loader-card"> | |
| <h2>Processing Image...</h2> | |
| <p>Our AI is analyzing your image. Please wait a moment.</p> | |
| <div class="loader"></div> | |
| </section> | |
| {% if image_url %} | |
| <section class="card result-display"> | |
| <h2>Detection Result</h2> | |
| <img src="{{ image_url }}" alt="Detected Objects"> | |
| </section> | |
| {% endif %} | |
| {% if error_message %} | |
| <div class="error-message"> | |
| <p>{{ error_message }}</p> | |
| </div> | |
| {% endif %} | |
| </main> | |
| <footer> | |
| <p>© 2025 VisionAI Platform. All rights reserved.</p> | |
| </footer> | |
| <script> | |
| const uploadForm = document.getElementById('upload-form'); | |
| const fileInput = document.getElementById('file-input'); | |
| const fileNameDisplay = document.getElementById('file-name'); | |
| const uploaderCard = document.getElementById('uploader-card'); | |
| const loaderCard = document.getElementById('loader-card'); | |
| // Show selected file name | |
| fileInput.addEventListener('change', () => { | |
| if (fileInput.files.length > 0) { | |
| fileNameDisplay.textContent = `Selected: ${fileInput.files[0].name}`; | |
| } else { | |
| fileNameDisplay.textContent = ''; | |
| } | |
| }); | |
| // Show loader on form submission | |
| uploadForm.addEventListener('submit', () => { | |
| // Check if a file is selected | |
| if (fileInput.files.length > 0) { | |
| uploaderCard.style.display = 'none'; | |
| loaderCard.style.display = 'block'; | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> |