有機ELよりも薄い紙TV

Flex有機ELの薄さなんて目じゃない厚さが紙のTVを作成しました。
動作ムービーはこちら
http://jp.youtube.com/watch?v=oczVc3YbN-w

赤色抽出+ラベリング+自由変換でできます。
赤色抽出はこちら
http://www.hatayan.org/weblog/archives/2005/11/30/123132.php
ラベリングはこちら
http://d.hatena.ne.jp/nitoyon/20071003/as3_labeling
自由変形はこちら
http://www.rubenswieringa.com/code/as3/flex/DistortImage/
を参考にしました。
TVとして認識させる方法
こんな感じに紙に4点赤い印をつけます。

これだけでOK
まだまだいろいろと課題があって、肌色も抽出されてしまう場合があるのと、ポイントが交差してしまう場合があるのでその処理が必要です。
ソースはこちら
途中冗長的な部分があります(汗

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()">
<mx:Script>
<![CDATA[
import org.flashsandy.display.*;
//カメラの作成
private var camera:Camera;
private function init():void{
    //カメラの設定
    camera = Camera.getCamera();
    if (camera != null) {
        camera.setQuality(0, 95);
        camera.setMode(640 , 480 , 60 , true );
        camera.setMotionLevel(0);
        myFlv.attachCamera( camera );
        camera.addEventListener(ActivityEvent.ACTIVITY , onActive);
    } else {
        trace("You need a camera.");
    }
    myFlv2.width  = myFlv.width;
    myFlv2.height = myFlv.height;
    myFlv2.play();
}
//カメラアクティブイベント
private function onActive( e:ActivityEvent ):void{
    this.addEventListener( Event.ENTER_FRAME , getPoint );
}
//ポイントの取得と画像の変換
private var distortion:DistortImage = new DistortImage(500, 375, 3, 3);
private function getPoint(e:Event):void{
    //赤色抽出
    //http://www.hatayan.org/weblog/archives/2005/11/30/123132.phpがオススメ
    var my_bd:BitmapData    = new BitmapData( myFlv.width , myFlv.height );
    var green_bd:BitmapData = new BitmapData( myFlv.width , myFlv.height );
    var blue_bd:BitmapData  = new BitmapData( myFlv.width , myFlv.height );
    my_bd.draw(myFlv);
    green_bd.copyChannel( my_bd , my_bd.rect , new Point() , 2 , 1 );
    blue_bd.copyChannel(  my_bd , my_bd.rect , new Point() , 3 , 1 );
    blue_bd.draw( green_bd, new Matrix(), new ColorTransform(), 'lighten');
    my_bd.draw(   blue_bd , new Matrix(), new ColorTransform(), 'subtract');
    my_bd.applyFilter( my_bd , my_bd.rect , new Point() , myBlur );
    my_bd.threshold( my_bd , my_bd.rect , new Point() , '>' , 0xff500000 , 0xffffffff );
    my_bd.threshold( my_bd , my_bd.rect , new Point() , '!=', 0xffffffff , 0xff000000 );
    //赤色があるところを検出
    var rect:Rectangle =my_bd.getColorBoundsRect(0xffffffff , 0xffffffff , true );
    //ラベリング
    var label:Array = new Array();
    var lno:uint = 0xffffff00;
    var i:int = 0;
    for (var x:int = 0; x < my_bd.width; x++) {
        for (var y:int = 0; y < my_bd.height; y++) {
            if (my_bd.getPixel(x, y) == 0xFFFFFF) { // 白色の場合
                lno += 30;
                label[i] = lno;
                i++;
                my_bd.floodFill(x , y, lno );
            }
        }
    }
    var pointNew:Array = new Array();
    //ポイントを線でつなぐ //この辺は上のfor文とあわせてもOKだと思う。
    myCanvas.graphics.clear();
    //グリッドの表示//myCanvas.graphics.lineStyle( 1 , 0xffff0000 , 1.0 , false );
       var rect:Rectangle =  my_bd.getColorBoundsRect( 0xffffffff ,     label[0] , true );
     myCanvas.graphics.moveTo( rect.x + rect.width/2 , rect.y + rect.height/2 );
    for( i = 0 ; i < label.length ; i++ ){
        rect = my_bd.getColorBoundsRect( 0xffffffff ,     label[i] , true );
        pointNew[i] = new Point( rect.x + 5 , rect.y + 5);
        myCanvas.graphics.lineTo( rect.x + rect.width/2 , rect.y + rect.height/2 );
    }
    rect = my_bd.getColorBoundsRect( 0xffffffff ,     label[0] , true );
    myCanvas.graphics.lineTo( rect.x + rect.width/2 , rect.y + rect.height/2 );
    myCanvas.graphics.endFill();
    myImage.source = new Bitmap( my_bd );
    var bd:BitmapData = new BitmapData( myFlv.width , myFlv.height );
    bd.draw( myFlv2 );
    //自由変形
    if( pointNew.length == 4 ){
        distortion.setTransform( myCanvas.graphics , bd , pointNew[1] , pointNew[3] , pointNew[2] , pointNew[0] );
     }
}
]]>
</mx:Script>
<mx:BlurFilter id="myBlur" blurX="3" blurY="3"/>
<mx:VideoDisplay x="10" y="10" width="640" height="480" id="myFlv"/>
<mx:Image x="694" y="10" width="258" height="216" id="myImage"/>
<mx:Canvas x="10" y="10" width="676" height="576" id="myCanvas"/>
<mx:VideoDisplay x="675" y="331" source="test.flv" autoPlay="true" id="myFlv2" visible="false" complete="{myFlv2.play();}" />
</mx:Application>

作ってて一人ですごい感激してしまった(>_<)