その他
    ホーム 技術発信 DoRuby Webカメラからの入力動画に対してActionScriptで2値化を行う

    Webカメラからの入力動画に対してActionScriptで2値化を行う

    この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

    こんにちは。

    KBMJの佐藤です。

    今回はActionScript3.0を使って、

    Webカメラからの入力動画に対して2値化を行ってみます。

    http://farm3.static.flickr.com/2284/2983782725_3acc71f952.jpg

    ソースコード

    package{
        import flash.display.*;
        import flash.events.*;
        import flash.media.*;
        import flash.system.*;
        import flash.text.*;
        import flash.geom.*;
        import flash.filters.*;
    
        [SWF(width="640", height="480")]
    
        public class Threshold2 extends Sprite {
    	private var video:Video;
    	private var camera:Camera;
    	private var msg:String;
    	public var txtArea:TextField = new TextField();
    	public var bdTmp:BitmapData;
    	public var bmp:Bitmap;
    
    	public function Threshold2()
    	{
    	    stage.scaleMode = StageScaleMode.NO_SCALE;
    	    stage.align = StageAlign.TOP_LEFT;
    
    	    // (1)
    	    camera = Camera.getCamera();
    	    if(camera != null){
    		camera.addEventListener(StatusEvent.STATUS, statusHandler);
    		camera.setMode(640, 480, 15);
    		camera.setMotionLevel(10);
    		camera.setQuality(0, 50);
    
    		// (2)
    		video = new Video(camera.width, camera.height);
    		video.attachCamera(camera);
    
    		addEventListener(Event.ENTER_FRAME, tick);
    	    }else{
    		msg = "使用可能なカメラがありません。";
    		txtArea.text = msg;
    	    }
    
    	    txtArea.autoSize = TextFieldAutoSize.LEFT;
    	    txtArea.text = "Threshold";
    	    txtArea.textColor = 0xffffff;
    	    txtArea.x = 2;
    	    txtArea.y = this.height - txtArea.textHeight - 10;
    	    this.addChild(txtArea);
    
    	    // (3)
    	    bdTmp = new BitmapData(video.width, video.height, false, 0xffffff);
    	    bmp = new Bitmap(bdTmp);
    	    this.addChild(bmp);
    	}
    
    	private function statusHandler(evt:StatusEvent):void{
    	    if(camera.muted){
    		msg = "カメラへのアクセスが拒否されました。";
    		msg += "カメラの映像を表示するにはアクセスを許可してください。";
    		txtArea.text = msg;
    		Security.showSettings(SecurityPanel.PRIVACY);
    	    }else{
    		msg = "使用中のカメラ : " + camera.name + "\n";
    		msg += "幅x高さ : " + camera.width + "x" + camera.width;
    		txtArea.text = msg;
    	    }
    	}
    
    	private function tick(event:Event):void{
    	    if(video == null || camera == null){
    		return;
    	    }
    	    if(camera.muted == true){
    		return;
    	    }
    	    // (4)
    	    var s:BitmapData = new BitmapData(video.width, video.height);
    	    s.draw(video);
    
    	    // (5)
    	    var r:Rectangle = new Rectangle(0, 0, video.width, video.height);
    	    bdTmp.fillRect(r, 0xffffffff);
    
    	    // (6)
    	    var threshold:uint = 0x00800000;
    	    var color:uint = 0x00000000;
    	    var maskColor:uint = 0x00ff0000;
    	    bdTmp.threshold(s, r, new Point(0, 0), "<=", threshold, color, maskColor, false);
    	}
        }
    }
    

    コード解説(1)

    camera = Camera.getCamera();
    

    Webカメラに対して各種操作の行えるCameraオブジェクトを取得します。

    コード解説(2)

    video = new Video(camera.width, camera.height);
    video.attachCamera(camera);
    

    Webカメラからの入力映像をVideoオブジェクトに流し込みます。

    コード解説(3)

    bdTmp = new BitmapData(video.width, video.height, false, 0xffffff);
    bmp = new Bitmap(bdTmp);
    this.addChild(bmp);
    

    画像操作用のバッファとしてBitmapDataオブジェクトを作成し、

    Bitmapオブジェクトに関連づけて、画面に表示します。

    コード解説(4)

    var s:BitmapData = new BitmapData(video.width, video.height);
    s.draw(video);
    

    Webカメラからの入力をBitmapDataオブジェクトにコピーします。

    コード解説(5)

    var r:Rectangle = new Rectangle(0, 0, video.width, video.height);
    bdTmp.fillRect(r, 0xffffffff);
    

    処理対象の矩形をRectangleオブジェクトとして作成し、

    BitmapDataオブジェクトの内容を白でクリアします。

    コード解説(6)

    var threshold:uint = 0x00800000;
    var color:uint = 0x00000000;
    var maskColor:uint = 0x00ff0000;
    bdTmp.threshold(s, r, new Point(0, 0), "<=", threshold, color, maskColor, false);
    

    thresholdメソッドを用いて2値化を行います。

    対象のカラー要素をmaskColor(0x0ff0000)によって抽出し、

    閾値threshold(0x00800000)より大きい場合は

    ピクセル値color(0x00000000)に設定します。

    さいごに

    2値化には様々な方法があるのですが、

    この記事では非常に簡単な方法を用いました。

    ヒストグラムなどを作成した上でそれを元に2値化を行えば

    より良い処理結果を得ることができます。

    次回以降もActionScriptで様々な画像処理を紹介していきたいと思います。

    お楽しみに!

    個人ブログ 拡張現実ライフ