Computer-Vision-Lab / movement-detection.html
YOUSEF2434's picture
Upload 96 files
a566fb0 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🕵️‍♂️ Secret Agent Motion Detector</title>
<style>
/* CSS: Making it look cool */
body {
background-color: #1a1a1a; /* Dark spy background */
color: #00ff41; /* Hacker green text */
font-family: 'Courier New', Courier, monospace; /* Typewriter font */
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
margin: 0;
padding: 20px;
}
h1 {
text-shadow: 0 0 10px #00ff41;
margin-bottom: 10px;
}
.instructions {
background: #222;
padding: 15px;
border-radius: 10px;
border: 1px solid #444;
max-width: 600px;
text-align: center;
margin-bottom: 20px;
color: #ddd;
}
/* The canvas where the magic happens */
#canvasFinal {
border: 4px solid #00ff41;
border-radius: 8px;
box-shadow: 0 0 20px rgba(0, 255, 65, 0.3);
background-color: #000;
max-width: 100%;
display: none; /* Hidden until camera starts */
}
/* Hide the raw video stream and processing canvas */
#camStream, #canvasHidden {
display: none;
}
button {
background-color: #00ff41;
color: #000;
border: none;
padding: 15px 30px;
font-size: 1.2rem;
font-weight: bold;
font-family: inherit;
cursor: pointer;
border-radius: 5px;
margin-bottom: 20px;
transition: all 0.3s;
}
button:hover {
background-color: #fff;
box-shadow: 0 0 15px #fff;
}
.status {
margin-top: 10px;
font-size: 0.9rem;
color: #888;
}
</style>
</head>
<body>
<button id="startBtn" onclick="startSpyCamera()">🚀 Activate Movement Detection Mode</button>
<p class="status" id="statusText">Waiting for activation...</p>
<!-- These are the HTML elements that handle the video -->
<video id="camStream" playsinline autoplay></video>
<canvas id="canvasHidden"></canvas>
<canvas id="canvasFinal"></canvas>
<script>
// JAVASCRIPT: The Brains of the Operation
// 1. Grab our HTML elements so we can control them
const video = document.getElementById('camStream');
const hiddenCanvas = document.getElementById('canvasHidden');
const finalCanvas = document.getElementById('canvasFinal');
const startBtn = document.getElementById('startBtn');
const statusText = document.getElementById('statusText');
// Contexts are like the "paintbrushes" for the canvas
const hiddenCtx = hiddenCanvas.getContext('2d');
const finalCtx = finalCanvas.getContext('2d');
// We need a place to store the "previous" frame to compare against
let previousFrameData = null;
async function startSpyCamera() {
try {
// 2. Ask the browser for permission to use the camera
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
// Connect the camera stream to our hidden video element
video.srcObject = stream;
// Update the UI
statusText.innerText = "System Active. Scanning for movement...";
startBtn.style.display = "none"; // Hide button
finalCanvas.style.display = "block"; // Show screen
// Start the loop!
requestAnimationFrame(processVideo);
} catch (err) {
// If they say no or don't have a camera
statusText.innerText = "⚠️ Error: Could not access camera. Please allow permission.";
console.error(err);
}
}
function processVideo() {
// Check if the video is ready and playing
if (video.readyState === video.HAVE_ENOUGH_DATA) {
// Set canvas sizes to match the video size
const width = video.videoWidth;
const height = video.videoHeight;
hiddenCanvas.width = width;
hiddenCanvas.height = height;
finalCanvas.width = width;
finalCanvas.height = height;
// 3. Draw the current video frame onto the hidden canvas
hiddenCtx.drawImage(video, 0, 0, width, height);
// 4. Get the pixel data (the raw numbers for every color)
const currentFrame = hiddenCtx.getImageData(0, 0, width, height);
const currentData = currentFrame.data;
// Create a new image for the result
const outputImage = finalCtx.createImageData(width, height);
const outputData = outputImage.data;
// 5. THE ALGORITHM: Compare this frame to the previous one
if (previousFrameData) {
const prevData = previousFrameData.data;
// Loop through every pixel (pixels are groups of 4: Red, Green, Blue, Alpha)
for (let i = 0; i < currentData.length; i += 4) {
// This math calculates the difference between old and new
// If pixels are the same, it turns GREY.
// If they are different, it creates high contrast colors.
outputData[i] = 0.5 * (255 - currentData[i]) + 0.5 * prevData[i]; // Red
outputData[i+1] = 0.5 * (255 - currentData[i+1]) + 0.5 * prevData[i+1]; // Green
outputData[i+2] = 0.5 * (255 - currentData[i+2]) + 0.5 * prevData[i+2]; // Blue
outputData[i+3] = 255; // Alpha (Opacity) is always 100%
}
// Draw the result to the main screen
finalCtx.putImageData(outputImage, 0, 0);
}
// 6. Save the current frame to be the "previous" frame for next time
// We clone it so we don't overwrite it immediately
previousFrameData = new ImageData(
new Uint8ClampedArray(currentFrame.data),
currentFrame.width,
currentFrame.height
);
}
// Repeat this function as fast as the screen can refresh
requestAnimationFrame(processVideo);
}
</script>
</body>
</html>