[WebCam]エッジの方向 http://aquioux.blog48.fc2.com/blog-entry-680.html の内容を WebCam に適用したものです。 Aquioux forked:2favorite:26lines:217license : MIT License modified : 2010-02-01 21:42:16 Embed Tweet // http://aquioux.blog48.fc2.com/blog-entry-680.html の内容を WebCam に適用したものです。 package { import flash.display.Sprite; import flash.events.Event; /** * 各種フィルタを使ったウェブカム画像の加工 * @author YOSHIDA, Akio (Aquioux) */ [SWF(width = "465", height = "465", frameRate = "30", backgroundColor = "#FFFFFF")] public class Main extends Sprite { public function Main() { Wonderfl.capture_delay(20); // Model を生成 try { var model:Model = new Model(stage); } catch (err:Error) { trace(err.message); return; } // View を生成 var view:View = new View(model); addChild(view); view.commands = model.commands; // 開始 model.start(); } } } import flash.display.BitmapData; import flash.display.GraphicsPathCommand; import flash.display.Stage; import flash.events.Event; import flash.events.EventDispatcher; import flash.filters.ConvolutionFilter; import flash.geom.Matrix; import flash.geom.Point; import flash.geom.Rectangle; import flash.media.Camera; import flash.media.Video; /** * Web Camera の映像にエフェクトをかける(MVC の Model) * エフェクトロジックは effector クラスとして外部で定義する * @author YOSHIDA, Akio (Aquioux) */ class Model extends EventDispatcher { // -------------------------------------------------- // 定数 // -------------------------------------------------- // 描画間隔 private const INTERVAL:uint = 6; // エッジ検出の強さ private const DEPTH:Number = 5.0; // -------------------------------------------------- // View へ渡すデータ(プロパティ) // -------------------------------------------------- public function get commands():Vector.<int> { return _commands; } private var _commands:Vector.<int>; public function get data():Vector.<Number> { return _data; } private var _data:Vector.<Number>; // -------------------------------------------------- // 外部との通信をおこなうメソッド // -------------------------------------------------- /** * 対 View 用メソッド * このメソッドの終了時にイベントを発行するので、View との通信手段となる * @private */ // ConvolutionFilter 用マトリクス private const HORISON_MATRIX:Array = [ -1, 0, 1, -DEPTH, 0, DEPTH, -1, 0, 1 ]; private const VERTICAL_MATRIX:Array = [ -1, -DEPTH, -1, 0, 0, 0, 1, DEPTH, 1 ]; private const HORISON_FILTER:ConvolutionFilter = new ConvolutionFilter(3, 3, HORISON_MATRIX); private const VERTICAL_FILTER:ConvolutionFilter = new ConvolutionFilter(3, 3, VERTICAL_MATRIX); private const ZERO_POINT:Point = new Point(0, 0); private function update():void { bmd.draw(video, matrix); // ウェブカム映像取り込み grayscale.applyEffect(bmd); // グレイスケール適用 cloneBmd = bmd.clone(); // 複製 // ConvolutionFilter 適用 bmd.applyFilter(bmd, rect, ZERO_POINT, HORISON_FILTER); cloneBmd.applyFilter(cloneBmd, rect, ZERO_POINT, VERTICAL_FILTER); // 平滑化適用 smoothing.applyEffect(bmd); smoothing.applyEffect(cloneBmd); // View 用データ data の決定 var cnt:uint = 0; for (var i:int = 0; i < numY; i++) { for (var j:int = 0; j < numX; j++) { var startX:uint = j * INTERVAL; var startY:uint = i * INTERVAL; var colorX:uint = bmd.getPixel(startX, startY); var colorY:uint = cloneBmd.getPixel(startX, startY); var xx:uint = colorX & 0xFF; var yy:uint = colorY & 0xFF; var radian:Number = Math.atan2(yy, xx); var strength:Number = Math.sqrt(xx * xx + yy * yy); var endX:Number = Math.cos(radian) * strength / INTERVAL + startX; var endY:Number = Math.sin(radian) * strength / INTERVAL + startY; _data[cnt * 4] = startX; _data[cnt * 4 + 1] = startY; _data[cnt * 4 + 2] = endX; _data[cnt * 4 + 3] = endY; cnt++; } } dispatchEvent(new Event(Event.CHANGE)); } // -------------------------------------------------- // その他のメソッド // -------------------------------------------------- /** * コンストラクタ * コンストラクタの引数はステージとする。各種データはアクセサーによって取り込むものとする * @param stage ステージ */ private var stage:Stage; // カメラが表示するサイズ private var cameraWidth:uint; private var cameraHeight:uint; // カメラ private var camera:Camera; private var video:Video; private var bmd:BitmapData; private var cloneBmd:BitmapData; private var matrix:Matrix; private var rect:Rectangle; private var numX:uint; private var numY:uint; public function Model(stage:Stage, cw:Number = 0, ch:Number = 0) { this.stage = stage; this.cameraWidth = (cw == 0) ? stage.stageWidth : cw; this.cameraHeight = (ch == 0) ? stage.stageHeight : ch; bmd = new BitmapData(cameraWidth, cameraHeight, false); cloneBmd = bmd.clone(); matrix = new Matrix( -1, 0, 0, 1, cameraWidth, 0); rect = bmd.rect; numX = cameraWidth / INTERVAL; numY = cameraHeight / INTERVAL; // View 用データの生成 _commands = new Vector.<int>(numX * numY * 2, true); _data = new Vector.<Number>(numX * numY * 4, true); // View 用データ commands の決定 var n:uint = _commands.length / 2; for (var i:int = 0; i < n; i++) { _commands[i * 2] = GraphicsPathCommand.MOVE_TO; _commands[i * 2 + 1] = GraphicsPathCommand.LINE_TO; } // カメラ camera = Camera.getCamera(); if (camera) { // camera のセットアップ camera.setMode(cameraWidth, cameraHeight, stage.frameRate); // video のセットアップ video = new Video(cameraWidth, cameraHeight); video.attachCamera(camera); } else { throw new Error("カメラがありません。"); } } /** * 処理開始 */ private var grayscale:EffectorGrayScale; private var smoothing:EffectorSmoothing; public function start():void { grayscale = new EffectorGrayScale(); smoothing = new EffectorSmoothing(); smoothing.strength = 8; stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler); } /** * イベントハンドラ * @private */ private function enterFrameHandler(event:Event):void { update(); } } import flash.display.Graphics; import flash.display.GraphicsEndFill; import flash.display.GraphicsPath; import flash.display.GraphicsPathCommand; import flash.display.GraphicsSolidFill; import flash.display.GraphicsStroke; import flash.display.IGraphicsData; import flash.display.Sprite; import flash.events.Event; /** * Web Camera のスクリーン(MVC の View) * @author YOSHIDA, Akio (Aquioux) */ class View extends Sprite { /** * コンストラクタ * @param model Model */ private var model:Model; public function View(model:Model) { init(); this.model = model; this.model.addEventListener(Event.CHANGE, changeHandler); } private var graphicsData:Vector.<IGraphicsData>; private var path:GraphicsPath; private function init():void{ var stroke:GraphicsStroke = new GraphicsStroke(); stroke.thickness = 0; stroke.fill = new GraphicsSolidFill(0x000000); var commands:Vector.<int> = new Vector.<int>(); var data:Vector.<Number> = new Vector.<Number>(); path = new GraphicsPath(commands, data); var endfill:GraphicsEndFill = new GraphicsEndFill(); graphicsData = new Vector.<IGraphicsData>(); graphicsData.push(stroke); graphicsData.push(path); graphicsData.push(endfill); } public function set commands(commands:Vector.<int>):void { path.commands = commands; } /** * Model との通信手段 * @param event 発生したイベント */ private function changeHandler(event:Event):void { // Model からデータを受け取り、視覚化 path.data = model.data; var g:Graphics = this.graphics; g.clear(); g.drawGraphicsData(graphicsData); } } import flash.display.BitmapData; import flash.geom.Point; /** * BitmapData エフェクト用抽象クラス * @author YOSHIDA, Akio */ class AbstractEffector { /* * BitmapData.applyFilter で destPoint として使用する Point オブジェクト */ protected const ZERO_POINT:Point = new Point(0, 0); /* * コンストラクタ */ public function AbstractEffector() {} /* * 効果の適用 * @param value 効果をかける BitmapData */ public function applyEffect(value:BitmapData):BitmapData { return effect(value); } /* * 効果内容、具体的なコードはサブクラスで定義する * @param value 効果をかける BitmapData */ protected function effect(value:BitmapData):BitmapData { return value; } } import flash.display.BitmapData; import flash.filters.ColorMatrixFilter; /** * ColorMatrixFilter による BitmapData のグレイスケール化(NTSC 系加重平均による) * 参考:Foundation ActionScript 3.0 Image Effects(P106) * http://www.amazon.co.jp/gp/product/1430218711?ie=UTF8&tag=laxcomplex-22 * @author YOSHIDA, Akio (Aquioux) */ class EffectorGrayScale extends AbstractEffector { // ColorMatrixFilter private const GRAYSCALE_MATRIX:Array = [ 0.3, 0.6, 0.1, 0, 0, 0.3, 0.6, 0.1, 0, 0, 0.3, 0.6, 0.1, 0, 0, 0, 0, 0, 1, 0 ]; private const GRAYSCALE_FILTER:ColorMatrixFilter = new ColorMatrixFilter(GRAYSCALE_MATRIX); /* * グレイスケール実行 * @param value 効果をかける BitmapData */ override protected function effect(value:BitmapData):BitmapData { value.applyFilter(value, value.rect, ZERO_POINT, GRAYSCALE_FILTER); return value; } } import flash.display.BitmapData; import flash.filters.BitmapFilterQuality; import flash.filters.BlurFilter; /** * BlurFilter による平滑化 * @author YOSHIDA, Akio (Aquioux) */ class EffectorSmoothing extends AbstractEffector { /* * ぼかしの量 * @param value 数値 */ public function set strength(value:Number):void { blurFilter.blurX = blurFilter.blurY = value; } /* * ぼかしの質 * @param value 数値 */ public function set quality(value:int):void { blurFilter.quality = value; } // ブラーフィルタ private var blurFilter:BlurFilter; public function EffectorSmoothing() { blurFilter = new BlurFilter(2, 2, BitmapFilterQuality.MEDIUM); } /* * 平滑化実行 * @param value 効果をかける BitmapData */ override protected function effect(value:BitmapData):BitmapData { value.applyFilter(value, value.rect, ZERO_POINT, blurFilter); return value; } } Code Fullscreen Preview Fullscreen jackfreak djankey savage69kr sekundo bgarraud idettman mio_____ jat32 TUNCAYS siouxcitizen.. m_607_m ngtn 024t910 178ep3 kaminaly Nao_u SetzerWolf digitrick sekiryou alptugan : cam yates9 : Tracking onedayitwill.. : flowfieldwebcam erickjones : WebCam novita001 : ConvolutionFilterwebcam zmaxlin : webcam miniapp : WebCam ConvolutionFilter Tracking WebCam cam flowfield smoothing Event.CHANGE clone dispatchEvent BitmapData stage Error Video Vector blurY blurX clear addEventListener quality push attachCamera message getPixel BlurFilter Point sort new page view favorite forked pv0 forked from: [WebCam]エッジの方向 bezoomy forked:0 favorite:0lines:217 (diff:350) pv0 forked from: [WebCam]エッジの方向 realman0205 forked:0 favorite:0lines:217 (diff:350)