Flash ActionScript2.0 実践講座6:ビデオ映像を扱う

本日の予定

今回の講義は、前回の個人制作の第1回のプレゼン内容を受けて、Flashでライブビデオ映像をキャプチャして、その情報を処理する方法について解説します。作品に映像を用いたインタラクションを考えていて、Flashでシステムを作成したいと考えている場合は、今回の内容が参考になると思います。

さらに次回はJitterやProcessingを用いて同様の処理を行う方法について取り上げていく予定です。

本日のスライド

サンプルファイル

本日のサンプル一覧

※ 今回のサンプルを閲覧するには、FlashPlayer 8以上のプラグインがインストールされた、ビデオカメラがとりつけられたコンピュータが必要です。

  1. シンプルなビデオキャプチャー
    sample01
  2. ビデオ・ミラー
    fig2
  3. ビデオ画像の解像度の変更
    fig3
  4. ピクセル化、その1
    fig4
  5. ピクセル化、その2
    fig5
  6. ビデオ in ビデオ
    fig6
  7. Zbig Rybczynski 「4次元」風エフェクト
    fig7

目次

今日の内容

ビデオカメラからのビデオのキャプチャー

ファイル構成

ビデオオブジェクトの生成

VideoCaptuerクラスのインスタンス化

 import as.VideoCapture;
 var v:VideoCapture = new VideoCapture(this, my_video);

VideoCaptuerクラスの設計

 my_camera = Camera.get();

 my_video.attachVideo(my_camera);

VideoCaptuerクラス

 import as.*;
 class VideoCapture {
	//自身のターゲットパス
	private var target_mc:MovieClip;
	//ビデオオブジェクトの場所
	private var my_video:Video;
	//とりつけられたカメラのオブジェクト
	private var my_camera:Camera;
	/*
	
	コンストラクタ関数
	
	*/
	public function VideoCapture(target:MovieClip, video:Video) {
		//Flashからわたされた引数を変数に格納
		target_mc = target;
		my_video = video;
		//ビデオカメラの接続方法の設定のためのダイアログを表示
		System.showSettings(3);
		//ビデオのキャプチャ開始
		captureVideo();
	}
	/*
	
	パソコンに取り付けられたカメラの映像を取得して、ビデオオブジェクトに貼り付ける
	
	*/
	private function captureVideo():Void {
		//カメラのをmy_cameraに設定
		my_camera = Camera.get();
		//ビデオオブジェクトにカメラの映像を貼り付ける
		my_video.attachVideo(my_camera);
		//ビデオオブジェクトの位置と大きさの補正
		my_video._x = my_video._y=0;
		my_video._width = Stage.width;
		my_video._height = Stage.height;
	}
 }

完成!
fig1

応用1:ビデオミラー

メインクラス「MirrorVideo.as」でやりたいこと

MirrorVideoクラス


 import as.*;
 import flash.display.BitmapData;
 import flash.display.*;
 /*
 ビデオ画面で「合わせ鏡」を作る!
 */
 class MirrorVideo {
	private var target_mc:MovieClip;
	private var my_video:Video;
	private var my_camera:Camera;
	private var fps:Number = 30;
	private var updateTimer:Number;
	private var myBitmapData:BitmapData;
	private var videoData_mc:MovieClip;
	public function MirrorVideo(target:MovieClip, video:Video) {
		target_mc = target;
		my_video = video;
		System.showSettings(3);
		captureVideo();
		createBitmapData();
	}
	/*
	ビデオをキャプチャ
	*/
	private function captureVideo():Void {
		my_camera = Camera.get();
		my_video.attachVideo(my_camera);
		my_video._visible = false;
	}
	/*
	ビットマップデータを貼りつけたムービクリップの生成
	画面の書き換え用のタイマーをスタート
	*/
	private function createBitmapData():Void {
		//新規ビットマップデータの生成
		myBitmapData = new BitmapData(my_camera.width, my_camera.height, false);
		//新規ムービクリップの生成
		videoData_mc = target_mc.createEmptyMovieClip("videoData", target_mc.getNextHighestDepth());
		//先程生成したビットマップデータを貼り付ける
		videoData_mc.attachBitmap(myBitmapData, 1);
		//ビデオの位置とサイズの補正
		videoData_mc._x = videoData_mc._y=0;
		videoData_mc._width = Stage.width;
		videoData_mc._height = Stage.height;
		//画面のアップデート用のタイマーをスタート
		clearInterval(updateTimer);
		updateTimer = setInterval(this, "update", 1000/fps);
	}
	/*
	画面の更新
	*/
	private function update():Void {
		var pc:Number;
		//ビットマップデータにビデオ画像を読み込む
		myBitmapData.draw(my_video);
		//ビデオ画像の行の数(幅)の半分だけ実行
		for (var col:Number = 0; col<myBitmapData.width/2; col++) {
			//ビデオ画像の列の数(高さ)だけ実行
			for (var row:Number = 0; row<myBitmapData.height; row++) {
				//ピクセルの色情報を取り出し
				pc = myBitmapData.getPixel(col, row);
				//左右を反転して貼り付ける
				myBitmapData.setPixel(myBitmapData.width-col, row, pc);
			}
		}
	}
 }

完成!
fig2

応用2:ビデオ映像の解像度を変更

ResizeVideoクラス

 import as.*;
 import flash.display.*;
 import flash.geom.*;
 /*
 ビデオ映像の解像度を変更→モザイク状に
 */
 class ResizeVideo {
	private var target_mc:MovieClip;
	private var my_video:Video;
	private var my_camera:Camera;
	private var fps:Number = 30;
	private var updateTimer:Number;
	private var myBitmapData:BitmapData;
	private var transformBitmap:BitmapData;
	private var videoData_mc:MovieClip;
	private var transform_mc:MovieClip;
	private var rows:Number;
	private var cols:Number;
	private var cell_width:Number;
	private var cell_height:Number;
	private var transform_matrix:Matrix;
	private var cellAarry = Array();
	/*
	コンストラクタ
	*/
	public function ResizeVideo(target:MovieClip, video:Video) {
		target_mc = target;
		my_video = video;
		cols = 20;
		rows = 15;
		cell_width = Stage.width/cols;
		cell_height = Stage.height/rows;
		System.showSettings(3);
		captureVideo();
		createBitmapData();
		transformVideo();
	}
	/*
	ビデオのキャプチャ
	*/
	private function captureVideo():Void {
		my_camera = Camera.get();
		my_video.attachVideo(my_camera);
		my_video._visible = false;
	}
	/*
	ビットマップデータを貼りつけたムービクリップの生成
	*/
	private function createBitmapData():Void {
		myBitmapData = new BitmapData(my_camera.width, my_camera.height, false);
		myBitmapData.draw(my_video);
		videoData_mc = target_mc.createEmptyMovieClip("videoData", target_mc.getNextHighestDepth());
		videoData_mc.attachBitmap(myBitmapData, 1);
	}
	/*
	ビデオの解像度を変更
	新規に、ビットマップデータを貼りつけたムービクリップの生成
	画面の書き換え用のタイマーをスタート
	*/
	private function transformVideo():Void {
		//ビットマップデータを貼りつけたムービクリップの幅と高さを指定のセルの数まで縮小
		videoData_mc._width = cols;
		videoData_mc._height = rows;
		//ムービークリップのデータをマトリクスに変換
		transform_matrix = videoData_mc.transform.matrix;
		//解像度を変換後のデータ表示用ビットマップを生成
		transformBitmap = new BitmapData(cols, rows, false);
		//解像度を変換後のデータ表示用ムービクリップを生成
		transform_mc = target_mc.createEmptyMovieClip("transform_mc", target_mc.getNextHighestDepth());
		transform_mc.attachBitmap(transformBitmap, 1);
		transform_mc._width = Stage.width;
		transform_mc._height = Stage.height;
		//画面のアップデート用のタイマーをスタート
		clearInterval(updateTimer);
		updateTimer = setInterval(this, "update", 1000/fps);
	}
	/*
	画面の更新
	*/
	private function update():Void {
		//解像度を変更したマトリクスに合致するようにビデオのデータを読み込み
		transformBitmap.draw(my_video, transform_matrix);
	}
 }

完成!
fig3

応用3:ビデオ映像を点描で表現

PixelateVideoクラス

 import as.*;
 import flash.display.*;
 import flash.geom.*;
 /*
 ビデオ映像を元にして、ピクセルを点描する
 */
 class PixelateVideo {
	private var target_mc:MovieClip;
	private var my_video:Video;
	private var my_camera:Camera;
	private var fps:Number = 10;
	private var updateTimer:Number;
	private var myBitmapData:BitmapData;
	private var transformBitmap:BitmapData;
	private var videoData_mc:MovieClip;
	private var rows:Number;
	private var cols:Number;
	private var cell_width:Number;
	private var cell_height:Number;
	private var transform_matrix:Matrix;
	private var cellAarry = Array();
	/*
	コンストラクタ
	*/
	public function PixelateVideo(target:MovieClip, video:Video) {
		target_mc = target;
		my_video = video;
		cols = 30;
		rows = 20;
		cell_width = Stage.width/cols;
		cell_height = Stage.height/rows;
		System.showSettings(3);
		captureVideo();
		createBitmapData();
		transformVideo();
		createCells();
	}
	/*
	ビデオのキャプチャ
	*/
	private function captureVideo():Void {
		my_camera = Camera.get();
		my_video.attachVideo(my_camera);
		my_video._visible = false;
	}
	/*
	ビットマップデータを貼りつけたムービクリップの生成
	*/
	private function createBitmapData():Void {
		myBitmapData = new BitmapData(my_camera.width, my_camera.height, false);
		myBitmapData.draw(my_video);
		videoData_mc = target_mc.createEmptyMovieClip("videoData", target_mc.getNextHighestDepth());
		videoData_mc.attachBitmap(myBitmapData, 1);
	}
	/*
	ビデオの解像度を変更
	新規に、ビットマップデータを貼りつけたムービクリップの生成
	*/
	private function transformVideo():Void {
		videoData_mc._width = cols;
		videoData_mc._height = rows;
		transform_matrix = videoData_mc.transform.matrix;
		transformBitmap = new BitmapData(cols, rows, false);
		transformBitmap.draw(my_video, transform_matrix);
	}
	/*
	ピクセル情報を表現するムービクリップをタイル状に敷き詰める
	画面の書き換え用のタイマーをスタート
	*/
	private function createCells():Void {
		//変換後のビットマップの縦横のピクセル数だけ、ムービクリップを生成していく
		for (var c:Number = 0; c<cols; ++c) {
			for (var r:Number = 0; r<rows; ++r) {
				var cell_mc:MovieClip = target_mc.createEmptyMovieClip("cell_mc", target_mc.getNextHighestDepth());
				//対応するビットマップデータのピクセルの位置にムービクリップを移動
				cell_mc._x = c*cell_width+cell_width*0.5;
				cell_mc._y = r*cell_height+cell_height*0.5;
				//生成したムービクリップを配列"cellAarry"に格納
				cellAarry.push(cell_mc);
			}
		}
		clearInterval(updateTimer);
		updateTimer = setInterval(this, "update", 1000/fps);
	}
	/*
	画面の更新
	*/
	private function update():Void {
		var pixelColor:Number;
		var cellRed:Number, cellGreen:Number, cellBlue:Number, bright:Number;
		transformBitmap.draw(my_video, transform_matrix);
		var count = 0;
		//変換後のビットマップの縦横のピクセル数だけ繰り返す
		for (var c:Number = 0; c<cols; c++) {
			for (var r:Number = 0; r<rows; r++) {
				//ビットマップデータのピクセル値を取り出す
				pixelColor = transformBitmap.getPixel(c, r);
				//取得した16進数の色情報を10進数のRGB分解した色情報に変換する
				cellRed = pixelColor >> 16 & 0xFF;
				cellGreen = pixelColor >> 8 & 0xFF;
				cellBlue = pixelColor & 0xFF;
				//ピクセルの明度を算出(0〜100にノーマライズ)
				bright = Math.max(Math.max(cellRed, cellGreen), cellBlue)/255*100;
				//配列"cellAarry"に格納したムービクリップをとりだす
				var cell_mc:MovieClip = cellAarry[count];
				//ムービクリップの内容を消去
				cell_mc.clear();
				//指定の場所に色の付いた点を描く
				//(終端がラウンドした太い線を1pxだけ描いて円にする)
				cell_mc.lineStyle(cell_height, pixelColor, 100, false, "normal", "round");
				cell_mc.lineTo(0, 1);
				//算出した明度の情報をもとに円の大きさを決定
				cell_mc._xscale = cell_mc._yscale=bright;
				count++;
			}
		}
	}
 }

完成!
fig4

さらに応用:文字を貼りつけたムービクリップで表現
fig5

応用4:ビデオ in ビデオ

つくり方

VideoInVideoクラス

 import as.*;
 import flash.display.*;
 import flash.geom.*;
 class VideoInVideo {
	private var target_mc:MovieClip;
	private var my_video:Video;
	private var my_camera:Camera;
	private var fps:Number = 15;
	private var updateTimer:Number;
	private var myBitmapData:BitmapData;
	private var transformBitmap:BitmapData;
	private var videoData_mc:MovieClip;
	private var rows:Number;
	private var cols:Number;
	private var cell_width:Number;
	private var cell_height:Number;
	private var transform_matrix:Matrix;
	private var cellAarry = Array();
	public function VideoInVideo(target:MovieClip, video:Video) {
		target_mc = target;
		my_video = video;
		cols = 20;
		rows = 20;
		cell_width = Stage.width/cols;
		cell_height = Stage.height/rows;
		System.showSettings(3);
		captureVideo();
		createBitmapData();
		transformVideo();
		createCells();
	}
	/*
	ビデオのキャプチャ
	*/
	private function captureVideo():Void {
		my_camera = Camera.get();
		my_video.attachVideo(my_camera);
		my_video._visible = false;
	}
	/*
	ビットマップデータを貼りつけたムービクリップの生成
	*/
	private function createBitmapData():Void {
		myBitmapData = new BitmapData(my_camera.width, my_camera.height, false);
		myBitmapData.draw(my_video);
		videoData_mc = target_mc.createEmptyMovieClip("videoData", target_mc.getNextHighestDepth());
		videoData_mc.attachBitmap(myBitmapData, 1);
	}
	/*
	ビデオの解像度を変更
	新規に、ビットマップデータを貼りつけたムービクリップの生成
	*/
	private function transformVideo():Void {
		videoData_mc = target_mc.createEmptyMovieClip("videoData", target_mc.getNextHighestDepth());
		videoData_mc.attachBitmap(myBitmapData, 1);
		videoData_mc._visible = false;
		videoData_mc._width = cols;
		videoData_mc._height = rows;
		transform_matrix = videoData_mc.transform.matrix;
		transformBitmap = new BitmapData(cols, rows, false);
		transformBitmap.draw(my_video, transform_matrix);
	}
	/*
	ピクセル情報を表現するムービクリップをタイル状に敷き詰める
	画面の書き換え用のタイマーをスタート
	*/
	private function createCells():Void {
		for (var c:Number = 0; c<cols; ++c) {
			for (var r:Number = 0; r<rows; ++r) {
				var cell_mc:MovieClip = target_mc.createEmptyMovieClip("cell_mc", target_mc.getNextHighestDepth());
				cell_mc._x = c*cell_width;
				cell_mc._y = r*cell_height;
				//ムービクリップの内部に、
				//解像度を調整した後のビデオ画像のビットマップデータを貼り付けている
				cell_mc.attachBitmap(transformBitmap, 1);
				cell_mc._width = cell_width;
				cell_mc._height = cell_height;
				cellAarry.push(cell_mc);
			}
		}
		clearInterval(updateTimer);
		updateTimer = setInterval(this, "update", 1000/fps);
	}
	/*
	画面の更新
	*/
	private function update():Void {
		var pixelColor:Number;
		var cellRed:Number, cellGreen:Number, cellBlue:Number, bright:Number;
		transformBitmap.draw(my_video, transform_matrix);
		var count = 0;
		for (var c:Number = 0; c<cols; c++) {
			for (var r:Number = 0; r<rows; r++) {
				pixelColor = transformBitmap.getPixel(c, r);
				cellRed = pixelColor >> 16 & 0xFF;
				cellGreen = pixelColor >> 8 & 0xFF;
				cellBlue = pixelColor & 0xFF;
				bright = Math.max(Math.max(cellRed, cellGreen), cellBlue)/255*100;
				var cell_mc:MovieClip = cellAarry[count];
				//ムービクリップの透明度を明度に対応させる
				cell_mc._alpha = bright;
				//ムービクリップの色を取得したピクセル値にあわせて変更
				var trans:Transform = new Transform(cell_mc);
				var colorTrans:ColorTransform = new ColorTransform(1, 1, 1, 1, cellRed, cellGreen, cellBlue, 0);
				trans.colorTransform = colorTrans;
				count++;
			}
		}
	}
 }

完成!
fig6

応用5:リプチンスキー・エフェクト

Rybczynskiクラス

 import as.*;
 import flash.display.*;

 import flash.geom.*;
 class Rybczynski {
	private var target_mc:MovieClip;
	private var my_video:Video;
	private var my_camera:Camera;
	private var fps:Number = 30;

	private var updateTimer:Number;
	private var myBitmapData:BitmapData;
	private var transformBitmap:BitmapData;
	private var videoData_mc:MovieClip;
	private var transform_mc:MovieClip;
	private var rows:Number;

	private var cols:Number;
	private var cell_width:Number;
	private var cell_height:Number;
	private var bitmapAarry = Array();
	private var transform_matrix:Matrix;
	public function Rybczynski(target:MovieClip, video:Video) {

		target_mc = target;
		my_video = video;
		cols = 60;
		rows = 60;
		cell_width = Stage.width/cols;
		cell_height = Stage.height/rows;

		System.showSettings(3);
		_quality = "LOW";
		captureVideo();
		transformVideo();
	}

	private function captureVideo():Void {
		my_camera = Camera.get();
		my_video.attachVideo(my_camera);
		my_video._visible = false;
		myBitmapData = new BitmapData(my_camera.width, my_camera.height, false);
		myBitmapData.draw(my_video);

	}
	private function transformVideo():Void {
		videoData_mc = target_mc.createEmptyMovieClip("videoData", target_mc.getNextHighestDepth());
		videoData_mc.attachBitmap(myBitmapData, 1);
		videoData_mc._visible = false;

		videoData_mc._width = cols;
		videoData_mc._height = rows;
		transform_matrix = videoData_mc.transform.matrix;
		transformBitmap = new BitmapData(cols, rows, false);
		transform_mc = target_mc.createEmptyMovieClip("transform_mc", target_mc.getNextHighestDepth());

		transform_mc.attachBitmap(transformBitmap, 1);
		transform_mc._width = Stage.width;
		transform_mc._height = Stage.height;
		clearInterval(updateTimer);
		updateTimer = setInterval(this, "update", 1000/fps);

	}
	private function update():Void {
		var pixelColor:Number;
		var cellRed:Number, cellGreen:Number, cellBlue:Number, bright:Number;
		var tmpBitmap:BitmapData = new BitmapData(cols, rows, false);
		tmpBitmap.draw(my_video, transform_matrix);

		bitmapAarry.push(tmpBitmap);
		if (bitmapAarry.length>rows) {
			bitmapAarry.shift();
		}
		for (var c:Number = 0; c<cols; c++) {

			for (var r:Number = 0; r<rows; r++) {
				pixelColor = bitmapAarry[r].getPixel(c, r);
				transformBitmap.setPixel(c, r, pixelColor);
			}
		}
	}

 }

完成!
fig7

Comments

コメントはありません

Add Comment

このアイテムは閉鎖されました。このアイテムへのコメントの追加、投票はできません。

トップページに戻る