動体検知 + 肌色認識 2 alpicola forked:0favorite:8lines:207license : MIT License modified : 2009-02-11 14:29:49 Embed Tweet 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>(); } } Code Fullscreen Preview Fullscreen jmk2 douglasarts ProjectNya buccchi zahir amp_green : cameramotion動体検知 Joker : 動体検知 zmaxlin : cameramotion camera motion 動体検知 Rectangle intersects inflate intersection size copy width Math.max ConvolutionFilter union bias Video clear BlendMode.DIFFERENCE addEventListener isEmpty matrix attachCamera clone splice