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

あの人メイカー(全自動版)

1. イケてる自分の顔をwebカメラに映す。
2. SAVEボタンではいチーズ!
 ほんとはsaqooshaさんのクマ帽子の画像でやりたいけど画像ない・・・
顔ラボ:顔検出WebAPI仕様
http://kaolabo.com/webapi/spec
/**
 * Copyright fumix ( http://wonderfl.net/user/fumix )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/oZhR
 */

// 1. イケてる自分の顔をwebカメラに映す。
// 2. SAVEボタンではいチーズ!
//
// ほんとはsaqooshaさんのクマ帽子の画像でやりたいけど画像ない・・・
//
// 顔ラボ:顔検出WebAPI仕様
// http://kaolabo.com/webapi/spec

package {
	import com.bit101.components.PushButton;

	import mx.graphics.codec.JPEGEncoder;

	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.media.Camera;
	import flash.media.Video;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.system.LoaderContext;
	import flash.text.TextField;
	import flash.utils.ByteArray;
	import flash.utils.Timer;

	/**
	 * @author fumix
	 */
	[SWF(backgroundColor="#000000", frameRate="31", width="465", height="465")]

	public class AnohitoMaker extends Sprite {

		private var _camera : Camera;
		private var _w : int;
		private var _h : int;
		private var _video : Video;
		private var _startScale : Number;
		private var _startPoint : Point;
		private var _ude : Sprite;
		private var _megane : Sprite;
		private var _referenceObject : Sprite;
		private var _btn : PushButton;
		private var _timer : Timer;
		private var _count : int;
		private var _xml:XML;

		private const APIURL : String = 'http://www.planet-ape.net/wonderfl/kaolabo.php';

		/**
		 * コンストラクタ
		 */
		public function AnohitoMaker() {
			if (stage) initialize();
			else addEventListener(Event.ADDED_TO_STAGE, initialize);			
		}

		/**
		 * 初期化
		 * @param event 
		 */
		private function initialize(event : Event = null) : void {
			removeEventListener(Event.ADDED_TO_STAGE, initialize);
			//プロパティの初期化
			_startPoint = new Point();
			//背景
			_w = stage.stageWidth;
			_h = stage.stageHeight;
			var bmd : BitmapData = new BitmapData(_w, _h, true, 0x000000);
			addChild(new Bitmap(bmd));
			
			//webカメラ
			_camera = Camera.getCamera();

			//カメラあり
			if(_camera != null) {
				setupCamera();
            //カメラ無し
			} else {
				var txt : TextField = new TextField();
				txt.textColor = 0xFFFFFF;
				txt.text = 'カメラ無し';
				addChild(txt);
			}
			//あの画像読み込み
			var url : String = "http://assets.wonderfl.net/images/related_images/e/ec/ec7f/ec7fd9e7c7419800b86347d36243def006e5f365";
			var loader : Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleteHandler);
			loader.load(new URLRequest(url), new LoaderContext(true));
			
			//保存ボタン
			_btn = new PushButton(this, 0, 0, 'capture', buttonClickHandler);
		}

		/**
		 * ボタンクリック
		 * @param event
		 */
		private function buttonClickHandler(event : MouseEvent) : void {
			//タイマーハンドラ(カウントダウン)
			_count = 3;
			_btn.label = String(_count);
			_timer = new Timer(1000, 3);
			_timer.addEventListener(TimerEvent.TIMER, timerHandler);
			_timer.start();
		}

		/**
		 * 顔認識APIリクエスト
		 */
		private function requestAPIFacialRecognition() : void {
			//画像バイナリ生成
			var cap : BitmapData = new BitmapData(_w, _h);
			cap.draw(_video);
			var enc : JPEGEncoder = new JPEGEncoder(80);
			var byteArray : ByteArray = enc.encode(cap);
			addChild(new Bitmap(cap));

			//POSTリクエスト生成
			var request:URLRequest = new URLRequest(APIURL);
			request.method = URLRequestMethod.POST;
			request.contentType = "image/jpeg";
			request.data = byteArray;
			
			//リクエスト用ローダー生成
			var loader:URLLoader = new URLLoader(request);
			loader.addEventListener(Event.COMPLETE, onLoaderComplate);
			//リクエスト実行
			loader.load(request);
		}
		/**
		 * リクエスト実行完了
		 * @param event
		 */
		private function onLoaderComplate(event : Event) : void {
			//スコア
			var score:Number = 0;
			//戻り値
			_xml = deleteNameSpace(event.target.data);
			var faces : XMLList = _xml.faces[0].face;
			//顔認識されなかった場合
			if(faces.length() < 1){
				var txt : TextField = new TextField();
				txt.textColor = 0xFFFFFF;
				txt.text = 'no faces!';
				addChild(txt);
				return;
			}

			//認識した顔から腕とメガネの位置と角度とスケールを計算
			var megane_width:Number = 64;
			var megane_distX:Number = (faces[0].elements('left-eye').@x - faces[0].elements('right-eye').@x);
			var megane_distY:Number = (faces[0].elements('left-eye').@y - faces[0].elements('right-eye').@y);
			var megane_dist:Number = Math.sqrt(megane_distX * megane_distX+megane_distY*megane_distY);
			var megane_scale:Number = megane_dist / megane_width;
			var megane_rotation:Number = Math.atan2((faces[0].elements('left-eye').@y - faces[0].elements('right-eye').@y), (faces[0].elements('left-eye').@x - faces[0].elements('right-eye').@x)) * 180 / Math.PI;
		
			_megane.scaleX = _megane.scaleY = _ude.scaleX = _ude.scaleY = megane_scale;
			_megane.x = Number(faces[0].elements('right-eye').@x) + (faces[0].elements('left-eye').@x - faces[0].elements('right-eye').@x)/ 2;
			_megane.rotation = megane_rotation;
			if(faces[0].elements('right-eye').@y > faces[0].elements('left-eye').@y){
				_megane.y = Number(faces[0].elements('left-eye').@y) + (faces[0].elements('right-eye').@y - faces[0].elements('left-eye').@y)/2;				
			}else{
				_megane.y = Number(faces[0].elements('right-eye').@y) + (faces[0].elements('left-eye').@y - faces[0].elements('right-eye').@y)/2;								
			}
			addChild(_megane);

			_ude.x = _megane.x;
			_ude.y = Number(faces[0].@y)+Number(faces[0].@height)*0.8;
			addChild(_ude);
		}
		/**
		 * 名前空間を削除します
		 * @param	オリジナルストリング(XML形式)
		 * @return	namespace宣言を取り去ったXML
		 */
		private function deleteNameSpace(xmlText : String) : XML {
			// remove the namespaces from the string representation of the XML
			xmlText = xmlText.replace(new RegExp("xmlns[^\"]*\"[^\"]*\"", "gi"), "");
			xmlText = xmlText.replace(new RegExp("xsi[^\"]*\"[^\"]*\"", "gi"), "");

			// set the string rep. of the XML back to real XML
			return new XML(xmlText);
		}

		/**
		 * タイマーハンドラ(カウントダウン)
		 * @param event
		 */
		private function timerHandler(event : TimerEvent) : void {
			_count--;
			_btn.label = String(_count);
			if(_count == 0) {
				_btn.visible = false;
				requestAPIFacialRecognition();				
			}			
		}

		/**
		 * 画像読み込み完了
		 * @param event
		 */
		private function loadCompleteHandler(event : Event) : void {
			var content : Bitmap = LoaderInfo(event.target).content as Bitmap;
			var bmd : BitmapData = content.bitmapData;
			var bmd_ude : BitmapData = new BitmapData(474, 259, true, 0x00FFFFFF);
			var bmd_megane : BitmapData = new BitmapData(127, 45, true, 0x00FFFFFF);
			
			//メガネ設置
			bmd_megane.draw(bmd);
			var bm_megane : Bitmap = new Bitmap(bmd_megane);
			bm_megane.x = -bm_megane.width / 2;
			bm_megane.y = -bm_megane.height / 2;
			_megane = new Sprite();
			_megane.addChild(bm_megane);

			//うで設置
			var mtx : Matrix = new Matrix();
			mtx.translate(0, -45);
			bmd_ude.draw(bmd, mtx, null);
			var bm_ude : Bitmap = new Bitmap(bmd_ude);
			bm_ude.x = -bm_ude.width / 2;
			bm_ude.y =0;
			_ude = new Sprite();
			_ude.addChild(bm_ude);
		}



		/**
		 * webカメラセットのアップ
		 */
		private function setupCamera() : void {
			_camera.setMode(Math.floor(_w / 2), Math.floor(_h / 2), 15);
			_video = new Video(_w, _h);
			_video.attachCamera(_camera);
			addChild(_video);			
		}
	}
}