Webカメラを2つ使ってアナグリフ撮影

by Hakuhin
♥8 | Line 312 | Modified 2011-12-15 08:53:40 | MIT License
play

Related images

ActionScript3 source code

/**
 * Copyright Hakuhin ( http://wonderfl.net/user/Hakuhin )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/rd3y
 */

<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" applicationComplete="init();"><mx:Script><![CDATA[public function init():void{
// -------------------------------------------------
//
// Webカメラを2つ使ってアナグリフ撮影
//
//
// Webカメラ2つを、画像のように平行に並べて撮影します。
// 赤青メガネをかけて画面を見ながらカメラの向きを調節すると
// ピントが合わせやすいようです。
//
// Webカメラが2つ必要になりますが
// 持ってない方が多いと思いますので
// 撮影風景を動画にしてアップロードしてみました。
// 
// http://www.youtube.com/watch?v=hsQopz_AOMA
//
// -------------------------------------------------



// -------------------------------------------------
// インポート
// -------------------------------------------------
import mx.core.*;
import mx.containers.*;
import mx.controls.*;
import mx.events.*;



// -------------------------------------------------
// Flash 設定
// -------------------------------------------------

// フレームレート
stage.frameRate = 60;

// 100% 表示
stage.scaleMode = StageScaleMode.NO_SCALE;

// 左上
stage.align = StageAlign.TOP_LEFT;
stage.align = "TL";



// -------------------------------------------------
// Flex 設定
// -------------------------------------------------

// パディングなし
setStyle("paddingTop",0);
setStyle("paddingBottom",0);
setStyle("paddingLeft",0);
setStyle("paddingRight",0);

// 背景透過
setStyle("backgroundAlpha",0);

// 左上
setStyle("horizontalAlign","left");
setStyle("verticalAlign","top");

// キャンバス作成
var canvas:Canvas = new Canvas();
addChild(canvas);



// -------------------------------------------------
// Flash オブジェクト作成
// -------------------------------------------------

// 黒壁紙
var shape:Shape = new Shape();
stage.addChildAt(shape,0);
var g : Graphics = shape.graphics;
g.beginFill (0x000000, 1.0);
g.drawRect  ( 0, 0 , 100 , 100);
g.endFill();

// 左カメラ
var video_l : Video = new Video();
video_l.blendMode = BlendMode.ADD;
stage.addChild(video_l);

// 右カメラ
var video_r : Video = new Video();
video_r.blendMode = BlendMode.ADD;
stage.addChild(video_r);

var camera_l : Camera = null;
var camera_r : Camera = null;



// -------------------------------------------------
// Flex コンポーネント作成
// -------------------------------------------------
var text : Text;

// 幅
text = new Text();
text.text = "幅";
text.x = 10;
text.y = 5;
text.width = 30;
text.height = 22;
canvas.addChild(text);

var stepper_w : NumericStepper = new NumericStepper();
stepper_w.x = 40;
stepper_w.y = 5;
stepper_w.value = 640;
stepper_w.minimum = 1;
stepper_w.maximum = 4096;
stepper_w.width = 60;
stepper_w.height = 22;
canvas.addChild(stepper_w);
stepper_w.addEventListener(Event.CHANGE,VideoCaptureUpdate);


// 高さ
text = new Text();
text.text = "高さ";
text.x = 10;
text.y = 30;
text.width = 40;
text.height = 22;
canvas.addChild(text);

var stepper_h : NumericStepper = new NumericStepper();
stepper_h.x = 40;
stepper_h.y = 30;
stepper_h.value = 480;
stepper_h.minimum = 1;
stepper_h.maximum = 4096;
stepper_h.width = 60;
stepper_h.height = 22;
canvas.addChild(stepper_h);
stepper_h.addEventListener(Event.CHANGE,VideoCaptureUpdate);


// FPS
text = new Text();
text.text = "FPS";
text.x = 110;
text.y = 5;
text.width = 40;
text.height = 22;
canvas.addChild(text);

var stepper_f : NumericStepper = new NumericStepper();
stepper_f.x = 150;
stepper_f.y = 5;
stepper_f.value = 60;
stepper_f.minimum = 12;
stepper_f.maximum = 120;
stepper_f.width = 60;
stepper_f.height = 22;
canvas.addChild(stepper_f);
stepper_f.addEventListener(Event.CHANGE,VideoCaptureUpdate);


// 色乗算
text = new Text();
text.text = "色乗算";
text.x = 220;
text.y = 5;
text.width = 40;
text.height = 22;
canvas.addChild(text);

var stepper_m : NumericStepper = new NumericStepper();
stepper_m.x = 265;
stepper_m.y = 5;
stepper_m.value = 1.0;
stepper_m.stepSize = 0.01;
stepper_m.minimum = -2.0;
stepper_m.maximum = 2.0;
stepper_m.width = 60;
stepper_m.height = 22;
canvas.addChild(stepper_m);
stepper_m.addEventListener(Event.CHANGE,VideoColorUpdate);


// 色加算
text = new Text();
text.text = "色加算";
text.x = 220;
text.y = 30;
text.width = 40;
text.height = 22;
canvas.addChild(text);

var stepper_a : NumericStepper = new NumericStepper();
stepper_a.x = 265;
stepper_a.y = 30;
stepper_a.value = 0;
stepper_a.minimum = -255;
stepper_a.maximum = 255;
stepper_a.width = 60;
stepper_a.height = 22;
canvas.addChild(stepper_a);
stepper_a.addEventListener(Event.CHANGE,VideoColorUpdate);


// 下側メニュー
var result:Canvas = new Canvas();
result.x = 0;
result.y = 300;
canvas.addChild(result);

// 左カメラの設定
var text_camera_l:Text = new Text();
text_camera_l.text = "左カメラの設定";
text_camera_l.x = 10;
text_camera_l.y = 5;
text_camera_l.width = 100;
text_camera_l.height = 22;
result.addChild(text_camera_l);


// 左カメラ反転
var check_reverse_l:CheckBox = new CheckBox();
check_reverse_l.label = "反転";
check_reverse_l.x = 150;
check_reverse_l.y = 5;
check_reverse_l.width = 60;
check_reverse_l.height = 22;
result.addChild(check_reverse_l);
check_reverse_l.addEventListener(Event.CHANGE,VideoSizeUpdate);


// 左カメラの色
var text_color_l:Text = new Text();
text_color_l.text = "色";
text_color_l.x = 10;
text_color_l.y = 35;
text_color_l.width = 70;
text_color_l.height = 22;
result.addChild(text_color_l);

var combo_color_l:ComboBox = new ComboBox();
combo_color_l.x = 80;
combo_color_l.y = 35;
combo_color_l.height = 22;
ComboboxSetColorTypeProvider(combo_color_l);
result.addChild(combo_color_l);
combo_color_l.addEventListener(Event.CHANGE,VideoColorUpdate);


// 左カメラのデバイス名
var text_device_l:Text = new Text();
text_device_l.text = "デバイス名";
text_device_l.x = 10;
text_device_l.y = 75;
text_device_l.width = 70;
text_device_l.height = 22;
result.addChild(text_device_l);

var combo_device_l:ComboBox = new ComboBox();
combo_device_l.x = 80;
combo_device_l.y = 75;
combo_device_l.height = 22;
result.addChild(combo_device_l);
combo_device_l.addEventListener(Event.CHANGE,VideoDeviceUpdate);


// 右カメラの設定
var text_camera_r:Text = new Text();
text_camera_r.text = "右カメラの設定";
text_camera_r.y = 5;
text_camera_r.width = 100;
text_camera_r.height = 22;
result.addChild(text_camera_r);


// 右カメラ反転
var check_reverse_r:CheckBox = new CheckBox();
check_reverse_r.label = "反転";
check_reverse_r.y = 5;
check_reverse_r.width = 60;
check_reverse_r.height = 22;
result.addChild(check_reverse_r);
check_reverse_r.addEventListener(Event.CHANGE,VideoSizeUpdate);


// 右カメラの色
var text_color_r:Text = new Text();
text_color_r.text = "色";
text_color_r.y = 35;
text_color_r.width = 70;
text_color_r.height = 22;
result.addChild(text_color_r);

var combo_color_r:ComboBox = new ComboBox();
combo_color_r.y = 35;
combo_color_r.height = 22;
ComboboxSetColorTypeProvider(combo_color_r);
combo_color_r.selectedIndex = 3;
result.addChild(combo_color_r);
combo_color_r.addEventListener(Event.CHANGE,VideoColorUpdate);


// 右カメラのデバイス名
var text_device_r:Text = new Text();
text_device_r.text = "デバイス名";
text_device_r.y = 75;
text_device_r.width = 70;
text_device_r.height = 22;
result.addChild(text_device_r);

var combo_device_r:ComboBox = new ComboBox();
combo_device_r.y = 75;
combo_device_r.height = 22;
result.addChild(combo_device_r);
combo_device_r.addEventListener(Event.CHANGE,VideoDeviceUpdate);



// -------------------------------------------------
// リサイズ時にフィット
// -------------------------------------------------
stage.addEventListener(Event.RESIZE,ResizeFunc);
function ResizeFunc(e:Event):void{
    var w:uint = stage.stageWidth;
    var h:uint = stage.stageHeight;

    // 下側メニュー
    result.y = h - 110;

    // 左カメラの設定
    combo_color_l.width = w / 2 - 100;
    combo_device_l.width = w / 2 - 100;
    check_reverse_r.x = w / 2 + 150;

    // 右カメラの設定
    text_camera_r.x = w / 2 + 10;
    text_color_r.x = w / 2 + 10;
    combo_color_r.x = w / 2 + 80;
    combo_color_r.width = w / 2 - 100;
    text_device_r.x = w / 2 + 10;
    combo_device_r.x = w / 2 + 80;
    combo_device_r.width = w / 2 - 100;
    
    // 背景
    shape.x = 5;
    shape.width = w - 10;
    shape.y = 60;
    shape.height = h - 170;
    
    // ビデオサイズ
    VideoSizeUpdate(null);
}
ResizeFunc(null);



// -------------------------------------------------
// 警告
// -------------------------------------------------
if(Camera.names.length < 2){
    Alert.show("動作するには、\n2つのWebカメラが必要となります。","エラー");
}



// -------------------------------------------------
// カメラデバイス名列挙
// -------------------------------------------------
var i:int;
var name:Array = Camera.names;
var num:int = name.length;
var data:Array = new Array();
for(i=0;i<num;i++){
    data[i] = {
        label: "No." + i + ":" + name[i],
        data:i
    };
}
combo_device_l.dataProvider = data;
combo_device_l.selectedIndex = 0;
combo_device_r.dataProvider = data;
combo_device_r.selectedIndex = 1;



// -------------------------------------------------
// カメラデバイス更新
// -------------------------------------------------
function VideoDeviceUpdate(e:Event):void{
    camera_l = Camera.getCamera(combo_device_l.selectedItem.data + "");
    camera_r = Camera.getCamera(combo_device_r.selectedItem.data + "");
    video_l.attachCamera(camera_l);
    video_r.attachCamera(camera_r);
}
VideoDeviceUpdate(null);



// -------------------------------------------------
// ビデオサイズ更新
// -------------------------------------------------
function VideoSizeUpdate(e:Event):void{
    var w:uint = stage.stageWidth;
    var h:uint = stage.stageHeight;

    video_r.width = video_l.width = w - 10;
    video_r.y = video_l.y = 60;
    video_r.height = video_l.height = h - 170;

    if(check_reverse_l.selected){
        video_l.x = w - 10;
        video_l.scaleX *= -1.0;
    }else{
        video_l.x = 5;
    }
    if(check_reverse_r.selected){
        video_r.x = w - 10;
        video_r.scaleX *= -1.0;
    }else{
        video_r.x = 5;
    }
}



// -------------------------------------------------
// ビデオキャプチャ更新
// -------------------------------------------------
function VideoCaptureUpdate(e:Event):void{
    if(camera_l)    camera_l.setMode(stepper_w.value,stepper_h.value,stepper_f.value,true);
    if(camera_r)    camera_r.setMode(stepper_w.value,stepper_h.value,stepper_f.value,true);
}
VideoCaptureUpdate(null);



// -------------------------------------------------
// ビデオカラー更新
// -------------------------------------------------
function VideoColorUpdate(e:Event):void{
    video_l.filters = [new ColorMatrixFilter(FilterGetMatrix(combo_color_l.selectedItem.data,combo_color_r.selectedItem.data))];
    video_r.filters = [new ColorMatrixFilter(FilterGetMatrix(combo_color_r.selectedItem.data,combo_color_l.selectedItem.data))];
}
VideoColorUpdate(null);



// -------------------------------------------------
// カラーマトリックスフィルタ用配列取得
// -------------------------------------------------
function FilterGetMatrix(type_my:Number,type_target:Number):Array{
    
    var r : Number = 0;
    var g : Number = 0;
    var b : Number = 0;
    
    // 使用可能カラー
    switch(type_target){
    case 0:    g++;    b++;    break;
    case 1:    r++;    b++;    break;
    case 2:    r++;    g++;    break;
    case 3:    r++;    break;
    case 4:    g++;    break;
    case 5:    b++;    break;
    };

    // 乗算と加算の調整
    var m : Number = stepper_m.value;
    var a : Number = stepper_a.value;
    r *= m;
    g *= m;
    b *= m;

    return [
        r,0,0,0,a,
        0,g,0,0,a,
        0,0,b,0,a,
        0,0,0,1,0
    ];
}



// -------------------------------------------------
// コンボボックスにカラーセット
// -------------------------------------------------
function ComboboxSetColorTypeProvider(combo:ComboBox):void{
    combo.dataProvider = [
        {label:"赤",data:0},
        {label:"緑",data:1},
        {label:"青",data:2},
        {label:"水(シアン)",data:3},
        {label:"紫(マゼンダ)",data:4},
        {label:"黄(イエロー)",data:5}
    ];
}








}]]></mx:Script></mx:Application>