mjpg-streamer/www/javascript_motiondetection....

193 lines
6.1 KiB
HTML

<html>
<head>
<title>MJPEG-Streamer</title>
<!-- refresh page after a few seconds, prevents hang-ups -->
<meta http-equiv="refresh" content="60" />
</head>
<script language="javascript" type="text/javascript" src="functions.js"></script>
<script type="text/javascript">
/*******************************************************************************
Copyright (C) 2009 Tom Stoeveken
This program is free software;
you can redistribute it and/or modify it under the terms of the
GNU General Public License, version 2.
See the file COPYING for details.
*******************************************************************************/
var img1 = null;
var img2 = null;
var canvas = null;
/*
compare two images and count the differences
input.: image1 and image2 are Image() objects
input.: canvas is a Canvas() object to draw with
input.: threshold specifies by how much the color value of a pixel
must differ before they are regarded to be different
return: number of different pixels
*/
function compare(image1, image2, canvas, threshold) {
var movement = 0;
var ctx = canvas.getContext("2d");
var width = canvas.width/2, height = canvas.height/2;
// copy images into canvas element
// these steps scale the images and decodes the image data
ctx.drawImage(image1, 0, 0, width, height);
ctx.drawImage(image2, width, 0, width, height);
// this makes r,g,b,alpha data of images available
var pixels1 = ctx.getImageData(0, 0, width, height);
var pixels2 = ctx.getImageData(width, 0, width, height);
var pixels_diff = ctx.getImageData(0, 0, width, height);
// substract picture1 from picture2
// if they differ set color value to max,
// if the difference is below threshold set difference to 0.
for (var x = 0; x < pixels1.width; x++) {
for (var y = 0; y < pixels1.height; y++) {
// each pixel has a red, green, blue and alpha value
// all values are stored in a linear array
var i = x*4 + y*4*pixels1.width;
pixels_diff.data[i] = (Math.abs(pixels1.data[i] - pixels2.data[i])>threshold)?255:0;
pixels_diff.data[i+1] = (Math.abs(pixels1.data[i] - pixels2.data[i])>threshold)?255:0;
pixels_diff.data[i+2] = (Math.abs(pixels1.data[i] - pixels2.data[i])>threshold)?255:0;
pixels_diff.data[i+3] = 255;
// count differing pixels
movement += Math.min(1, pixels_diff.data[i] + pixels_diff.data[i+1] + pixels_diff.data[i+2]);
}
}
ctx.putImageData(pixels_diff, width/2, height);
return movement;
}
/*
Callback function for completed picture downloads
With every new picture a compare() is performed.
The new picture is 'img1', the previous picture is stored in 'img2'.
*/
function newPictureComplete() {
// just compare if there are two pictures
if ( img2 != null ) {
var res;
try {
// compare the two pictures, the given threshold helps to ignore noise
res = compare(img1, img2, canvas, 50);
}
catch(e) {
// errors can happen if the pictures were corrupted during transfer
// instead of giving up, just proceed
}
// show to the user if we regards this as motion
// decide for a color depending on movement (more then N pixels)
// draw into free area of canvas
// (hardcoded positions for better performance)
var ctx = canvas.getContext("2d");
ctx.fillStyle = ( res > 5 ) ? "rgb(200,0,0)" : "rgb(0,200,0)";
ctx.fillRect (0, 50, 25, 50); ctx.fillRect (75, 50, 25, 50);
// send server our finding that there was some movement
if ( res > 5 ) {
AJAX_get('./?action=command&command=store')
}
}
// copy reference of img1 to img2
img2 = img1;
img2.onload = null;
// load a new picture into img1
img1 = new Image();
img1.onload=newPictureComplete;
// load next picture in a few milliseconds
// the server blocks anyway until a fresh picture has arrived, so it can never be faster
// than the framerate. This timeout is intended to have the option
// to lower the required processing power at client side.
window.setTimeout("img1.src='./?action=snapshot&unique='+Math.random();", 1);
}
/*
Initialize the elements
* Create a Canvas() object and insert it into the page
* Download the first image
* Pause the Livestream again if we were paused previously
This way we will not pause, but we will lower the refresh rate
For a proper pause, the page can not be reloaded
*/
function run() {
canvas = document.createElement("canvas");
canvas.width = 100;
canvas.height = 100;
canvas.id = "comparison_canvas";
document.getElementById("comparison").appendChild(canvas);
img1 = new Image();
img1.onload=newPictureComplete;
img1.src = "./?action=snapshot";
if ( window.name.indexOf('paused') != -1 )
play_pause(document.getElementById("stream"));
}
/*
Callback function for AJAX command
input.: text is the response of the server
*/
function AJAX_response(text) {
// nothing to do
// later we might show a little folder symbol or so that dissapears
// after a while
}
/*
can toggle play/pause of the HTTP-push live preview
input.: 'img' is the Image() object displaying the stream/picture
*/
function play_pause(img) {
if ( img.src.indexOf('./?action=stream') != -1 ) {
img.src = "./?action=snapshot&unique="+Math.random();
// to keep the play/pause state over a page reload
// this persistent property of the window can be (mis)used
// it is a simple, but not so clean way of doing it
// a cookie or server side scripting would be better in order to
// pass information from one page to the other (reload)
window.name = 'paused';
} else {
img.src = "./?action=stream";
window.name = 'streaming';
}
}
</script>
<body onload="run()">
<fieldset style="background-color: silver; width: 200px; float: left">
<legend style="background-color: silver; border: 1px solid black">Motion Detection</legend>
<div id="comparison"></div>
</fieldset>
<fieldset style="background-color: silver; width: 50%">
<legend style="background-color: silver; border: 1px solid black">Lifestream</legend>
<img id="stream" src="./?action=stream" width="100%" onclick="play_pause(this)" />
</fieldset>
</body>
</html>