Object-Detection-Space / static /js /detection.js
derpiestme's picture
Upload 23 files
8491f89 verified
// Object Detection Interface Handler
document.addEventListener('DOMContentLoaded', () => {
// Mode switching
const modeButtons = document.querySelectorAll('.mode-btn');
const sections = {
'mode-webcam': document.getElementById('webcam-section'),
'mode-video': document.getElementById('video-section'),
'mode-image': document.getElementById('image-section')
};
modeButtons.forEach(btn => {
btn.addEventListener('click', () => {
// Update button styles
modeButtons.forEach(b => {
b.classList.remove('active', 'bg-white', 'text-zinc-900');
b.classList.add('bg-zinc-800', 'text-white');
});
btn.classList.add('active', 'bg-white', 'text-zinc-900');
btn.classList.remove('bg-zinc-800', 'text-white');
// Show/hide sections
Object.values(sections).forEach(s => s?.classList.add('hidden'));
sections[btn.id]?.classList.remove('hidden');
// Stop webcam if switching away
if (btn.id !== 'mode-webcam') {
stopWebcam();
}
});
});
// ===== WEBCAM MODE =====
const startWebcamBtn = document.getElementById('start-webcam');
const stopWebcamBtn = document.getElementById('stop-webcam');
const webcamStream = document.getElementById('webcam-stream');
const webcamStatus = document.getElementById('webcam-status');
let webcamInterval = null;
startWebcamBtn?.addEventListener('click', startWebcam);
stopWebcamBtn?.addEventListener('click', stopWebcam);
function startWebcam() {
webcamStatus.textContent = 'Starting webcam...';
webcamStream.src = '/webcam_feed';
webcamStream.classList.remove('hidden');
startWebcamBtn.classList.add('hidden');
stopWebcamBtn.classList.remove('hidden');
webcamStatus.textContent = 'Webcam active - detecting exercises...';
// Handle errors
webcamStream.onerror = () => {
webcamStatus.textContent = 'Error: Could not access webcam';
stopWebcam();
};
}
function stopWebcam() {
if (webcamStream) {
webcamStream.src = '';
webcamStream.classList.add('hidden');
}
if (webcamInterval) {
clearInterval(webcamInterval);
webcamInterval = null;
}
startWebcamBtn?.classList.remove('hidden');
stopWebcamBtn?.classList.add('hidden');
webcamStatus.textContent = '';
}
// ===== VIDEO UPLOAD MODE =====
const videoForm = document.getElementById('video-form');
const videoInput = document.getElementById('video-input');
const videoStream = document.getElementById('video-stream');
const videoStatus = document.getElementById('video-status');
videoForm?.addEventListener('submit', async (e) => {
e.preventDefault();
const file = videoInput.files?.[0];
if (!file) return;
videoStatus.textContent = 'Uploading video...';
try {
const formData = new FormData();
formData.append('video', file);
const res = await fetch('/upload_video', {
method: 'POST',
body: formData
});
const data = await res.json();
if (!res.ok || !data.ok) {
throw new Error(data.error || 'Upload failed');
}
videoStatus.textContent = 'Processing video...';
videoStream.src = `/video_feed/${data.video_id}`;
videoStream.classList.remove('hidden');
videoStatus.textContent = 'Video processing complete!';
} catch (err) {
console.error(err);
videoStatus.textContent = `Error: ${err.message}`;
}
});
// ===== IMAGE UPLOAD MODE =====
const imageForm = document.getElementById('image-form');
const imageInput = document.getElementById('image-input');
const previewBox = document.getElementById('preview');
const previewImg = document.getElementById('preview-img');
const imageStatus = document.getElementById('image-status');
const imageResult = document.getElementById('image-result');
// Preview handler
imageInput?.addEventListener('change', () => {
const file = imageInput.files?.[0];
if (!file) return;
const url = URL.createObjectURL(file);
previewImg.src = url;
previewBox.classList.remove('hidden');
imageStatus.textContent = '';
});
// Submit handler
imageForm?.addEventListener('submit', async (e) => {
e.preventDefault();
const file = imageInput.files?.[0];
if (!file) return;
imageStatus.textContent = 'Analyzing image...';
imageResult.innerHTML = '<div class="text-zinc-400 text-sm">Processing...</div>';
try {
const formData = new FormData();
formData.append('image', file);
const res = await fetch('/analyze_image', {
method: 'POST',
body: formData
});
const data = await res.json();
if (!res.ok || !data.ok) {
throw new Error(data.error || 'Analysis failed');
}
// Display results
const detections = data.detections || [];
const detectionCount = detections.length;
let resultsHTML = `
<div class="space-y-4">
<div class="flex justify-center">
<img src="${data.annotated_image}"
alt="Detected exercises"
class="rounded-lg border border-white/10 max-w-full">
</div>
<div class="text-lg font-semibold">
Found ${detectionCount} exercise${detectionCount !== 1 ? 's' : ''}
</div>
`;
if (detections.length > 0) {
resultsHTML += '<div class="space-y-3">';
detections.forEach((det, idx) => {
const conf = (det.confidence * 100).toFixed(1);
resultsHTML += `
<div class="bg-zinc-800/50 rounded-lg p-4 border border-white/5">
<div class="flex justify-between items-center">
<span class="font-semibold text-lg capitalize">${det.label}</span>
<span class="text-zinc-400">${conf}% confident</span>
</div>
</div>
`;
});
resultsHTML += '</div>';
// Add tips
if (data.tips && data.tips.length > 0) {
resultsHTML += '<div class="mt-4 space-y-2">';
resultsHTML += '<div class="font-semibold">Form Tips:</div>';
data.tips.forEach(tip => {
if (tip) {
resultsHTML += `<p class="text-zinc-300 text-sm">• ${tip}</p>`;
}
});
resultsHTML += '</div>';
}
}
resultsHTML += '</div>';
imageResult.innerHTML = resultsHTML;
imageStatus.textContent = '';
} catch (err) {
console.error(err);
imageStatus.textContent = `Error: ${err.message}`;
imageResult.innerHTML = '<div class="text-red-400 text-sm">Analysis failed. Please try again.</div>';
}
});
});