|
document.addEventListener("DOMContentLoaded", () => { |
|
document |
|
.getElementById("detectBtn") |
|
.addEventListener("click", onDetectEmotionClick); |
|
document.getElementById("settingsBtn").addEventListener("click", onDetectEmotionClick); |
|
initWebcam(); |
|
const technicalSection = document.getElementById("technical-section"); |
|
technicalSection.style.display = "none"; |
|
}); |
|
|
|
|
|
async function sendImageToBackend(imageData) { |
|
try { |
|
|
|
const base64String = imageData.src.split(',')[1]; |
|
|
|
const response = await fetch("/upload", { |
|
method: "POST", |
|
headers: { |
|
"Content-Type": "application/json", |
|
}, |
|
body: JSON.stringify({ |
|
image: base64String |
|
}) |
|
}); |
|
|
|
if (!response.ok) { |
|
throw new Error(`Server responded with status: ${response.status}`); |
|
} |
|
const result = await response.json(); |
|
console.log("Emotion detection result:", result); |
|
return result; |
|
} catch (error) { |
|
console.error("Error during API call:", error); |
|
throw error; |
|
} |
|
} |
|
|
|
async function onDetectEmotionClick() { |
|
const initialContent = document.getElementById("initial-content"); |
|
const calculatingContent = document.getElementById("calculating-content"); |
|
const detectBtn = document.getElementById("detectBtn"); |
|
const technicalSection = document.getElementById("technical-section"); |
|
const loadingSpinner = document.querySelector(".loading-spinner"); |
|
|
|
try { |
|
|
|
initialContent.style.display = "none"; |
|
calculatingContent.style.display = "flex"; |
|
detectBtn.style.opacity = "0"; |
|
loadingSpinner.style.display = "block"; |
|
|
|
|
|
technicalSection.style.display = "none"; |
|
|
|
|
|
const capturedImage = captureImage(); |
|
const result = await sendImageToBackend(capturedImage); |
|
|
|
if (result.error) { |
|
throw new Error(result.error); |
|
} |
|
|
|
|
|
loadingSpinner.style.display = "none"; |
|
|
|
|
|
technicalSection.style.display = "block"; |
|
void technicalSection.offsetWidth; |
|
technicalSection.classList.add('visible'); |
|
|
|
|
|
updateTechnicalSection(result); |
|
|
|
|
|
document.querySelector(".result-emoji").textContent = result.emoji; |
|
document.querySelector(".result-comment").textContent = getEmotionMessage(result.emotion); |
|
|
|
|
|
detectBtn.innerHTML = '<i class="fas fa-code mr-2"></i>Show Details'; |
|
detectBtn.style.opacity = "1"; |
|
|
|
|
|
detectBtn.removeEventListener('click', onDetectEmotionClick); |
|
detectBtn.addEventListener('click', handleShowDetails); |
|
|
|
} catch (error) { |
|
console.error("Error:", error); |
|
loadingSpinner.style.display = "none"; |
|
document.querySelector(".result-emoji").textContent = "β"; |
|
document.querySelector(".result-comment").textContent = "Failed to detect emotion. Please try again."; |
|
detectBtn.style.opacity = "1"; |
|
technicalSection.style.display = "none"; |
|
} |
|
} |
|
|
|
|
|
document.addEventListener("DOMContentLoaded", () => { |
|
const detectBtn = document.getElementById("detectBtn"); |
|
const settingsBtn = document.getElementById("settingsBtn"); |
|
const technicalSection = document.getElementById("technical-section"); |
|
|
|
|
|
technicalSection.style.display = "none"; |
|
|
|
|
|
detectBtn.addEventListener("click", onDetectEmotionClick); |
|
settingsBtn.addEventListener("click", onDetectEmotionClick); |
|
|
|
initWebcam(); |
|
}); |
|
|
|
function updateTechnicalSection(result) { |
|
console.log("Full result:", result); |
|
console.log("Processing steps:", result.processing_steps); |
|
console.log("Detailed steps:", result.processing_steps.detailed_steps); |
|
|
|
|
|
document.getElementById("preprocessed-image").innerHTML = ` |
|
<img src="${result.grayscale_image}" alt="Preprocessed Image" class="preprocessed-image"> |
|
<div class="processing-info"> |
|
<p>Image Size: ${result.processing_steps.original_size[0]}x${result.processing_steps.original_size[1]}</p> |
|
<p>Color Mode: ${result.processing_steps.color_mode}</p> |
|
</div> |
|
`; |
|
|
|
|
|
const processSteps = result.processing_steps.detailed_steps; |
|
if (!processSteps) { |
|
console.error("No processing steps found in result"); |
|
return; |
|
} |
|
|
|
let stepsHtml = '<div class="process-flow">'; |
|
|
|
|
|
try { |
|
for (const [stage, steps] of Object.entries(processSteps)) { |
|
console.log("Processing stage:", stage, steps); |
|
const stageName = stage.split('_').map(word => |
|
word.charAt(0).toUpperCase() + word.slice(1) |
|
).join(' '); |
|
|
|
stepsHtml += ` |
|
<div class="process-stage"> |
|
<h4>${stageName}</h4> |
|
<ul class="step-list"> |
|
${Array.isArray(steps) ? steps.map(step => `<li>${step}</li>`).join('') : ''} |
|
</ul> |
|
</div> |
|
`; |
|
} |
|
stepsHtml += '</div>'; |
|
|
|
|
|
stepsHtml += ` |
|
<div class="model-info"> |
|
<h4>MODEL SPECIFICATIONS</h4> |
|
<ul class="step-list"> |
|
<li>Type: ${result.processing_steps.model_type}</li> |
|
<li>Input Shape: ${result.processing_steps.input_shape}</li> |
|
<li>Output: ${result.processing_steps.output_classes}</li> |
|
</ul> |
|
</div> |
|
`; |
|
|
|
console.log("Generated HTML:", stepsHtml); |
|
document.getElementById("processing-steps").innerHTML = stepsHtml; |
|
} catch (error) { |
|
console.error("Error generating steps HTML:", error); |
|
} |
|
|
|
|
|
const probContainer = document.getElementById("emotion-probabilities"); |
|
probContainer.innerHTML = ""; |
|
|
|
Object.entries(result.model_probabilities).forEach(([emotion, probability]) => { |
|
const percentage = (probability * 100).toFixed(1); |
|
const barElement = document.createElement('div'); |
|
barElement.className = 'probability-bar probability-bar-custom probability-bar-width'; |
|
barElement.style.setProperty('--percentage', `${percentage}%`); |
|
|
|
probContainer.innerHTML += ` |
|
<div class="probability-label"> |
|
<span>${emotion}</span> |
|
<span>${percentage}%</span> |
|
</div> |
|
`; |
|
probContainer.appendChild(barElement); |
|
}); |
|
|
|
|
|
document.getElementById("detected-emoji").textContent = result.emoji; |
|
document.getElementById("detected-emotion").textContent = result.emotion; |
|
document.getElementById("confidence-score").querySelector("h4").textContent = |
|
`${(result.model_probabilities[result.emotion] * 100).toFixed(1)}%`; |
|
} |
|
|
|
function getEmotionMessage(emotion) { |
|
const messages = { |
|
happy: "You're radiating happiness! Your smile lights up the room! π", |
|
sad: "I see some sadness there. Remember, every cloud has a silver lining! π", |
|
angry: "Whoa, looking pretty fired up! Take a deep breath and count to ten. π§", |
|
disgust: "That's quite the expression! Something leave a bad taste? π", |
|
fear: "I sense some anxiety there. Remember, you're stronger than you think! πͺ", |
|
surprise: "Well, that caught you off guard! What an unexpected moment! π²", |
|
neutral: "Keeping it cool and collected with that poker face! π" |
|
}; |
|
return messages[emotion] || "Interesting expression you've got there! π€"; |
|
} |
|
|
|
|
|
function handleShowDetails() { |
|
const technicalSection = document.getElementById("technical-section"); |
|
|
|
technicalSection.style.display = "block"; |
|
|
|
setTimeout(() => { |
|
technicalSection.scrollIntoView({ |
|
behavior: "smooth", |
|
block: "start" |
|
}); |
|
}, 100); |
|
} |
|
|