Detect and locate webcam motion in Flash 8
In this post I want to discuss the possibilities we have in Flash 8 to detect and locate motion. There are many sources online telling us how to detect motion (it's rather easy) but how can we locate where the movement exactly is going on? I will explain a few possibilities like so you can choose yourself which one works best…
Detecting changing brightness:
As Guy Watson is showing in his article on the Adobe website brightness changes are a good manner to detect motion. And by combining this with the difference blend mode, you can more or less detect where the motion is going on. If you want to know more about this approach you can see Guy's tutorial here. Ones you have isolated the changed pixels you can easely find the location of the most centered pixel value by using some Mathimatical expressions.
Detecting changing average color values
Another possibilty I came up with while experimenting this matter is tracking the webcamimage for changed color values with a given offset. Because we cannot track the change of every pixel (to slow and Flash will probably crash) we are going to track the average color change in a specific region. So we have to divide our webcam image in different parts, actually a grid.
So suppose we divide the webcam image into a grid of 100 cells. Each cell will have a rectangle of rect(0,0,16,12). So we have something like this for a webcam stream with dimension 160×120 pixels :

We can calculate the average colour for each of the cell in the webcam image grid using following code:
function computeAverageColor(bm:BitmapData):Number{
var totalR:Number = 0;
var totalG:Number = 0;
var totalB:Number = 0;
var count:Number = 0;
for (var j:Number = 0; j<bm.height; j++) {
for (var i:Number = 0; i<bm.width; i++) {
var col:Number = bm.getPixel(i, j);
var red:Number = (col & 0xFF0000) >>> 16;
var green:Number = (col & 0×00FF00) >>> 8;
var blue:Number = col & 0×0000FF;
totalR += red;
totalG += green;
totalB += blue;
count++;
}
}
var targetR:Number = Math.round(totalR/count);
var targetG:Number = Math.round(totalG/count);
var targetB:Number = Math.round(totalB/count);
//combine the color and return target color value
//…
}
As you can see in the funcion computeAverageColor we are adding up the separate color channel values and at the end we divide each sum with the total number of pixels in that specific tile "bm". Now we have three separate average channel values so next thing we have to do is combining this in one average color value by writing this code at the end of the function:
var targetCol:Number = targetR << 16 | targetG << 8 | targetB; return targetCol;
To divide the actual webcam image in those separate tiles I made a custom class BitmapBlock (extending on the Bitmapdata class) where I use the copyPixels method to extract a tile from the webcam image with the specific source rectangle as parameter.
Next thing to do is actually compare the tiles color every time the Camera.onActivity() handler is invoked. So we must store the tiles in an Array where I also hold a reference to the position of the tile on the Stage. We know when something moves in the camview the average color value will change. By measuring the change (if the difference is huge enough to be considered as a motion) we can know in wich region the motion is detected and by example make a snapshot of that specific region.
I did a few tests but I have to say that Flash 8 is a bit to slow for actual commercial use but it's a challenge to work around this and I hope by experimenting on this issue you will get a better understanding about the BitmapData and Camera class possibilities. If you want to make something that is actually usable, try experimenting with Adobe Director and the Webcam Xtra you can find here. Another possibility is offcourse Actionscript 3.0 where it all goes much faster :-).
If you have other possibilities to track and locate motion, feel free to comment this post
Happy coding,
Koen
PS: I started with this experimenting because I was thinking about a smart shooter game where the computer always follows you and tries to shoot you down
Filed under: Flash 8



















Looping thru each pixel in each 16×12 block is always going to be a expensive operation. You could get around this by simply scaling your entire 160×120 image by 0.1, therefore ending up with a 16×12 image - each pixel should represent the average color - thus aboviding many getPixel’s.
This does however depend on how good the anti-aliasing is in the scaling operation. You also try bluring the image before the scale, and setting the bitmap to smooth.
Just a thought, not tested but should work.
yeah indeed, getPixel() is rather slow. The combination of AS3
and scaling will definitely do the job I guess.
Syla - though the idea sounds logical it will not work like this in Flash - scaling down a 10×10 pixel block to 1 pixel will NOT give you the average value of those 100 pixels but only the average of a few of them (the amount and which are included depends on the _quality settings).
If you want to get some better approximation for the average you should apply the blur filter first - which is part of the technique I use in my Minority Cube (http://incubator.quasimondo.com/flash/minority_cube.php)
Oops Syla - somehow I overread your second paragraph - sorry
For a different approach to this problem, see my flex derby submission here .
very interesting indeed. Raf did a motion checker once using the colour differences. Problem is the colour contrast has to be rather high. So were a black suit on a white background if you play this game.
Btw, nice jumping around ^^
hahhaha,thank
let me put it into my bookmark
i think i need to use many day to study it
Hey gang. I am finally got some time to start playing around with Flash 8 and a web cam. I’ve been very inspired by all the work I’ve come across from Guy Watson, Gskinner, and you all as well.
I love reverse engineering these things, that’s really the fun part. But I wouldn’t mind being pointed in the right direction, if anyone has discovered some new and improved approaches to motion capture. Esp those that all you to track specific points/colors/etc.
Any suggestions are very much appreciated. Cheers!
Thanks, this was a great help in creating a pixellating effect I needed to build. I too experienced a slowdown caused by the code reading the color values for each pixel so I just changed i++ and j++ to i+=2 and j+=2, obviously you could increase these even more but I found the results were almost identical to the single increments, but done in half the time, so they were a good trade-off. All the best, Tim.
Wow, I had no idea this was possible (yes I’m a real newbie lol)
Thanks for posting
hi, I am trying to make a character on screen react to
a motion tracked by a webcam. does anyone know
how to do it? it should be easy, but i’m a novice.
can a change in motion trigger flash to gotoAndPlay?
very interesting, but I don’t agree with you
Idetrorce
Hi - This is good stuff. Does anyone know how to convert the BitmapData to 256 colors in order to simplify doing some color-specific Bitmap analysis?
Thanks! Adam
Hi @sophia if you look on my blog http://www.tobytremayne.com/index.cfm/2007/3/4/Flex-2–Webcam-motion-tracking-part-3 I’ve done something like what you’re talking about - you should be able to reuse the code. I’m actually doing something a bit more advanced at the moment so if it works out I’ll blog that too
[...] und so funktionierts: klick mich klick mich klick mich [...]
Wow this was great, you learn new stuff every day