Motion Tracer Demo
MotionTracerDemo
@author Test Dept
/**
* Copyright Test_Dept ( http://wonderfl.net/user/Test_Dept )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/3Dmp
*/
package {
import flash.display.Bitmap;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.media.Camera;
import flash.media.Video;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
/**
* MotionTracerDemo
* @author Test Dept
*/
[SWF(backgroundColor="#cccccc", width="465", height="465")]
public class MotionTracerDemo extends Sprite {
private var _video : Video;
private var _tracer : MotionTracer;
private var _cursorPane : Sprite;
public function MotionTracerDemo() {
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
private function addedToStageHandler(event : Event) : void {
var camera : Camera = Camera.getCamera();
if (camera == null) {
var textField : TextField = new TextField();
textField.autoSize = TextFieldAutoSize.LEFT;
textField.text = "requires web camera.";
addChild(textField);
return;
}
camera.setMode(320, 240, 12, true);
_tracer = new MotionTracer(80, 60);
_video = new Video(camera.width, camera.height);
_video.x = 4;
_video.y = 4;
_video.attachCamera(camera);
addChild(_video);
var bmp : Bitmap = new Bitmap(_tracer.bitmapData);
bmp.x = _video.width + 8;
bmp.y = 4;
addChild(bmp);
_cursorPane = new Sprite();
addChild(_cursorPane);
addEventListener(Event.ENTER_FRAME, function(event : Event) : void {
_tracer.capture(_video);
} );
_tracer.addEventListener(Event.CHANGE, function(event : Event) : void {
var g : Graphics = _cursorPane.graphics;
var x : Number = _tracer.currentX * _video.width / _tracer.width;
var y : Number = _tracer.currentY * _video.height / _tracer.height;
g.clear();
g.lineStyle(2, 0x00ff00);
g.moveTo(x, 0);
g.lineTo(x, _video.height);
g.moveTo(0, y);
g.lineTo(_video.width, y);
} );
}
}
}
import flash.display.BitmapData;
import flash.media.Video;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.events.EventDispatcher;
import flash.events.Event;
import flash.filters.BlurFilter;
class MotionTracer extends EventDispatcher {
private const _matchThreshold : Number = 32;
private const _moveThreshold : Number = 64;
private const _percentMinMoved : Number = 0.1;
private const _percentMaxMoved : Number = 25;
private var _minMoved : Number;
private var _maxMoved : Number;
private var _width : Number;
private var _height : Number;
private var _calcBmp : BitmapData;
private var _lastBmp : BitmapData;
private var _currentX : Number;
private var _currentY : Number;
public function MotionTracer(width : Number, height : Number) {
_width = width;
_height = height;
_calcBmp = new BitmapData(width, height);
_lastBmp = null;
_currentX = 0;
_currentY = 0;
var numPixels : Number = width * height;
_minMoved = numPixels * _percentMinMoved / 100;
_maxMoved = numPixels * _percentMaxMoved / 100;
}
public function get bitmapData() : BitmapData {
return _calcBmp;
}
public function get currentX() : Number {
return _currentX;
}
public function get currentY() : Number {
return _currentY;
}
public function get width() : Number {
return _width;
}
public function get height() : Number {
return _height;
}
public function capture(video : Video) : void {
var bmp : BitmapData = new BitmapData(_width, _height);
var scaleX : Number = _width / video.width;
var scaleY : Number = _height / video.height;
bmp.draw(video, new Matrix(scaleX, 0, 0, scaleY) );
if (_lastBmp != null) {
calc(_lastBmp, bmp);
}
_lastBmp = bmp;
}
private function calc(bmp1 : BitmapData, bmp2 : BitmapData) : void {
var x : int;
var y : int;
_calcBmp.fillRect(new Rectangle(0, 0, _width, _height), 0xffffffff);
for (y = 0; y < _height; y++) {
for (x = 0; x < _width; x++) {
var match : Boolean = matchColor(
bmp1.getPixel(x, y), bmp2.getPixel(x, y) );
if (!match) {
_calcBmp.setPixel(x, y, 0x000000);
}
}
}
// LPF
_calcBmp.applyFilter(_calcBmp,
new Rectangle(0, 0, _width, _height),
new Point(0, 0),
new BlurFilter(2, 2) );
var numMoved : int = 0;
var moveX : Number = 0;
var moveY : Number = 0;
for (y = 0; y < _height; y++) {
for (x = 0; x < _width; x++) {
var value : int = _calcBmp.getPixel(x, y) & 0xff;
if (value < _moveThreshold) {
moveX += x;
moveY += y;
numMoved++;
}
}
}
if (_minMoved <= numMoved && numMoved <= _maxMoved) {
_currentX = moveX / numMoved;
_currentY = moveY / numMoved;
dispatchEvent(new Event(Event.CHANGE) );
}
}
private function matchValue(value : int) : Boolean {
return -_matchThreshold <= value && value <= _matchThreshold;
}
private function matchColor(color1 : uint, color2 : uint) : Boolean {
var rgb1 : Array = getRGB(color1);
var rgb2 : Array = getRGB(color2);
return matchValue(rgb1[0] - rgb2[0])
|| matchValue(rgb1[1] - rgb2[1])
|| matchValue(rgb1[2] - rgb2[2]);
}
private static function getRGB(color : uint) : Array {
return [(color >>> 16) & 0xff, (color >>> 8) & 0xff, color & 0xff];
}
}