Prathamesh1420's picture
create a live object detection application from my camera - Initial Deployment
de71102 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Live Object Detection</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/coco-ssd"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.detection-box {
position: absolute;
border: 3px solid;
border-radius: 4px;
font-weight: bold;
text-shadow: 1px 1px 1px rgba(0,0,0,0.8);
padding: 2px 4px;
white-space: nowrap;
}
.video-container {
position: relative;
overflow: hidden;
border-radius: 12px;
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
}
.detection-canvas {
position: absolute;
top: 0;
left: 0;
pointer-events: none;
}
.stats-card {
backdrop-filter: blur(10px);
background: rgba(255, 255, 255, 0.1);
}
.detection-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
gap: 8px;
}
.detection-item {
transition: all 0.3s ease;
}
.detection-item:hover {
transform: translateY(-3px);
}
.pulse {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7); }
70% { box-shadow: 0 0 0 10px rgba(59, 130, 246, 0); }
100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); }
}
</style>
</head>
<body class="bg-gradient-to-br from-gray-900 to-gray-800 min-h-screen text-white">
<div class="container mx-auto px-4 py-8">
<header class="text-center mb-12">
<h1 class="text-4xl md:text-5xl font-bold mb-4 bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-purple-500">
Live Object Detection
</h1>
<p class="text-gray-300 max-w-2xl mx-auto">
Real-time object detection using your device's camera powered by TensorFlow.js and COCO-SSD model.
Grant camera access to start detecting objects in your environment.
</p>
</header>
<main>
<div class="flex flex-col lg:flex-row gap-8">
<!-- Camera Feed Section -->
<div class="lg:w-2/3">
<div class="video-container relative">
<video id="video" autoplay playsinline class="w-full h-auto rounded-lg bg-gray-800 aspect-video"></video>
<canvas id="canvas" class="detection-canvas w-full h-auto rounded-lg"></canvas>
<!-- Camera Access Prompt -->
<div id="cameraPrompt" class="absolute inset-0 flex flex-col items-center justify-center bg-gray-900 bg-opacity-80 rounded-lg">
<div class="text-center p-8">
<i class="fas fa-camera text-6xl text-blue-400 mb-4"></i>
<h2 class="text-2xl font-bold mb-2">Camera Access Required</h2>
<p class="text-gray-300 mb-6">Please allow camera access to enable live object detection</p>
<button id="startBtn" class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-3 px-8 rounded-full text-lg transition-all transform hover:scale-105 pulse">
Start Detection
</button>
</div>
</div>
</div>
<!-- Controls -->
<div class="mt-6 flex flex-wrap gap-4 justify-center">
<button id="toggleDetectionBtn" class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-6 rounded-lg flex items-center disabled:opacity-50">
<i class="fas fa-play mr-2"></i> Start Detection
</button>
<button id="toggleCameraBtn" class="bg-gray-700 hover:bg-gray-600 text-white font-medium py-2 px-6 rounded-lg flex items-center">
<i class="fas fa-sync mr-2"></i> Switch Camera
</button>
<button id="captureBtn" class="bg-purple-600 hover:bg-purple-700 text-white font-medium py-2 px-6 rounded-lg flex items-center">
<i class="fas fa-camera mr-2"></i> Capture Frame
</button>
</div>
</div>
<!-- Detection Results -->
<div class="lg:w-1/3">
<div class="bg-gray-800 bg-opacity-50 rounded-xl p-6 h-full">
<h2 class="text-2xl font-bold mb-4 flex items-center">
<i class="fas fa-list mr-3 text-blue-400"></i> Detection Results
</h2>
<div class="stats-card rounded-lg p-4 mb-6">
<div class="grid grid-cols-3 gap-4 text-center">
<div>
<div class="text-sm text-gray-300">Objects</div>
<div id="objectCount" class="text-2xl font-bold">0</div>
</div>
<div>
<div class="text-sm text-gray-300">FPS</div>
<div id="fpsCounter" class="text-2xl font-bold">0</div>
</div>
<div>
<div class="text-sm text-gray-300">Confidence</div>
<div id="avgConfidence" class="text-2xl font-bold">0%</div>
</div>
</div>
</div>
<h3 class="text-lg font-semibold mb-3 flex items-center">
<i class="fas fa-boxes mr-2 text-blue-400"></i> Detected Objects
</h3>
<div id="detectionList" class="detection-grid">
<!-- Detected items will appear here -->
<div class="text-center py-4 text-gray-400">
No objects detected yet
</div>
</div>
</div>
</div>
</div>
</main>
<footer class="mt-16 text-center text-gray-400">
<p>Powered by TensorFlow.js and COCO-SSD model | Built with Tailwind CSS</p>
<p class="mt-2">Note: Processing happens entirely in your browser - no data is sent to any server</p>
</footer>
</div>
<script>
// DOM Elements
const video = document.getElementById('video');
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const cameraPrompt = document.getElementById('cameraPrompt');
const startBtn = document.getElementById('startBtn');
const toggleDetectionBtn = document.getElementById('toggleDetectionBtn');
const toggleCameraBtn = document.getElementById('toggleCameraBtn');
const captureBtn = document.getElementById('captureBtn');
const objectCount = document.getElementById('objectCount');
const fpsCounter = document.getElementById('fpsCounter');
const avgConfidence = document.getElementById('avgConfidence');
const detectionList = document.getElementById('detectionList');
// App State
let model = null;
let detectionActive = false;
let stream = null;
let currentFacingMode = 'environment'; // 'user' for front, 'environment' for back
let lastTimestamp = 0;
let frameCount = 0;
let fps = 0;
let detectedObjects = [];
// Color palette for detection boxes
const colors = [
'#FF5252', '#FF4081', '#E040FB', '#7C4DFF',
'#536DFE', '#448AFF', '#40C4FF', '#18FFFF',
'#64FFDA', '#69F0AE', '#B2FF59', '#EEFF41'
];
// Initialize the app
async function init() {
try {
// Load the model
model = await cocoSsd.load();
console.log('Model loaded successfully');
// Set up event listeners
startBtn.addEventListener('click', startCamera);
toggleDetectionBtn.addEventListener('click', toggleDetection);
toggleCameraBtn.addEventListener('click', switchCamera);
captureBtn.addEventListener('click', captureFrame);
// Disable buttons until camera is started
toggleDetectionBtn.disabled = true;
toggleCameraBtn.disabled = true;
captureBtn.disabled = true;
} catch (error) {
console.error('Error loading model:', error);
alert('Failed to load the object detection model. Please try again later.');
}
}
// Start the camera
async function startCamera() {
try {
stream = await navigator.mediaDevices.getUserMedia({
video: { facingMode: currentFacingMode }
});
video.srcObject = stream;
cameraPrompt.classList.add('hidden');
toggleDetectionBtn.disabled = false;
toggleCameraBtn.disabled = false;
captureBtn.disabled = false;
// Wait for video to load metadata
video.addEventListener('loadedmetadata', () => {
// Set canvas dimensions to match video
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
// Start detection if button was clicked to start
if (detectionActive) {
detectFrame();
}
});
} catch (error) {
console.error('Error accessing camera:', error);
cameraPrompt.querySelector('p').textContent = 'Camera access denied. Please allow camera permissions and refresh the page.';
}
}
// Switch between front and back camera
async function switchCamera() {
if (!stream) return;
// Stop current stream
stream.getTracks().forEach(track => track.stop());
// Toggle facing mode
currentFacingMode = currentFacingMode === 'environment' ? 'user' : 'environment';
// Restart camera
await startCamera();
}
// Toggle detection on/off
function toggleDetection() {
detectionActive = !detectionActive;
if (detectionActive) {
toggleDetectionBtn.innerHTML = '<i class="fas fa-pause mr-2"></i> Pause Detection';
detectFrame();
} else {
toggleDetectionBtn.innerHTML = '<i class="fas fa-play mr-2"></i> Resume Detection';
}
}
// Capture current frame
function captureFrame() {
if (!detectionActive) return;
// Create a temporary canvas to draw the current frame
const tempCanvas = document.createElement('canvas');
tempCanvas.width = canvas.width;
tempCanvas.height = canvas.height;
const tempCtx = tempCanvas.getContext('2d');
// Draw video frame
tempCtx.drawImage(video, 0, 0, tempCanvas.width, tempCanvas.height);
// Draw detections
tempCtx.drawImage(canvas, 0, 0);
// Create download link
const link = document.createElement('a');
link.download = 'object-detection-' + new Date().toISOString().replace(/:/g, '-') + '.png';
link.href = tempCanvas.toDataURL('image/png');
link.click();
// Show notification
showNotification('Frame captured successfully!');
}
// Show notification
function showNotification(message) {
const notification = document.createElement('div');
notification.className = 'fixed bottom-4 right-4 bg-green-600 text-white px-4 py-2 rounded-lg shadow-lg z-50 animate-fadeIn';
notification.textContent = message;
document.body.appendChild(notification);
setTimeout(() => {
notification.classList.add('animate-fadeOut');
setTimeout(() => {
document.body.removeChild(notification);
}, 500);
}, 3000);
}
// Main detection function
async function detectFrame() {
if (!detectionActive || !model) return;
// Start timing for FPS calculation
const startTime = performance.now();
try {
// Detect objects in the frame
const predictions = await model.detect(video);
// Clear previous detections
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Process predictions
detectedObjects = [];
let totalConfidence = 0;
predictions.forEach((prediction, index) => {
// Extract prediction data
const [x, y, width, height] = prediction.bbox;
const label = prediction.class;
const score = Math.round(prediction.score * 100);
// Add to detected objects
detectedObjects.push({
label,
score,
color: colors[index % colors.length]
});
// Draw bounding box
ctx.strokeStyle = colors[index % colors.length];
ctx.lineWidth = 3;
ctx.strokeRect(x, y, width, height);
// Draw label background
ctx.fillStyle = colors[index % colors.length];
const textWidth = ctx.measureText(`${label} ${score}%`).width;
ctx.fillRect(x, y, textWidth + 10, 25);
// Draw label text
ctx.fillStyle = 'white';
ctx.font = 'bold 16px Arial';
ctx.fillText(`${label} ${score}%`, x + 5, y + 18);
// Add to total confidence for average
totalConfidence += score;
});
// Update stats
objectCount.textContent = predictions.length;
const avgConf = predictions.length > 0 ? Math.round(totalConfidence / predictions.length) : 0;
avgConfidence.textContent = `${avgConf}%`;
// Update detection list
updateDetectionList();
// Calculate FPS
frameCount++;
const elapsed = startTime - lastTimestamp;
if (elapsed >= 1000) {
fps = Math.round((frameCount * 1000) / elapsed);
fpsCounter.textContent = fps;
frameCount = 0;
lastTimestamp = startTime;
}
} catch (error) {
console.error('Detection error:', error);
}
// Continue detection loop
if (detectionActive) {
requestAnimationFrame(detectFrame);
}
}
// Update the detection list UI
function updateDetectionList() {
if (detectedObjects.length === 0) {
detectionList.innerHTML = '<div class="text-center py-4 text-gray-400 col-span-3">No objects detected</div>';
return;
}
// Clear previous list
detectionList.innerHTML = '';
// Create new items
detectedObjects.forEach(obj => {
const item = document.createElement('div');
item.className = 'detection-item bg-gray-700 rounded-lg p-3 flex flex-col items-center';
item.innerHTML = `
<div class="w-12 h-12 rounded-full mb-2 flex items-center justify-center" style="background-color: ${obj.color}">
<i class="fas fa-box text-white text-xl"></i>
</div>
<div class="font-semibold">${obj.label}</div>
<div class="text-sm text-gray-300">${obj.score}%</div>
`;
detectionList.appendChild(item);
});
}
// Initialize the app when the page loads
window.addEventListener('DOMContentLoaded', init);
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Prathamesh1420/live-camera-object-detection" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>