|
|
document.addEventListener('DOMContentLoaded', function() { |
|
|
const uploadForm = document.getElementById('uploadForm'); |
|
|
const submitBtn = document.getElementById('submitBtn'); |
|
|
const btnText = document.getElementById('btnText'); |
|
|
const loadingSpinner = document.getElementById('loadingSpinner'); |
|
|
const resultsSection = document.getElementById('results'); |
|
|
const errorSection = document.getElementById('error'); |
|
|
const videoInput = document.getElementById('video'); |
|
|
|
|
|
|
|
|
const ACTIONS = [ |
|
|
"barbell biceps curl", "lateral raise", "push-up", "bench press", |
|
|
"chest fly machine", "deadlift", "decline bench press", "hammer curl", |
|
|
"hip thrust", "incline bench press", "lat pulldown", "leg extension", |
|
|
"leg raises", "plank", "pull Up", "romanian deadlift", "russian twist", |
|
|
"shoulder press", "squat", "t bar row", "tricep Pushdown", "tricep dips" |
|
|
]; |
|
|
|
|
|
uploadForm.addEventListener('submit', async function(e) { |
|
|
e.preventDefault(); |
|
|
|
|
|
|
|
|
const hasFile = videoInput.files.length > 0; |
|
|
|
|
|
if (!hasFile) { |
|
|
showError('Please select a video file.'); |
|
|
return; |
|
|
} |
|
|
|
|
|
|
|
|
setLoadingState(true); |
|
|
hideResults(); |
|
|
hideError(); |
|
|
|
|
|
try { |
|
|
const formData = new FormData(); |
|
|
formData.append('video', videoInput.files[0]); |
|
|
|
|
|
const response = await fetch('/upload', { |
|
|
method: 'POST', |
|
|
body: formData |
|
|
}); |
|
|
|
|
|
const data = await response.json(); |
|
|
|
|
|
if (response.ok && data.success) { |
|
|
displayResults(data.results); |
|
|
} else { |
|
|
showError(data.error || 'An error occurred during processing.'); |
|
|
} |
|
|
} catch (error) { |
|
|
console.error('Upload error:', error); |
|
|
showError('Network error occurred. Please try again.'); |
|
|
} finally { |
|
|
setLoadingState(false); |
|
|
} |
|
|
}); |
|
|
|
|
|
function setLoadingState(loading) { |
|
|
submitBtn.disabled = loading; |
|
|
if (loading) { |
|
|
btnText.textContent = 'Processing...'; |
|
|
loadingSpinner.style.display = 'inline-block'; |
|
|
} else { |
|
|
btnText.textContent = 'Analyze Video'; |
|
|
loadingSpinner.style.display = 'none'; |
|
|
} |
|
|
} |
|
|
|
|
|
function showError(message) { |
|
|
document.getElementById('errorMessage').textContent = message; |
|
|
errorSection.style.display = 'block'; |
|
|
resultsSection.style.display = 'none'; |
|
|
} |
|
|
|
|
|
function hideError() { |
|
|
errorSection.style.display = 'none'; |
|
|
} |
|
|
|
|
|
function hideResults() { |
|
|
resultsSection.style.display = 'none'; |
|
|
} |
|
|
|
|
|
function displayResults(results) { |
|
|
console.log('Results:', results); |
|
|
|
|
|
|
|
|
displayPredictions('ensembleResults', results.ensemble_predictions); |
|
|
|
|
|
|
|
|
displayPredictions('stgcnResults', results.individual_predictions.stgcn); |
|
|
displayPredictions('transformerResults', results.individual_predictions.transformer_12rel); |
|
|
displayPredictions('angleResults', results.individual_predictions.transformer_angle); |
|
|
displayPredictions('swin3dResults', results.individual_predictions.swin3d); |
|
|
|
|
|
|
|
|
document.getElementById('stgcnTime').textContent = results.processing_times.stgcn.toFixed(2); |
|
|
document.getElementById('transformerTime').textContent = results.processing_times.transformer_12rel.toFixed(2); |
|
|
document.getElementById('angleTime').textContent = results.processing_times.transformer_angle.toFixed(2); |
|
|
document.getElementById('swin3dTime').textContent = results.processing_times.swin3d.toFixed(2); |
|
|
|
|
|
|
|
|
document.getElementById('totalTime').textContent = results.total_processing_time; |
|
|
document.getElementById('windowsProcessed').textContent = results.windows_processed || 'N/A'; |
|
|
document.getElementById('mediapipeTime').textContent = results.processing_times.mediapipe.toFixed(2); |
|
|
|
|
|
|
|
|
resultsSection.style.display = 'block'; |
|
|
hideError(); |
|
|
} |
|
|
|
|
|
function displayPredictions(containerId, predictions) { |
|
|
const container = document.getElementById(containerId); |
|
|
container.innerHTML = ''; |
|
|
|
|
|
predictions.forEach((pred, index) => { |
|
|
const predItem = document.createElement('div'); |
|
|
predItem.className = 'prediction-item'; |
|
|
|
|
|
const exerciseName = document.createElement('span'); |
|
|
exerciseName.className = 'exercise-name'; |
|
|
exerciseName.textContent = `${index + 1}. ${pred.exercise}`; |
|
|
|
|
|
const probability = document.createElement('span'); |
|
|
probability.className = 'probability'; |
|
|
probability.textContent = `${(pred.probability * 100).toFixed(1)}%`; |
|
|
|
|
|
const probabilityBar = document.createElement('div'); |
|
|
probabilityBar.className = 'probability-bar'; |
|
|
|
|
|
const probabilityFill = document.createElement('div'); |
|
|
probabilityFill.className = 'probability-fill'; |
|
|
probabilityFill.style.width = `${pred.probability * 100}%`; |
|
|
|
|
|
probabilityBar.appendChild(probabilityFill); |
|
|
|
|
|
predItem.appendChild(exerciseName); |
|
|
predItem.appendChild(probability); |
|
|
|
|
|
const predContainer = document.createElement('div'); |
|
|
predContainer.appendChild(predItem); |
|
|
predContainer.appendChild(probabilityBar); |
|
|
|
|
|
container.appendChild(predContainer); |
|
|
}); |
|
|
} |
|
|
}); |