PsychedelicCam
@author fumix
/**
* Copyright fumix ( http://wonderfl.net/user/fumix )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/12Rl
*/
package {
import net.hires.debug.Stats;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.ColorMatrixFilter;
import flash.filters.ConvolutionFilter;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.media.Camera;
import flash.media.Video;
import flash.text.TextField;
/**
* @author fumix
*/
[SWF(backgroundColor="#000000", frameRate="31", width="465", height="465")]
public class PsychedelicCam extends Sprite {
private var _w : int;
private var _h : int;
private var _camera : Camera;
private var _video : Video;
private var _bm : Bitmap;
private var _bmd : BitmapData;
private var _psycheFlag : Boolean;
public function PsychedelicCam() {
if(stage) initialize();
else addEventListener(Event.ADDED_TO_STAGE, initialize);
}
/**
* 初期化
* @param event
*/
private function initialize(event : Event = null) : void {
removeEventListener(Event.ADDED_TO_STAGE, initialize);
//背景設定
_w = stage.stageWidth;
_h = stage.stageHeight;
var bmd : BitmapData = new BitmapData(_w, _h, true, 0x000000);
addChild(new Bitmap(bmd));
//webカメラ
_camera = Camera.getCamera();
_camera.setMode(_w, _h, 15);
_video = new Video(_w, _h);
_video.attachCamera(_camera);
addChild(_video);
//カメラあり
if(_camera != null) {
//カメラ無し
} else {
var txt : TextField = new TextField();
txt.textColor = 0xFFFFFF;
txt.text = 'カメラ無し';
addChild(txt);
}
//フラグ初期化
_psycheFlag = false;
//サイケ画像表示用
_bm = new Bitmap();
_bmd = new BitmapData(_w, _h, true, 0xFFFFFFFF);
_bm.bitmapData = new BitmapData(_w, _h, true, 0xFF000000);
_bm.visible = false;
addChild(_bm);
//Stats
addChild(new Stats());
Wonderfl.capture_delay( 20 );
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
/**
* マウスクリック
* @param event
*/
private function onMouseUp(event : MouseEvent) : void {
_psycheFlag = !_psycheFlag;
if(_psycheFlag) {
_bm.visible = true;
effect();
//stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
}else{
_bm.visible = false;
//stage.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
}
}
/**
* フレーム処理
* @param event
*/
private function onEnterFrame(event : Event) : void {
effect();
}
/**
* エフェクト処理
*/
private function effect() : void {
var colorArray : Array = [0xFF33CC33,0xFF3364FE,0xFFC727F9,0xFFFF4342,0xFFFFFF02,0xFF658448,0xFFFE33A8];
colorArray = shuffleArray(colorArray);
var bmd : BitmapData = new BitmapData(_w, _h);
var thres : BitmapData;
var edge : BitmapData;
var min : int = 20;
var max : int = 190;
var step : int = 7;
//ベースのbitmapをリセット
_bm.bitmapData.copyPixels(_bmd, _bmd.rect, new Point(0, 0));
//webカメラの画像を取得
bmd.draw(_video);
//グレースケール化
var t:Number
var g : BitmapData = grayscaleFilter(bmd);
//ノイズ除去
g = medianSmoothFilter(g);
for (var i : int = 0;i <step;i ++) {
t= min+(max-min)/step * i;
//2値化
thres = thresholdFilter(g, t, colorArray[i]);
//2値化
edge = thresholdFilter(g, t);
//エッジ検出
edge = laplacianFilter(edge);
//描画
_bm.bitmapData.draw(thres, null, null, BlendMode.NORMAL);
_bm.bitmapData.draw(edge, null, null, BlendMode.SUBTRACT);
}
//ビットマップ破棄
bmd.dispose();
thres.dispose();
edge.dispose();
}
/**
* 2値化処理
* @param image
* @param threshold
* @param color
* @return BitmapData
*/
private function thresholdFilter(image : BitmapData,threshold : int,color : uint = 0xFFFFFFFF) : BitmapData {
var d:BitmapData = new BitmapData(image.width, image.height);
var r:Rectangle = new Rectangle(0, 0, image.width, image.height);
d.fillRect(r, 0x00000000); // 不透明黒で塗りつぶす
// 閾値以下を不透明黒にする
d.threshold(image, r, new Point(0, 0), ">", threshold, color, 0x000000FF, false);
return d;
}
/**
* ノイズ除去
* @param image
* @return BitmapData
*/
private function medianSmoothFilter(image : BitmapData) : BitmapData {
var d:BitmapData = new BitmapData(image.width, image.height);
var a:Array = new Array(9);
for (var x:int = 0; x < image.width; x++) {
for (var y:int = 0; y < image.height; y++) {
a[0] = image.getPixel(x - 1, y - 1) & 255;
a[1] = image.getPixel(x - 1, y) & 255;
a[2] = image.getPixel(x - 1, y + 1) & 255;
a[3] = image.getPixel(x, y - 1) & 255;
a[4] = image.getPixel(x, y) & 255;
a[5] = image.getPixel(x, y + 1) & 255;
a[6] = image.getPixel(x + 1, y - 1) & 255;
a[7] = image.getPixel(x + 1, y) & 255;
a[8] = image.getPixel(x + 1, y + 1) & 255;
a.sort(Array.NUMERIC); // ソートして
var c:int = a[4]; // 真ん中を取る
d.setPixel(x, y, (c << 16) | (c << 8) | c); // 中央値による色の設定
}
}
return d;
}
/**
* ラプラシアンフィルタ(エッジ処理)
* @param image
* @return BitmapData
*/
private function laplacianFilter(image : BitmapData) : BitmapData {
var d:BitmapData = new BitmapData(image.width, image.height);
var rect : Rectangle = new Rectangle(0, 0, image.width, image.height);
var p : Point = new Point(0, 0);
var l:Array = [-1, -1, -1,
-1, +8, -1,
-1, -1, -1]; // ラプラシアンフィルタ
d.applyFilter(image, rect, p,
new ConvolutionFilter(3, 3, l));
return d;
}
/**
* グレースケールフィルタ
* @param imageData
* @return BitmapData
* @return BitmapData
*/
private function grayscaleFilter(image : BitmapData) : BitmapData {
var d : BitmapData = new BitmapData(image.width, image.height);
var rect : Rectangle = new Rectangle(0, 0, image.width, image.height);
var p : Point = new Point(0, 0);
var cmatrix:ColorMatrixFilter = new ColorMatrixFilter([
1/3,1/3,1/3,0 ,0,
1/3,1/3,1/3,0 ,0,
1/3,1/3,1/3,0 ,0,
0 ,0 ,0 ,255,0]);
d.applyFilter(image, rect, p, cmatrix);
return d;
}
/**
* 配列のシャッフル
* @param arr
* @return Array
*/
private function shuffleArray(arr:Array):Array {
var _len:uint = arr.length;
var _reArr:Array = arr;
while (_len) {
var _m:uint = Math.floor(Math.random() * _len);
var _n:uint = _reArr[--_len];
_reArr[_len] = _reArr[_m];
_reArr[_m] = _n ;
}
return _reArr;
}
}
}