Vision-Guard / static /js /upload.js
yakub-md's picture
Upload 3 files
bd18c39 verified
Raw
History Blame Contribute Delete
9.3 kB
// Upload and Prediction JavaScript
// Image preview functionality
function setupImagePreview(inputId, previewId, placeholderId) {
const input = document.getElementById(inputId);
const preview = document.getElementById(previewId);
const placeholder = input.parentElement.querySelector('.upload-placeholder');
if (input) {
input.addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
preview.src = e.target.result;
preview.style.display = 'block';
if (placeholder) placeholder.style.display = 'none';
};
reader.readAsDataURL(file);
}
});
}
}
// Setup previews based on mode
if (mode === 'multimodal') {
setupImagePreview('fundusImage', 'fundusPreview');
setupImagePreview('octImage', 'octPreview');
} else if (mode === 'fundus') {
setupImagePreview('fundusImage', 'fundusPreview');
} else if (mode === 'oct') {
setupImagePreview('octImage', 'octPreview');
}
// Form submission
const form = document.getElementById('uploadForm');
const analyzeBtn = document.getElementById('analyzeBtn');
const btnText = document.getElementById('btnText');
const btnLoader = document.getElementById('btnLoader');
const errorMessage = document.getElementById('errorMessage');
const resultsSection = document.getElementById('resultsSection');
form.addEventListener('submit', async function(e) {
e.preventDefault();
// Show loading state
btnText.style.display = 'none';
btnLoader.style.display = 'inline-block';
analyzeBtn.disabled = true;
errorMessage.style.display = 'none';
resultsSection.style.display = 'none';
try {
const formData = new FormData(form);
const endpoint = `/predict/${mode}`;
const response = await fetch(endpoint, {
method: 'POST',
body: formData
});
if (!response.ok) {
throw new Error('Prediction failed');
}
const result = await response.json();
// Display results
displayResults(result);
} catch (error) {
console.error('Error:', error);
errorMessage.textContent = 'An error occurred during analysis. Please try again.';
errorMessage.style.display = 'block';
} finally {
// Reset button state
btnText.style.display = 'inline';
btnLoader.style.display = 'none';
analyzeBtn.disabled = false;
}
});
function displayResults(result) {
let html = '';
if (mode === 'fundus') {
html = generateFundusResults(result);
} else if (mode === 'oct') {
html = generateOCTResults(result);
} else if (mode === 'multimodal') {
html = generateMultimodalResults(result);
}
resultsSection.innerHTML = html;
resultsSection.style.display = 'block';
// Scroll to results
resultsSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
function generateFundusResults(result) {
const isGlaucoma = result.prediction === 'GON+';
const headerClass = isGlaucoma ? 'warning' : 'success';
return `
<div class="result-header ${headerClass}">
<div class="result-prediction">${result.prediction}</div>
<div class="result-confidence">Confidence: ${(result.confidence * 100).toFixed(1)}%</div>
</div>
<div class="result-grid">
<div class="result-card">
<h4>Original Image</h4>
<img src="data:image/jpeg;base64,${result.original_image}" class="result-image" alt="Original">
</div>
<div class="result-card">
<h4>Grad-CAM Visualization</h4>
${result.gradcam_image ?
`<img src="data:image/png;base64,${result.gradcam_image}" class="result-image" alt="Grad-CAM">` :
'<p>Visualization not available</p>'
}
</div>
</div>
<div class="clinical-features">
<div class="feature-item">
<div class="feature-label">vCDR (Cup-to-Disc Ratio)</div>
<div class="feature-value">${result.vcdr.toFixed(2)}</div>
</div>
<div class="feature-item">
<div class="feature-label">Prediction Confidence</div>
<div class="feature-value">${(result.confidence * 100).toFixed(1)}%</div>
</div>
</div>
<div class="interpretation">
<strong>Clinical Interpretation:</strong><br>
${result.interpretation}
</div>
`;
}
function generateOCTResults(result) {
const isNormal = result.prediction === 'NO';
const headerClass = isNormal ? 'success' : 'warning';
let top3HTML = result.top3.map((item, index) =>
`<div class="feature-item">
<div class="feature-label">${index + 1}. ${item.class}</div>
<div class="feature-value">${(item.probability * 100).toFixed(1)}%</div>
</div>`
).join('');
return `
<div class="result-header ${headerClass}">
<div class="result-prediction">${result.prediction}</div>
<div class="result-confidence">Confidence: ${(result.confidence * 100).toFixed(1)}%</div>
</div>
<div class="result-grid">
<div class="result-card">
<h4>Original Image</h4>
<img src="data:image/jpeg;base64,${result.original_image}" class="result-image" alt="Original">
</div>
<div class="result-card">
<h4>Grad-CAM Visualization</h4>
${result.gradcam_image ?
`<img src="data:image/png;base64,${result.gradcam_image}" class="result-image" alt="Grad-CAM">` :
'<p>Visualization not available</p>'
}
</div>
</div>
<div class="result-card">
<h4>Top 3 Predictions</h4>
<div class="clinical-features">
${top3HTML}
</div>
</div>
<div class="interpretation">
<strong>Clinical Interpretation:</strong><br>
${result.interpretation}
</div>
`;
}
function generateMultimodalResults(result) {
const isGlaucoma = result.prediction === 'GLAUCOMA';
const headerClass = isGlaucoma ? 'warning' : 'success';
return `
<div class="result-header ${headerClass}">
<div class="result-prediction">${result.prediction}</div>
<div class="result-confidence">Confidence: ${(result.confidence * 100).toFixed(1)}%</div>
</div>
<div class="result-grid">
<div class="result-card">
<h4>Fundus Image</h4>
<img src="data:image/jpeg;base64,${result.fundus_image}" class="result-image" alt="Fundus">
<h5 style="margin-top: 1rem;">Fundus Grad-CAM</h5>
${result.fundus_gradcam ?
`<img src="data:image/png;base64,${result.fundus_gradcam}" class="result-image" alt="Fundus Grad-CAM">` :
'<p>Visualization not available</p>'
}
</div>
<div class="result-card">
<h4>OCT Image</h4>
<img src="data:image/jpeg;base64,${result.oct_image}" class="result-image" alt="OCT">
<h5 style="margin-top: 1rem;">OCT Grad-CAM</h5>
${result.oct_gradcam ?
`<img src="data:image/png;base64,${result.oct_gradcam}" class="result-image" alt="OCT Grad-CAM">` :
'<p>Visualization not available</p>'
}
</div>
</div>
<div class="clinical-features">
<div class="feature-item">
<div class="feature-label">vCDR (Cup-to-Disc Ratio)</div>
<div class="feature-value">${result.vcdr.toFixed(2)}</div>
</div>
<div class="feature-item">
<div class="feature-label">RNFL Thickness</div>
<div class="feature-value">${result.rnfl.toFixed(1)} μm</div>
</div>
<div class="feature-item">
<div class="feature-label">Prediction Confidence</div>
<div class="feature-value">${(result.confidence * 100).toFixed(1)}%</div>
</div>
<div class="feature-item">
<div class="feature-label">Analysis Type</div>
<div class="feature-value">Multimodal</div>
</div>
</div>
<div class="interpretation">
<strong>Clinical Interpretation:</strong><br>
${result.interpretation}
</div>
`;
}