家庭教師のトライをFlashで試してみた

こんな感じ
こんな感じ

SPARK Projectに顔認識用のライブラリがあるので家庭教師のトライにトライしてみました(ややこしい)。

画面に直接マウスで落書きすると、顔の動きに落書きが追随します。

サンプルはこちらのページにあります

動作にはWEBカメラが必要。あとめちゃくちゃ重いです。

ライブラリを普通に使ってるだけで特別なことしてないのがバレバレで恥ずかしいですが以下はコードです。重くて泣きたくなる場合は37行目のコメントアウトを外して代わりに38行目をコメントアウトしてみて下さい。

ドキュメントクラス-Main.as

顔認識は全部ここに突っ込んだ。

package {
	import flash.display.Sprite;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	//
	import flash.events.Event;
	//
	import flash.media.Camera;
	import flash.media.Video;
	import flash.events.ActivityEvent;
	//
	import jp.maaash.ObjectDetection.ObjectDetector;
	import jp.maaash.ObjectDetection.ObjectDetectorOptions;
	import jp.maaash.ObjectDetection.ObjectDetectorEvent;

	public class Main extends Sprite {
		private const VIDEO_SCALE:Number = .8;
		private const DEFAULT_FACE_RECT:Number = 50;
		private var camera:Camera;
		private var video:Video;
		private var detector:ObjectDetector;
		private var options:ObjectDetectorOptions;

		private var raku:Raku;
		function Main():void {
			init();
			initDetector();
		}
		private function init():void {
			camera = Camera.getCamera();
			if (camera != null) {
				video = new Video(stage.stageWidth, stage.stageHeight);
				video.attachCamera(camera);
				//camera.addEventListener(ActivityEvent.ACTIVITY, onCameraActivityHandler);
				addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
				addChild(video);
			}
			var target:Sprite = new Sprite();
			var g:Graphics = target.graphics;
			g.beginFill(0x000000, 0);
			g.drawRect(0, 0, stage.stageHeight*2, stage.stageWidth*2)
			g.endFill();
			addChild(target)
			raku = new Raku(target);
			addChild(raku);
		}
		private function initDetector():void {
			detector = new ObjectDetector;
			detector.options = getDetectorOptions();
			detector.addEventListener(ObjectDetectorEvent.DETECTION_COMPLETE, onDetectorCompleteHandler);
			detector.loadHaarCascades( '/samples/kao/face.zip' );
		}
		private function onCameraActivityHandler(e:ActivityEvent):void {
			if (e.activating) {
				addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
			} else {
				removeEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
			}
		}
		private function onEnterFrameHandler(e:Event):void {
			var bitmap:Bitmap = new Bitmap(new BitmapData(video.width, video.height, false));
			var matrix:Matrix = new Matrix();
			matrix.scale(VIDEO_SCALE, VIDEO_SCALE);
			bitmap.bitmapData.draw(video,matrix);
			detector.detect(bitmap);
		}
		private function onDetectorCompleteHandler(e:ObjectDetectorEvent):void {
			if ( e.rects ) {
				e.rects.forEach( function( r :Rectangle, idx :int, arr :Array ) :void {
				raku.moveRaku( r.x/VIDEO_SCALE, r.y/VIDEO_SCALE, r.width/VIDEO_SCALE, r.height/VIDEO_SCALE );
				});
			}
		}
		private function getDetectorOptions():ObjectDetectorOptions {
			options = new ObjectDetectorOptions;
			options.min_size  = 50;
			options.startx    = ObjectDetectorOptions.INVALID_POS;
			options.starty    = ObjectDetectorOptions.INVALID_POS;
			options.endx      = ObjectDetectorOptions.INVALID_POS;
			options.endy      = ObjectDetectorOptions.INVALID_POS;
			return options;
		}
	}
}

落書きするクラス-Raku.as

顔認識で得た矩形に合わせて拡大縮小してるだけ

package {

	import flash.display.Sprite;
	import flash.display.Graphics;
	import flash.events.MouseEvent;
	import flash.events.Event;
	public class Raku extends Sprite {
		private const DEFAULT_FACE_WIDTH:Number = 50;
		private const DEFAULT_FACE_HEIGHT:Number = 50;

		private var this_scale_x:Number = 1;
		private var this_scale_y:Number = 1;
		private var g:Graphics;
		private var target:Sprite;
		function Raku(mc:Sprite):void {
			target = mc;
			init();
		}
		private function init():void {
			target.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownHandler);
			Sprite(target).stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUpHandler);
			g = graphics;
			g.lineStyle(2, 0x000000);
		}
		private function onMouseDownHandler(e:MouseEvent):void {
			target.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveHandler);
			g.moveTo((e.stageX-x)/this_scale_x, (e.stageY-y)/this_scale_y);
		}
		private function onMouseUpHandler(e:MouseEvent):void {
			target.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveHandler);
		}
		private function onMouseMoveHandler(e:MouseEvent):void {
			g.lineTo((e.stageX-x)/this_scale_x, (e.stageY-y)/this_scale_y);
		}
		public function moveRaku(_x:Number, _y:Number, _width:Number, _height:Number):void{
			this.x = _x;
			this.y = _y;
			this_scale_x = _width/DEFAULT_FACE_WIDTH;
			this_scale_y = _height/DEFAULT_FACE_HEIGHT;
			this.scaleX = this_scale_x
			this.scaleY = this_scale_y
		}
	}
}

コメントを残す

メールアドレスが公開されることはありません。