身近にあるレーザーポインターをマウス代わりにしてみた。

先生とかがよく使う赤いレーザーポインターを疑似マウスにしてみました。
赤い玉を検出してます。
動作ムービーはこちら
http://jp.youtube.com/watch?v=1602j8qvRN0
ゆくゆくはレーザーポインタでなくタッチパネルみたいにしたいです。
あと、自動でキャリブレーションしたり。
こんな感じにセッティング。

プロジェクタ+Webカメラで遊んでます。

目が疲れた(>_<)
将来的にはホワイトボード+カメラで遊んでみたいなぁ。
今回動作ムービーにDVを使ってみたのですが、画質きれいです。
Flash上でもWebカメラと同様に使えるので、高解像度な映像がほしいときはもってこいですね。
ソースはこちら

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()" backgroundGradientAlphas="[1.0, 1.0]" backgroundGradientColors="[#000000, #000000]">
<mx:Script>
<![CDATA[
import mx.containers.Canvas;
//初期化関数
private function init():void{
    setCamera();
}
//カメラの作成
private var camera:Camera;
private var sp5:Canvas = new Canvas();
private function setCamera():void{
    //カメラを反転させておく
    myFlv.scaleX = -1;
    myFlv.x = myFlv.width;
    //カメラの設定
    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 , onActiv);
    } else {
        trace("You need a camera.");
    }
    //オブジェクト配置
    sp5.graphics.beginFill(0x0000ff , 1 );
    sp5.graphics.drawCircle(0,0,20);
    sp5.graphics.endFill();
    this.addChild( sp5 );
}
//カメラアクティブイベント
private function onActiv(e:ActivityEvent):void{
    var timer:Timer = new Timer(0);
    timer.addEventListener( TimerEvent.TIMER , onTimer );
    timer.start();
}
//毎フレーム実行
private function onTimer( e:TimerEvent ):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 );
    //オブジェを移動
    sp5.x = -rect.x * 6.5 + 1300;
    sp5.y = rect.y * 5.0  - 500;
}
]]>
</mx:Script>
<mx:BlurFilter id="myBlur" blurX="2" blurY="2"/>
<mx:VideoDisplay x="0" y="10" width="241" height="260" id="myFlv" visible="false"/>
</mx:Application>