AS3でWebカメラの映像をJPEGで保存

4月 25th, 2008 admin

Webカメラ楽しいー!とかって5年遅れぐらいですかね。

デモ

※白黒画像ですがカメラを許可して画面をクリックすると画像が保存されます。
動作サンプルはこちら

成果物

ステージをクリックするとWebカメラに表示されている内容が白黒でサーバ上に保存されます。
パーマリンクとかつけてあげると普通に便利なサイトが出来上がりそうです。
sample.jpg

コード

ACTIONSCRIPT:
  1. package
  2. {
  3.     import flash.display.Bitmap;
  4.     import flash.display.BitmapData;
  5.     import flash.display.Sprite;
  6.     import flash.events.Event;
  7.     import flash.events.EventDispatcher;
  8.     import flash.events.MouseEvent;
  9.     import flash.geom.Point;
  10.     import flash.geom.Rectangle;
  11.     import flash.media.Camera;
  12.     import flash.media.Video;
  13.     import flash.net.*;
  14.     import flash.text.TextField;
  15.     import flash.utils.ByteArray;
  16.    
  17.     import com.adobe.images.JPGEncoder;
  18.    
  19.     public class Main extends flash.display.Sprite
  20.     {
  21.         private var camera_width:int = 200;
  22.         private var camera_height:int = 150;
  23.         private var video:Video = new Video(camera_width, camera_height);
  24.         private var tfView:TextField;
  25.        
  26.         private var urlRequest:URLRequest;
  27.         private var urlLoader:URLLoader; 
  28.         private var fileReceiver:String = "http://www.jamboree.jp/tmp/cam2jpeg/receive.php";
  29.    
  30.         public function Main():void
  31.         {
  32.            
  33.             tfView = addTextField(220, 0, 200, 150);
  34.             tfView.appendText("start\n");
  35.             var camera:Camera = Camera.getCamera();
  36.             if (camera == null) {
  37.                 //error
  38.                 tfView.appendText("cant get camera!\n");
  39.                 return;
  40.             }
  41.             video.attachCamera(camera);
  42.             addChild(video);
  43.             video.x = 0;
  44.             video.y = 0;
  45.             stage.addEventListener(MouseEvent.CLICK, onClick);
  46.         }
  47.        
  48.         private function onClick(event:MouseEvent):void {
  49.             tfView.appendText("click!\n");
  50.             var s:BitmapData = new BitmapData(camera_width, camera_height)
  51.             s.draw(video);
  52.            
  53.             var d:BitmapData = new BitmapData(camera_width, camera_height)
  54.            
  55.             var r:Rectangle = new Rectangle(0, 0, camera_width, camera_height);
  56.             d.fillRect(r, 0xFFFFFFFF);
  57.            
  58.             d.threshold(s, r, new Point(0, 0), "<=", 90, 0xFF000000, 255, false);
  59.            
  60.             var img:Bitmap = new Bitmap(d);
  61.             addChild(img);
  62.             img.x = 0;
  63.             img.y160;
  64.            
  65.             //送信
  66.             var jpgEncoder:JPGEncoder = new JPGEncoder(80);
  67.             var byteArr:ByteArray = jpgEncoder.encode(d);
  68.             urlRequest = new URLRequest(fileReceiver);
  69.             urlLoader = new URLLoader();
  70.             urlRequest.contentType = "application/octet-stream";
  71.             urlRequest.method = URLRequestMethod.POST;
  72.             urlRequest.data = byteArr;
  73.             urlLoader.load(urlRequest);
  74.             urlLoader.addEventListener(Event.COMPLETE,onUpload)
  75.         }
  76.        
  77.         private function onUpload(event:Event):void {
  78.             tfView.appendText("uploaded!\n");
  79.         }
  80.        
  81.         private function addTextField(x:Number, y:Number, w:Number, h:Number):TextField {
  82.             var textField:TextField;
  83.             textField = new TextField();
  84.             addChild(textField);
  85.             textField.x         = x;
  86.             textField.y         = y;
  87.             textField.width     = w;
  88.             textField.height    = h;
  89.             textField.text      ="";
  90.             textField.selectable=true;
  91.             textField.border    =true;
  92.            
  93.             return textField;
  94.         }
  95.     }
  96. }

receive.php

PHP:
  1. <?php
  2. $fileName = time()."-".round(rand(1,10000)).".jpg";
  3. $fp = fopen("data/".$fileName, 'wb');
  4. fwrite($fp, $GLOBALS['HTTP_RAW_POST_DATA']);
  5. fclose($fp);
  6. chmod("data/".$fileName,0777);
  7. ?>

解説

as3corelibのJPGEncoderクラスというのをBitmapからJpegへの変換に使用しているのでhttp://code.google.com/p/as3corelib/source/checkoutからチェックアウトして下図の様に配置しておいてください。
tree.gif

まとめ

勉強会とかもみんなWebCamでバシバシとったら面白いんじゃないかと思った。いまどきは動画もいけるんだけどやっぱ写真の面白さはまた別にありますよね。

参考サイト

Flashから画像ファイルを保存する - FICC LABS

as3でWebカメラ画像の2値化(白黒化)

4月 11th, 2008 admin

白黒の顔写真を取り込みたかっただけなんだけど、思ってたより1ピクセルが大きくてギザギザになった。
これをスムーズにする方法があるんだろうか。
このWebカメラは100万画素ぐらいあるはずなんだけど、取り込み用のそういうのはどこかで設定できるんだろうな。
今日はもう遅いのでまた明日調べよう

成果物

しみやそばかすを自動で消してくれるフォトレタッチソフト(落書きっぽいのは後付です)
flash2.jpg
サンプルはこちら(画面をクリックで白黒画像がとれます)

コード

package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.media.Camera;
	import flash.media.Video;
	import flash.text.TextField;

	public class Main extends flash.display.Sprite
	{
		private var camera_width:int = 200;
		private var camera_height:int = 150;
		private var video:Video = new Video(camera_width, camera_height);
		private var tfView:TextField;

		public function Main():void
		{

			tfView = addTextField(220, 0, 200, 150);
			tfView.appendText("start\n");
			var camera:Camera = Camera.getCamera();
			if (camera == null) {
				//error
				return;
			}
			video.attachCamera(camera);
			addChild(video);
			stage.addEventListener(MouseEvent.CLICK, onClick);
		}

		private function onClick(event:MouseEvent):void {
			tfView.appendText("click!\n");
			var s:BitmapData = new BitmapData(camera_width, camera_height)
			s.draw(video);

			var d:BitmapData = new BitmapData(camera_width, camera_height) 

			var r:Rectangle = new Rectangle(0, 0, camera_width, camera_height);
			d.fillRect(r, 0xFFFFFFFF);

			d.threshold(s, r, new Point(0, 0), "<=", 90, 0xFF000000, 255, false);

			var img:Bitmap = new Bitmap(d);
			addChild(img);
			img.x = 0;
			img.y =  160;
		}

		private function addTextField(x:Number, y:Number, w:Number, h:Number):TextField {
			var textField:TextField;
			textField = new TextField();
            addChild(textField);
            textField.x         = x;
            textField.y         = y;
            textField.width     = w;
            textField.height    = h;
            textField.text      ="";
            textField.selectable=true;
            textField.border    =true;

			return textField;
		}
	}
}

まとめ

BitmapDataにthresholdっていうすべてのピクセルを特定の条件で色を変えるっていうずばりそのもののコードがあったのでできた。そしてずばりそのもののコードが載っているサイトがあったのでできた。Webカメラから取り込んでいるというところだけがオリジナル。Webすごい

参考サイト

Flash Player 9/ActionScript3.0/Flex2の勉強日記

BitmapData - ActionScript 3.0 コンポーネントリファレンスガイド


trick7.com blog: BIT-101 : BitmapData Threshold Explorer

as3でWebカメラ画像の取り込みの練習

4月 8th, 2008 admin

話が逆な気もするけど「Flash+WebCam+Web」って凄い組み合わせだと思う。
今後数年以内に爆発的に流行ると思うので今から取り込みの練習。
ビデオを取得してそれをビットマップにすればいいらしい。

成果物

買ったし安くなかった割に読んでない本を自慢できるswf
flash.jpg
画面をクリックする度にWebカメラの画像が取り込まれて下につながっていく。それだけ。

コード

package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.media.Camera;
	import flash.media.Video;
	import flash.text.TextField;

	public class Main extends flash.display.Sprite
	{
		private var camera_width:int = 200;
		private var camera_height:int = 150;
		private var bitmap_y_offset:int = 160;
		private var video:Video = new Video(camera_width, camera_height);
		private var tfView:TextField;

		public function Main():void
		{

			tfView = addTextField(220, 0, 200, 150);
			tfView.appendText("start\n");
			var camera:Camera = Camera.getCamera();
			if (camera == null) {
				//error
				return;
			}
			video.attachCamera(camera);
			addChild(video);
			stage.addEventListener(MouseEvent.CLICK, onClick);
		}

		private function onClick(event:MouseEvent):void {
			tfView.appendText("click!\n");
			var bd:BitmapData = new BitmapData(camera_width, camera_height)
			bd.draw(video);
			var img:Bitmap = new Bitmap(bd);
			addChild(img);
			img.x = 0;
			img.y =  bitmap_y_offset;
			bitmap_y_offset += bitmap_y_offset;

		}

		private function addTextField(x:Number, y:Number, w:Number, h:Number):TextField {
			var textField:TextField;
			textField = new TextField();
            addChild(textField);
            textField.x         = x;
            textField.y         = y;
            textField.width     = w;
            textField.height    = h;
            textField.text      ="";
            textField.selectable=true;
            textField.border    =true;

			return textField;
		}
	}
}

まとめ

次はサーバにアップロードされるようにしたいと思う。そうすればサイトにアクセスしてWebカメラをポンとクリックしてスマートURLが発行されて友達に送れるっていう、お前なんかいてもいなくても同じなWebサービスの完成です。

疑問

videoのCLICKイベントを拾いたかったけど拾えなかった、どうやってやるんだろうか?

参考サイト

Flash Player 9/ActionScript3.0/Flex2の勉強日記
AS3でDisplayObjectをBitmapDataに変換してみたよ。 - Humming Via Kitchen

FlashDevelopはIEのFlash Playerを使う

2月 9th, 2008 admin

FlashDevelopでAS3デビューしようとしていたら
デバッグ実行の時に

Waiting for Player to connect
Failed to connect; session timed out.
Ensure that:
1. you compiled your Flash movie with debugging on, and
2. you are running the Debugger version of the Flash Player.

とかって出るんですよ
どうもこういうこと↓らしいんです。

GMSBLOG � FlashDevelopのPlayerはIEのヤツ
http://gamusoba.com/blog/item_20070815.html#nucleus_cf

1時間ぐらいFlash CS3とかを入れたりとか出したりしながら悩んでいましたがあっさり解決。
FlashDevelopのデフォルト設定では、IEのFlashPlayerを使うようです。だからIEのやつを9以上のバージョンにしないといけなかったんですね。

もしくは
Tools>Settings>Plugins>FlashViewer>Mics>ExternalPlayerPath
で変更できるので、IEのPlayerのバージョンをわざわざ上げたくない場合はどうぞ

FMSで作るBBSアプリケーションチュートリアル

9月 2nd, 2007 admin

Flash Media Serverを使って掲示板アプリケーションを作成するまでのメモです。そもそもFlashがわからないという僕のような人は

Flash 8 入門講座:ITpro

あたりを読むことから始めましょう。かなり充実しています。(僕はやっと第24回までいきました)

参考資料

今回参考にしたのは下記のサイトです。

環境と準備

  • Windows
  • Window版FMSのダウンロードとインストール
  • Flash8のインストール

サービスの確認

  • Macromedia Flash Media Server 2
  • Start Flash Media Admin Server and Flash Media Server

Windows の場合、サーバーが稼動していることを確認するため
に、タスクマネージャを開いて、FMSAdmin.exe と FMSMaster.exe の両方が [ プロセス ] タブに表
示されていることを確認します。

そんな確認方法しかないらしいです。

サーバの準備

アプリケーションのセット

C:¥Program files¥Macromedia¥Flash Media Server 2¥applicationsの中にアプリケーション名でディレクトリを作成します。

今回は「bbs」にしました。

インスタンスの作成

管理画面からインスタンスを作成します。「インスタンスを作成=サーバを立てた」だと思います。

インスタンスを作成するときに名前を聞かれますが、今回は_defInst_で問題ありません。_defInst_はクライアントからインスタンス名が指定されなかった場合に接続される特別な名前だからです。

掲示板(チャット)の場合だとスレッド(トピック)ごとにインスタンスを作成するんだと思います。

fms01.gif

サーバへの接続

アプリケーションは、RTMP (Real-Time Messaging Protocol) または RTMPS (Real-Time Messaging Protocol over SSL (Secure Socket Layer)) を使用して Flash Media Server に 接続できます。


my_nc = new NetConnection();
my_nc.connect("rtmp://localhost/bbs");

fms02.gif
fms03.gif

こんなコードを書いて実行してみると、サーバに接続できます。2行でいいなんてすごい。

BBSアプリケーションの作成

テクササイズ第6回
FlashMediaServer2を使ってみよう

ここのSharedObjectのスクリプトを参考に作ってみる。

my_nc = new NetConnection();
my_nc.connect("rtmp://localhost/bbs");
bbs();
function bbs(){
//sharedObjectを作る
//getRemoteメソッドの第一引数はSharedObjectの名前、第二引数はURL。URLはNetConnection.uriプロパティで取得できる。
so = SharedObject.getRemote("shared_text",my_nc.uri);
//SharedObjectが変更されたときの処理
//SharedObjectが変更されるとonSyncイベントが呼び出されるのでイベントハンドラメソッドを作る
so.onSync=function(){
trace("SharedObjectが変更されました");
comments.text=this.data.comments;//このスコープの中ではthisはsoを指す
}
//SharedObjectをサーバーに接続
so.connect(my_nc);
send.onRelease=function(){
so.data.comments += "\n" + myComment.text;
myComment.text = "";
}

テスト

なぜか最初にundefinedと表示されてしまうが、通信できるようになりました。
BBSを作る予定でしたがどちらかというとCHATですね。

fms04.gif

connect()で指定しているアドレスをlocalhostから変更してやれば別のPCからでも接続できます。

サンプル

bbs.zip