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/8Twf
 */

// forked from minon's くまの人メイカー(全自動版)
// forked from fumix's あの人メイカー(全自動版)
// 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 _kuma : 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://labs.minomix.net/kuma/kuma.png";
            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();
            */
                _btn.visible = false;
                requestAPIFacialRecognition();                
        }

        /**
         * 顔認識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 kuma_width : Number = 53;//くま画像から左右の眼の幅。

            //認識した顔の左右の眼のx,y
            var faceLeftEye_x : Number = faces[0].elements('left-eye').@x;
            var faceLeftEye_y : Number = faces[0].elements('left-eye').@y;
            var faceRightEye_x : Number = faces[0].elements('right-eye').@x;
            var faceRightEye_y : Number = faces[0].elements('right-eye').@y;
            
            //左右の眼の座標から幅と高さ
            var faceEyeWidth : Number = faceLeftEye_x - faceRightEye_x;
            var faceEyeHeight : Number = faceLeftEye_y - faceRightEye_y;
            //左右の眼の距離
            var faceEyeDistance : Number = Math.sqrt(faceEyeWidth * faceEyeWidth + faceEyeHeight * faceEyeHeight);
            //拡大率
            var scale : Number = faceEyeDistance / kuma_width;
            
            //回転角度
            var rot : Number = Math.atan2(faceEyeHeight, faceEyeWidth);
            
            _kuma.scaleX = _kuma.scaleY = scale;
            _kuma.rotation = rot * 180 / Math.PI;

            _kuma.x = faceRightEye_x + faceEyeWidth / 2;

            if(faceRightEye_y > faceLeftEye_y) {
                _kuma.y = faceLeftEye_y - faceEyeHeight / 2;
            } else {
                _kuma.y = faceRightEye_y + faceEyeHeight / 2;
            }
            addChild(_kuma);

            
        }
        /**
         * 名前空間を削除します
         * @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_kuma : BitmapData = new BitmapData(320, 320, true, 0x00FFFFFF);
            
            //くま
            bmd_kuma.draw(bmd);
            var bm_kuma : Bitmap = new Bitmap(bmd_kuma);
            bm_kuma.x = -160;
            bm_kuma.y = -189;
            _kuma = new Sprite();
            _kuma.addChild(bm_kuma);
        }



        /**
         * 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);            
        }
    }
}