--- a +++ b/templates/index.html @@ -0,0 +1,333 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Medical X-Ray Classifier</title> + <style> + /* General Styles */ + body { + font-family: 'Arial', sans-serif; + background: linear-gradient(to right, #e3f2fd, #ffffff); + margin: 0; + padding: 0; + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; + } + + .container { + width: 90%; + max-width: 1200px; + background: #fff; + border-radius: 12px; + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15); + display: flex; + overflow: hidden; + animation: fadeIn 1s ease-in-out; + } + + @keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } + } + + .left-column { + width: 35%; + background: #f8f9fa; + padding: 20px; + border-right: 1px solid #ddd; + } + + .right-column { + width: 65%; + padding: 20px; + display: flex; + flex-direction: column; + align-items: center; + } + + h1 { + text-align: center; + font-size: 1.8rem; + margin-bottom: 20px; + color: #333; + } + + input[type="file"] { + margin: 15px 0; + padding: 10px; + border: 1px solid #ddd; + border-radius: 6px; + cursor: pointer; + width: 100%; + } + + button { + padding: 12px 30px; + background: #007bff; + color: #fff; + border: none; + border-radius: 6px; + font-size: 14px; + cursor: pointer; + transition: background 0.3s ease; + margin: 10px 0; + } + + button:hover { + background: #0056b3; + } + + .progress-bar { + width: 100%; + height: 10px; + background: #e9ecef; + border-radius: 5px; + margin: 15px 0; + overflow: hidden; + position: relative; + } + + .progress-bar .progress { + height: 100%; + background: #28a745; + width: 0; + transition: width 0.5s; + } + + .fixed-box { + margin-top: 20px; + text-align: center; + border: 1px solid #ddd; + border-radius: 10px; + padding: 10px; + background: #fff; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + } + + .fixed-box img { + max-width: 100%; + border-radius: 8px; + } + + .results { + font-size: 1rem; + margin-bottom: 20px; + text-align: center; + display: none; + } + + .results.visible { + display: block; + } + + .note { + font-size: 1rem; + color: #d9534f; + text-align: center; + margin-top: 20px; + } + + .visualization-group { + margin-top: 20px; + width: 100%; + display: none; + } + + .visualization-group.visible { + display: block; + } + + .visualization-group h3 { + font-size: 1.2rem; + margin-bottom: 10px; + text-align: center; + } + + .visualization { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 15px; + justify-items: center; + } + + .visualization img { + max-width: 100%; + border-radius: 8px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + transition: transform 0.2s ease; + } + + .visualization img:hover { + transform: scale(1.05); + } + + .image-name { + text-align: center; + font-size: 0.9rem; + margin-top: 5px; + color: #555; + } + + /* Prediction Result Box */ + .prediction-box { + padding: 20px; + background-color: #f8f9fa; + border-radius: 8px; + border: 1px solid #ddd; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + margin-top: 20px; + text-align: center; + } + + .prediction-box p { + font-size: 1.2rem; + margin: 5px 0; + } + + .prediction-box .class { + font-weight: bold; + font-size: 1.5rem; + color: #007bff; + } + + .prediction-box .confidence { + font-size: 1.1rem; + color: #28a745; + } + </style> +</head> +<body> + <div class="container"> + <!-- Left Column --> + <div class="left-column"> + <h1>Upload X-Ray</h1> + <form id="upload-form"> + <input type="file" id="file-input" name="file" accept="image/*" required> + <button type="submit">Predict</button> + <button id="refresh-button">Refresh</button> + <div class="progress-bar"> + <div class="progress" id="progress-bar"></div> + </div> + </form> + <div class="fixed-box"> + <h3>Uploaded Image</h3> + <img id="original" src="https://via.placeholder.com/150?text=Upload+Image" alt="Uploaded Image"> + <div class="image-name" id="image-name">Image Name</div> + </div> + </div> + + <!-- Right Column --> + <div class="right-column"> + <div class="prediction-box" id="result-box"> + <p><strong>Predicted Class:</strong> <span id="predicted-class">N/A</span></p> + <p><strong>Confidence Score:</strong> <span id="confidence-score">N/A</span></p> + </div> + <div id="note" class="note" style="display: none;"> + Sorry, you uploaded a non chest X-ray image. Please upload a chest X-ray image. Thank you! + </div> + <div class="visualization-group" id="visualization-group"> + <h3>Image Visualizations</h3> + <div class="visualization"> + <div> + <img id="grayscale" src="https://via.placeholder.com/150?text=Grayscale" alt="Grayscale Image"> + <div class="image-name">Grayscale</div> + </div> + <div> + <img id="equalized" src="https://via.placeholder.com/150?text=Equalized" alt="Equalized Image"> + <div class="image-name">Equalized</div> + </div> + <div> + <img id="edges" src="https://via.placeholder.com/150?text=Edges" alt="Edge Detection"> + <div class="image-name">Edges</div> + </div> + <div> + <img id="segmented" src="https://via.placeholder.com/150?text=Segmented" alt="Segmented Image"> + <div class="image-name">Segmented</div> + </div> + </div> + <h3>Advanced Visualizations</h3> + <div class="visualization"> + <div> + <img id="grad_cam" src="https://via.placeholder.com/150?text=Grad-CAM" alt="Grad-CAM Visualization"> + <div class="image-name">Grad-CAM</div> + </div> + <div> + <img id="roi" src="https://via.placeholder.com/150?text=ROI" alt="Region of Interest"> + <div class="image-name">ROI</div> + </div> + </div> + </div> + </div> + </div> + + <script> + const form = document.getElementById('upload-form'); + const progressBar = document.getElementById('progress-bar'); + const resultBox = document.getElementById('result-box'); + const refreshButton = document.getElementById('refresh-button'); + const note = document.getElementById('note'); + const visualizationGroup = document.getElementById('visualization-group'); + const imageName = document.getElementById('image-name'); + + form.addEventListener('submit', async (event) => { + event.preventDefault(); + + progressBar.style.width = '0'; + resultBox.style.display = 'none'; + note.style.display = 'none'; + visualizationGroup.style.display = 'none'; + const formData = new FormData(form); + + // Simulate progress + let progress = 0; + const interval = setInterval(() => { + if (progress < 100) { + progress += 10; + progressBar.style.width = `${progress}%`; + } else { + clearInterval(interval); + } + }, 100); + + const response = await fetch('/predict', { method: 'POST', body: formData }); + const data = await response.json(); + + document.getElementById('original').src = URL.createObjectURL(formData.get('file')); + imageName.textContent = formData.get('file').name; + + if (data.error) { + resultBox.style.display = 'block'; + document.getElementById('predicted-class').textContent = 'N/A'; + document.getElementById('confidence-score').textContent = 'N/A'; + note.style.display = 'block'; + return; + } + + resultBox.style.display = 'block'; + document.getElementById('predicted-class').textContent = data.predicted_class; + document.getElementById('confidence-score').textContent = `${data.confidence_score}%`; + visualizationGroup.style.display = 'block'; + + document.getElementById('grayscale').src = data.visualizations.grayscale; + document.getElementById('equalized').src = data.visualizations.equalized; + document.getElementById('edges').src = data.visualizations.edges; + document.getElementById('segmented').src = data.visualizations.segmented; + document.getElementById('grad_cam').src = data.visualizations.grad_cam; + document.getElementById('roi').src = data.visualizations.roi; + }); + + refreshButton.addEventListener('click', () => { + window.location.reload(); + }); + </script> +</body> +</html>