Motion Detection - Chrome Browser Crashes or No Image

I found some code… I have adapted it slightly (following watching a Dan Shiffman Processing video) - but can’t get it to work.

Here is the page I’ve created: Webcam motion detection

In the Shiffman video online - we see an outline of the ‘mover’ on the screen (the pixels turning black) but on mine - we never see any movement. In fact we only see a blank page.

The update I made was to introduce the distNew() function instead of using the dist() function (I kept getting an advisory message saying:

p5.js says: dist() was expecting at least 4 arguments, but received only 3.

and after a while - the browser crashes and my Chromebook shuts down.)

Any suggestions?

// Variable for capture device
var video;
// Previous Frame
var prevFrame;
// How different must a pixel be to be a “motion” pixel
var threshold = 50;

function setup() {
createCanvas(300, 150);
//frameRate=(10); // just trying to slow it down!
pixelDensity(1);
video = createCapture(VIDEO);
vw=video.width;// just seeing what the values are
vh=video.height;// just seeing what the values are
video.size(width, height);
video.hide();
// Create an empty image the same size as the video
prevFrame = createImage(video.width, video.height);
}

function draw() {
//image(prevFrame, 0, 0);

loadPixels();
video.loadPixels();
prevFrame.loadPixels();

// Begin loop to walk through every pixel
for (var x = 0; x < video.width; x++) {
for (var y = 0; y < video.height; y++) {

  // Step 1, what is the location into the array
  var loc = (x + y * 200) * 4;

  // Step 2, what is the previous color
  var r1 = prevFrame.pixels[loc];
  var g1 = prevFrame.pixels[loc + 1];
  var b1 = prevFrame.pixels[loc + 2];

  // Step 3, what is the current color
  var r2 = video.pixels[loc];
  var g2 = video.pixels[loc + 1];
  var b2 = video.pixels[loc + 2];

  // Step 4, compare colors (previous vs. current)
  var diff = distNew(r1, g1, b1, r2, g2, b2);
  // Step 5, How different are the colors?
  // If the color at that pixel has changed, then there is motion at that pixel.
  if (diff > threshold*threshold) {
    // If motion, display black
    pixels[loc] = 0;
    pixels[loc+1] = 0;
    pixels[loc+2] = 0;
    pixels[loc+3] = 0;
    
  } else {
    // If not, display white
    pixels[loc] = 255;
    pixels[loc+1] = 255;
    pixels[loc+2] = 255;
    pixels[loc+3] = 255;
    
  }
}

}
updatePixels();

// Save frame for the next cycle
//if (video.canvas) {
prevFrame.copy(video, 0, 0, video.width, video.height, 0, 0, video.width, video.height); // Before we read the new frame, we always save the previous frame for comparison!
//}

}

function distNew(x1,y1,z1,x2,y2,z2){
var d= (x2-x1)(x2-x1)+(y2-y1)(y2-y1)+(z2-z1)*(z2-z1);
return d;
}

1 Like

Changing this to remove the *4 seems to help.

Can anyone explain why?

Changing this…

var loc = (x + y * 200) * 4;

by removing the *4 helps.

Why?

Could you share a link of Daniel’s video, please?

At the moment I’m not certain what you’re going for, but some things I noticed:

  • The canvas and video have different sizes, is that on purpose? Commenting out video.size already shows more pixel thingies happening on the screen
  • The formula used to calculate var d in the function distNew didn’t work for me. Had to add some multiplication signs

Slightly edited version of your sketch:

You’re using a nested loop (the part where it says // Begin loop to walk through every pixel) to go through all pixels, starting at the left top and ending at the right bottom. Seeing you’re using a canvas of 300 x 150 pixels, this means:

  • the first pixel [0] is in the left top
  • the pixel in the right top is [299]
  • the pixel in the right bottom is (300 x 150 - 1) [44 999]

The variable loc is used to manipulate these values. It takes the value of the current x and y pixel and multiplies it by 200 and 4. You can imagine that when this number becomes too big, it gets placed outside the boundaries of your canvas. Try reducing the numbers and you’ll see the pixels get placed int he canvas again.

1 Like

My guess: because you are using loc to access a pixels array.

video.pixels[loc]

So, say you have 2000 pixels. And you ask for video.pixels[9999]. That generates an error, because there is no such pixel. That is why getting the math wrong on choosing a pixel value can lead to a sketch error when you try to access that pixel.

Edit looks like this was already addressed in part by Tiemen. Key concept: don’t ask for pixels[loc] or pixels[loc+3] that don’t exist.

1 Like