In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

動体検知 + 肌色認識 2

Get Adobe Flash player
by alpicola 11 Feb 2009
/**
 * Copyright alpicola ( http://wonderfl.net/user/alpicola )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/fSCb
 */

package {
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.display.BlendMode;
	import flash.events.Event;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.filters.ColorMatrixFilter;
	import flash.filters.ConvolutionFilter;
	import flash.media.Camera;
	import flash.media.Video;

	[SWF(width="465", height="465", backgroundColor="#ffffff", frameRate="24")] 
	
	public class MotionDetection extends Sprite {
		
		private var camera:Camera;
		private var video:Video;
		private var now:BitmapData;
		private var prev:BitmapData;
		private var rec:Rectangle;
		private var pt:Point;
		private var noiseReduction:ConvolutionFilter;
		private var grayScale:ColorMatrixFilter;
		private var skin:ColorMatrixFilter;
		private var s:Sprite;
		private var objects:Vector.<MotionObject> = new Vector.<MotionObject>();
		
		public function MotionDetection() {
			stage.align = "TL";
			stage.scaleMode = "noScale";

			camera = Camera.getCamera();
			if (camera == null) return;
			camera.setMode(465, 465, 24);
			video = new Video(camera.width, camera.height);
			video.attachCamera(camera);
			addChild(video);
			s = new Sprite();
			addChild(s);

			now = new BitmapData(camera.width, camera.height, false);
			prev = new BitmapData(camera.width, camera.height, false);
			rec = new Rectangle(0, 0, camera.width, camera.height);
			pt = new Point();
			
			noiseReduction = new ConvolutionFilter(3, 3);
			noiseReduction.bias = -(0x1000 + 0x100 * 6);
			noiseReduction.matrix = [
				1,  1, 1,
				1, 16, 1,
				1,  1, 1
			];
			grayScale = new ColorMatrixFilter([
				0.3, 0.59, 0.11, 0, 0,
				0.3, 0.59, 0.11, 0, 0,
				0.3, 0.59, 0.11, 0, 0,
				0, 0, 0, 1, 0
			]);
			skin = new ColorMatrixFilter([
				0, 0, 0, 0, 0,
				-0.43, -0.85, 1.28, 0, 198.4,
				1.28, -1.07, -0.21, 0, 108.8,
				0, 0, 0, 1, 0
			]);
			
			addEventListener(Event.ENTER_FRAME, update);
		}

		private function update(e:Event):void {
			var rect:Rectangle;
			var rects:Vector.<Rectangle> = getRects();
			var candidates:Vector.<MotionObject> = new Vector.<MotionObject>();
			var intersects:Vector.<MotionObject>;
			var object:MotionObject;
			var n:int = objects.length;
			for (var i:int = 0, length:int = rects.length; i < length; i++) {
				rect = rects[i];
				if (rect.width * rect.height > video.width * video.height * 0.7) continue;

				intersects = new Vector.<MotionObject>();
				for (var j:int = 0; j < n; j++) {
					object = objects[j];
					if (object.rect.intersects(rect)) intersects.push(object);
				}

				var len:int = intersects.length;
				switch (len) {
					case 0:
						if (rect.width * rect.height > video.width * video.height * 0.02) {
							candidates.push(new MotionObject(rect));
						}
						break;
					case 1:
						intersects[0].move(rect);
						break;
					default:
						var result:MotionObject;
						var intersection:Rectangle;
						var size:int;
						var max:int = 0;
						while (len--) {
							object = intersects[len];
							intersection = rect.intersection(object.rect);
							size = intersection.width * intersection.height;
							if (size > max) {
								result = object;
								max = size;
							}
						}
						result.move(rect);
				}
			}

			while (n--) {
				object = objects[n];
				object.update();
				if (object.dead) objects.splice(n, 1);
			}


			n = candidates.length;
			while (n--) {
				objects.push(candidates[n]);
			}
			
			draw();
		}

		private function getRects():Vector.<Rectangle> {
			now.draw(video);
			var copy:BitmapData = now.clone();
			now.draw(prev, new Matrix(), new ColorTransform(), BlendMode.DIFFERENCE);
			prev = copy.clone();
			copy.applyFilter(now, rec, pt, skin);
			now.applyFilter(now, rec, pt, grayScale);
			now.threshold(now, rec, pt, ">", 0xff111111, 0xffffffff);
			//now.threshold(now, rec, pt, "!=", 0xffffffff, 0xff000000);
			now.threshold(copy, rec, pt, "!=", 0x008080, 0xff000000, 0x00c0c0);
			now.applyFilter(now, rec, pt, noiseReduction);

			var rects:Vector.<Rectangle> = new Vector.<Rectangle>();
			var rect:Rectangle;
			var bound:Rectangle = now.getColorBoundsRect(0xffffff, 0xffffff);
			var line:BitmapData = new BitmapData(rec.width, 1, false);
			var lineBound:Rectangle = new Rectangle(0, 0, rec.width, 1);
			while (!bound.isEmpty()) {
				lineBound.y = bound.y;
				line.copyPixels(now, lineBound, pt);
				bound = line.getColorBoundsRect(0xffffff, 0xffffff);
				now.floodFill(bound.x, lineBound.y, 0xff00ff);
				rect = now.getColorBoundsRect(0xffffff, 0xff00ff);
				rect.inflate(4, 4);
				now.fillRect(rect, 0x0000ff);
				rects.push(rect);
				bound = now.getColorBoundsRect(0xffffff, 0xffffff);
			}

			/*var length:int = rects.length;
			for (var i:int = 0; i < length; i++) {
				var rect1:Rectangle = rects[i];
				for (var j:int = i + 1; j < length; j++) {
					var rect2:Rectangle = rects[j];
					if (rect1.intersects(rect2)) {
						rects[j] = rect1.union(rect2);
						rects.splice(i, 1);
						i--;
						length--;
						break;
					}
				}
			}*/

			var m:int, n:int = rects.length;
			var rect1:Rectangle, rect2:Rectangle;
			while (n-- > 1) {
				rect1 = rects[n];
				m = n;
				while (m--) {
					rect2 = rects[m];
					if (!rect1.intersects(rect2)) continue;
					rects[m] = rect1.union(rect2);
					rects.splice(n, 1);
					break;
				}
			}

			return rects;
		}

		private function draw():void {
			s.graphics.clear();
			s.graphics.lineStyle(0, 0x00c0c0);
			var rect:Rectangle;
			for (var i:int = 0, length:int = objects.length; i < length; i++) {
				if (!objects[i].time) continue;
				rect = objects[i].rect;
				s.graphics.beginFill(0x00c0c0, 0.4);
				s.graphics.drawRect(rect.x, rect.y, rect.width, rect.height);
				s.graphics.endFill();
			}
		}

	}
}

import flash.geom.Rectangle;

class MotionObject {

	public var time:int = 0;
	public var dead:Boolean = false;
	public var rect:Rectangle;
	private var rects:Vector.<Rectangle> = new Vector.<Rectangle>();
	private var count:int = 5;

	function MotionObject(rect:Rectangle) {
		this.rect = rect;
	}

	public function move(rect:Rectangle):void {
		rects.push(rect);
	}

	public function update():void {
		time++;
		var len:int = rects.length;
		switch (len) {
			case 0:
				count--;
				if (!count) dead = true;
				break;
			case 1:
				count = 5;
				rect = rects[0];
				break;
			default:
				count = 5;
				rect = rects[0];
				while (--len) {
					rect = rect.union(rects[len]);
				}
		}
		if (rect.width > 8) rect.inflate(-4, 0);
		if (rect.height > 8) rect.inflate(0, -4);

		rects = new Vector.<Rectangle>();
	}

}