| <!DOCTYPE html> |
| <html lang="fr"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Labélisation d'Images avec SAM</title> |
| <link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}"> |
| <style> |
| body { |
| font-family: Arial, sans-serif; |
| margin: 20px; |
| background-color: #f9f9f9; |
| } |
| |
| h1 { |
| text-align: center; |
| color: #333; |
| } |
| |
| section { |
| margin: 20px 0; |
| padding: 20px; |
| background: #fff; |
| box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1); |
| border-radius: 8px; |
| } |
| |
| canvas { |
| border: 2px solid #ddd; |
| border-radius: 8px; |
| display: block; |
| margin: 20px auto; |
| } |
| |
| button { |
| background-color: #4CAF50; |
| color: white; |
| border: none; |
| padding: 10px 20px; |
| font-size: 14px; |
| cursor: pointer; |
| border-radius: 5px; |
| transition: background-color 0.3s ease; |
| } |
| |
| button:hover { |
| background-color: #45a049; |
| } |
| |
| button:disabled { |
| background-color: #ccc; |
| cursor: not-allowed; |
| } |
| |
| .upload-section { |
| text-align: center; |
| } |
| |
| .class-management { |
| text-align: center; |
| } |
| |
| .class-list { |
| display: flex; |
| flex-wrap: wrap; |
| gap: 10px; |
| justify-content: center; |
| list-style: none; |
| padding: 0; |
| } |
| |
| .class-item { |
| padding: 5px 10px; |
| border-radius: 5px; |
| background-color: #f4f4f4; |
| border: 1px solid #ccc; |
| cursor: pointer; |
| transition: all 0.3s ease; |
| } |
| |
| .class-item:hover { |
| background-color: #ddd; |
| } |
| |
| .class-item.active { |
| background-color: #4CAF50; |
| color: white; |
| border-color: #45a049; |
| } |
| |
| #annotated-image { |
| display: block; |
| max-width: 100%; |
| margin: 20px auto; |
| border: 2px solid #4CAF50; |
| border-radius: 8px; |
| } |
| |
| .status { |
| text-align: center; |
| margin-top: 10px; |
| font-weight: bold; |
| } |
| |
| .status.success { |
| color: #4CAF50; |
| } |
| |
| .status.error { |
| color: #f44336; |
| } |
| </style> |
| </head> |
| <body> |
| <h1>Labélisation d'Images avec SAM</h1> |
|
|
| |
| <section class="upload-section"> |
| <form method="post" enctype="multipart/form-data"> |
| <label for="image">Télécharger une image :</label><br> |
| <input type="file" id="image" name="image" accept="image/*" required> |
| <br> |
| <button type="submit">Télécharger</button> |
| </form> |
| </section> |
|
|
| {% if uploaded_image %} |
| |
| <section> |
| <canvas id="image-canvas"></canvas> |
| </section> |
|
|
| |
| <section> |
| <h2>Image Annotée</h2> |
| <img id="annotated-image" style="display: none;" alt="Image Annotée"> |
| </section> |
|
|
| |
| <section class="class-management"> |
| <h3>Ajouter une classe :</h3> |
| <input type="text" id="class-name" placeholder="Entrez une classe"> |
| <button id="add-class">Ajouter</button> |
| <h4>Classes disponibles :</h4> |
| <ul id="class-list" class="class-list"></ul> |
| </section> |
|
|
| |
| <section> |
| <div class="controls"> |
| <button id="segment-button" disabled>Lancer la Segmentation</button> |
| </div> |
| </section> |
| {% endif %} |
|
|
| <script> |
| let canvas = document.getElementById('image-canvas'); |
| let ctx = canvas ? canvas.getContext('2d') : null; |
| let points = []; |
| let currentClass = null; |
| |
| {% if uploaded_image %} |
| |
| const img = new Image(); |
| img.src = "{{ url_for('static', filename='uploads/' + uploaded_image) }}"; |
| img.onload = () => { |
| canvas.width = img.width; |
| canvas.height = img.height; |
| ctx.drawImage(img, 0, 0); |
| }; |
| |
| |
| document.getElementById('add-class').addEventListener('click', () => { |
| const className = document.getElementById('class-name').value.trim(); |
| if (!className) return; |
| |
| const li = document.createElement('li'); |
| li.textContent = className; |
| li.classList.add('class-item'); |
| li.onclick = () => { |
| |
| document.querySelectorAll('.class-item').forEach(item => item.classList.remove('active')); |
| li.classList.add('active'); |
| currentClass = className; |
| }; |
| |
| document.getElementById('class-list').appendChild(li); |
| document.getElementById('class-name').value = ''; |
| }); |
| |
| |
| canvas.addEventListener('click', event => { |
| if (!currentClass) { |
| alert('Veuillez sélectionner une classe.'); |
| return; |
| } |
| |
| const rect = canvas.getBoundingClientRect(); |
| const x = event.clientX - rect.left; |
| const y = event.clientY - rect.top; |
| points.push({ x, y, class: currentClass }); |
| |
| |
| ctx.fillStyle = 'red'; |
| ctx.beginPath(); |
| ctx.arc(x, y, 5, 0, 2 * Math.PI); |
| ctx.fill(); |
| |
| |
| document.getElementById('segment-button').disabled = points.length === 0; |
| }); |
| |
| |
| document.getElementById('segment-button').addEventListener('click', () => { |
| const status = document.createElement('div'); |
| status.className = 'status'; |
| document.body.appendChild(status); |
| |
| fetch('/segment', { |
| method: 'POST', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify({ |
| image_name: "{{ uploaded_image }}", |
| points: points |
| }) |
| }) |
| .then(response => response.json()) |
| .then(data => { |
| if (data.success) { |
| status.textContent = 'Segmentation terminée !'; |
| status.classList.add('success'); |
| const annotatedImg = document.getElementById('annotated-image'); |
| annotatedImg.src = "{{ url_for('static', filename='') }}" + data.annotated_image; |
| annotatedImg.style.display = 'block'; |
| } else { |
| status.textContent = 'Erreur : ' + data.error; |
| status.classList.add('error'); |
| } |
| }) |
| .catch(err => { |
| status.textContent = 'Erreur de réseau.'; |
| status.classList.add('error'); |
| console.error('Erreur:', err); |
| }); |
| }); |
| {% endif %} |
| </script> |
| </body> |
| </html> |
|
|