In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

WebCam Test For Various Filters - Motion and Edge Detection

includes j2e's EdgeTransform Function for color-coded edges with orientation data
japanese2english@gmail.com

カメラ画像を取得してRGBに分解します。
画面をクリックすると分割した画像を1点に重ねます。
背景が黒、ブレンドモードがADDなら元画像と同じになるはずです。
ブレンドモードをいじったりしてみてください。
/**
 * Copyright j2e ( http://wonderfl.net/user/j2e )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/cYFe
 */

// forked from j2e's forked from: カメラ映像を分解したり戻したり
// includes j2e's EdgeTransform Function for color-coded edges with orientation data
// japanese2english@gmail.com
//
// forked from undo's カメラ映像を分解したり戻したり
/*
* カメラ画像を取得してRGBに分解します。
* 画面をクリックすると分割した画像を1点に重ねます。
* 背景が黒、ブレンドモードがADDなら元画像と同じになるはずです。
* ブレンドモードをいじったりしてみてください。
*/
package
{
    import flash.events.ActivityEvent;
    import caurina.transitions.Tweener;
    
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BitmapDataChannel;
    import flash.display.BlendMode;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.media.Camera;
    import flash.media.Video;
    import flash.system.Security;
    import flash.system.SecurityPanel;
    import flash.geom.Rectangle;
    import flash.geom.Point;
    import flash.filters.ConvolutionFilter;
    import flash.filters.BitmapFilter;
    
    [SWF(backgroundColor = 0x0)]

    public class CameraTests extends Sprite
    {
        public function CameraTests()
        {
            Wonderfl.capture_delay(1);
                stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            this.camWidth = this.stage.stageWidth/2;
            this.camHeight = this.stage.stageHeight/2;
            init();
        }

        private var myBmd:BitmapData;
        private const SMOOTHING:uint = 1; 
        // SMOOTHING defines how far away sampled pixels will be for comparison, 
        //higher numbers may help to eliminate graininess
        
        
        private var _cam:Camera;
        private var _vid:Video;
        private var _bmd:BitmapData;

        private var _redBmd:BitmapData;
        private var _greenBmd:BitmapData;
        private var _blueBmd:BitmapData;

        private var _rbm:Bitmap;
        private var _gbm:Bitmap;
        private var _bbm:Bitmap;

        private var camWidth:Number;
        private var camHeight:Number;
        private var camFPS:Number = 15;

        private var bMode:String = BlendMode.DIFFERENCE;
        private var conved:Boolean = false;
        private function init():void
        {
            Security.allowDomain('*');
            
            _cam = Camera.getCamera();
            if(!_cam) return;
            
            _vid = new Video(camWidth, camHeight);
            _cam.setMode(camWidth, camHeight, camFPS);
            _vid.attachCamera(_cam);
            _bmd = new BitmapData(camWidth, camHeight, false);
            _redBmd = new BitmapData(camWidth, camHeight, false,0);
            _greenBmd = new BitmapData(camWidth, camHeight, false,0);
            _blueBmd = new BitmapData(camWidth, camHeight, false,0);
            // BitmapData to save nonmoving object data for reuse
            //_backgroundBmd = new BitmapData(camWidth, camHeight, false,0);

            _rbm = new Bitmap(_redBmd);
            _gbm = new Bitmap(_greenBmd);
            _bbm = new Bitmap(_blueBmd);            
            
            _rbm.y = _gbm.y = camHeight;
            _bbm.x = _gbm.x = camWidth;
            
            
            var rsp:Sprite = new Sprite();
            var gsp:Sprite = new Sprite();
            var bsp:Sprite = new Sprite();
            
            rsp.cacheAsBitmap = true;
            gsp.cacheAsBitmap = true;
            bsp.cacheAsBitmap = true;
            
            this.addChild(new Bitmap(_bmd));
            
            this.addChild(_rbm);
            this.addChild(_gbm);
            this.addChild(_bbm);
            
            _rbm.blendMode = bMode;
            _gbm.blendMode = bMode;
            _bbm.blendMode = bMode;

            addEventListener(Event.ENTER_FRAME, onEnter);
            _cam.setMotionLevel(5, 1000);

            //_cam.addEventListener(ActivityEvent.ACTIVITY, onMotion);

            stage.addEventListener(MouseEvent.CLICK, onClick);
        }

        private function onEnter(evt:Event):void
        {
            var matrix:Matrix = new Matrix();
            matrix.scale(-1, 1);
            matrix.translate(camWidth, 0);
            //_redBmd.draw(_vid, matrix);
            
            //Set redBmd to motion outline, then find the old position and new position 
            //outlines, so that the old position pixels can be transferred to the new positions.
            // Also, the moving parts could be filtered out of the background, and the background
            // image could be saved as its own separate image with moving object "NORMAL" blended images.
            
            _redBmd.draw(_vid, matrix);
            _redBmd.draw(_bmd, null, null, BlendMode.DIFFERENCE);
            
            //RightEdges(_redBmd);
            //_redBmd.floodFill(0, 0, 0x0000FF);
            
            
            
            _blueBmd.draw(_vid, matrix);
            _greenBmd.draw(_vid, matrix);
            EdgeTransform(_blueBmd);
            //_blueBmd.draw(_redBmd, null, null, BlendMode.SCREEN);
            
            //EdgeTransform(_greenBmd);
            _bmd.draw(_vid, matrix);
            //_bmd.draw(_blueBmd, null, null, BlendMode.ADD);
            
            
            //_redBmd.draw(_vid, matrix);
            
            
            //_rbm.draw(_vid);
            //feed.copyPixels(buffer, rect, pnt);
            //buffer.draw(prev, null, null, BlendMode.DIFFERENCE);
            //prev.draw(video);
            //canvas.copyPixels(buffer, rect, pnt);
            
            //_redBmd.copyChannel(_bmd, _bmd.rect, new Point(), 1, 1);
            
            //_greenBmd.copyChannel(_bmd, _bmd.rect, new Point(), 2, 2);
            //_blueBmd.copyChannel(_bmd, _bmd.rect, new Point(), 4, 4);
        }
        
        private function SectionBitmap(bmd:BitmapData):void {
            
            
        }

        private function RightEdges(bmd:BitmapData):void {
            var rect:Rectangle = new Rectangle(0, 0, bmd.width, bmd.height);
            var pt:Point = new Point(0, 0);
            var solidifyFilter:ConvolutionFilter = new ConvolutionFilter(3, 3, [1, 0, 0, 1, 0, 0, 1, 0, 0])
            var rightEdgeFilter:ConvolutionFilter = new ConvolutionFilter(3, 3, [0, 0, 0, -5, 5, 0, 0, 0, 0]);
            
            bmd.applyFilter(bmd, rect, pt, rightEdgeFilter);
        }

        private function onMotion(evt:ActivityEvent):void {
            var matrix:Matrix = new Matrix();
            
            
        }

        private function onClick(evt:MouseEvent):void
        {
            trace(conved);
            Tweener.removeAllTweens();
            if(conved)
            {
                Tweener.addTween(_rbm, {x:0, time:1, transition:"easeInOutCubic"});
                Tweener.addTween(_bbm, {y:0, time:1, transition:"easeInOutCubic"});
                conved = false;
            }
            else
            {
                Tweener.addTween(_rbm, {x: camWidth, time: 1, transition: "easeInOutCubic"});
                Tweener.addTween(_bbm, {y: camHeight, time: 1, transition: "easeInOutCubic"});
                conved = true;
            }
        }


        /*
         * functions
         */
        private function selectCamera():void
        {
            //ダイアログを表示して、ユーザにカメラを選択してもらう
            Security.showSettings(SecurityPanel.CAMERA);
        }

        private function setCamToVideo(c:Camera, v:Video = null):Video
        {
            //Videoへカメラを設定する
            if (!v)
                v = new Video();

            v.attachCamera(c);
            return v;
        }
        
        ///I tried this 'QuickEdges' version which is more elegant to write but is waaayy slower
        ///than the 'EdgeTransform' version I wrote below.
        /// I thought convolution filters would be faster, but they turned out to take about 3 times as long
        
        private function QuickEdges(bmd:BitmapData):void {
            var rect:Rectangle = new Rectangle(0, 0, bmd.width, bmd.height);
            var pt:Point = new Point(0, 0);
            
            var verthorvertEdges:ConvolutionFilter = new ConvolutionFilter(3, 3, [-1, 0, 0, -1, 4, -1, 0, 0, -1]);
            var horhorvertEdges:ConvolutionFilter = new ConvolutionFilter(3, 3, [-1, -1, 0, 0, 4, 0, 0, -1, -1]);
            var horverthorEdges:ConvolutionFilter = new ConvolutionFilter(3, 3, [0, -1, -1, 0, 4, 0, -1, -1, 0]);
            
            // Create bitmaps for writing edge info to
            var nRedBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
            var nGreenBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
            var nBlueBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
            
            nRedBmd.applyFilter(bmd, rect, pt, verthorvertEdges);
            nGreenBmd.applyFilter(bmd, rect, pt, horhorvertEdges);
            nBlueBmd.applyFilter(bmd, rect, pt, horverthorEdges);
            
            bmd.copyChannel(nRedBmd, rect, pt, BitmapDataChannel.RED, BitmapDataChannel.RED);
            bmd.copyChannel(nGreenBmd, rect, pt, BitmapDataChannel.GREEN, BitmapDataChannel.GREEN);
            bmd.copyChannel(nBlueBmd, rect, pt, BitmapDataChannel.BLUE, BitmapDataChannel.BLUE);
        
        
        }
                /// EdgeTransform takes bitmapData and overwrites it with its edge info
        private function EdgeTransform(bmd:BitmapData):void {
            var rect:Rectangle = new Rectangle(0, 0, bmd.width, bmd.height);
            var pt:Point = new Point(0, 0);
            
            /// Split input bitmap into different color channels to preserve color contrast effect
            
            var redBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
            var greenBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
            var blueBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
            
            redBmd.copyChannel(bmd, rect, pt, BitmapDataChannel.RED, BitmapDataChannel.RED);
            greenBmd.copyChannel(bmd, rect, pt, BitmapDataChannel.GREEN, BitmapDataChannel.GREEN);
            blueBmd.copyChannel(bmd, rect, pt, BitmapDataChannel.BLUE, BitmapDataChannel.BLUE);
            
            // Create bitmaps for writing edge info to
            var nRedBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
            var nGreenBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
            var nBlueBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
            
            var rgbR:uint;
            var rgbG:uint;
            var rgbB:uint;
            
            var oldRgbR:uint;
            var oldRgbG:uint;
            var oldRgbB:uint;
            
            var vertOrientation:uint;
            var horOrientation:uint;
            var verthorOrientation:uint;
            var horvertOrientation:uint;
            
            var ul:uint;
            var ll:uint;
            var dl:uint;
            var uu:uint;
            var ur:uint;
            var rr:uint;
            var dr:uint;
            var c:uint;
            var dd:uint;
            
            var y:uint;
            var x:uint;
            
            //// Go through each channel bitmap separately to preserve color contrast effect
            //// First red channel
            for (y = SMOOTHING; y < bmd.height; y++)
            {
                // Get pixel colors from a 2x3 box of bitmap
                c = redBmd.getPixel(SMOOTHING, y);
                ul = redBmd.getPixel(0, y-SMOOTHING);
                ll = redBmd.getPixel(0, y);
                dl = redBmd.getPixel(0, y+SMOOTHING);
                uu = redBmd.getPixel(SMOOTHING, y-SMOOTHING);
                dd = redBmd.getPixel(SMOOTHING, y+SMOOTHING);
                
                for (x = SMOOTHING; x < bmd.width; x++)
                {
                    // Get pixel colors from right-hand column of 3x3 box
                    ur = redBmd.getPixel(x+SMOOTHING, y-SMOOTHING);
                    rr = redBmd.getPixel(x+SMOOTHING, y);
                    dr = redBmd.getPixel(x+SMOOTHING, y+SMOOTHING);
                    
                    //calculate the angle of the edge for the center point c
                    // depending upon surrounding edge pattern in 3x3 box
                    vertOrientation = uint((Math.abs(ll - c) + Math.abs(rr - c)) / 2);
                    horOrientation = uint((Math.abs(uu - c) + Math.abs(dd - c)) / 2);
                    verthorOrientation = uint((Math.abs(ur - c) + Math.abs(dl - c)) / 2);
                    horvertOrientation = uint((Math.abs(dr - c) + Math.abs(ul - c)) / 2);
                   
                    // Give each instantaneous edge orientation angle a color code
                    rgbR = uint((vertOrientation + horvertOrientation)/0x010101);
                    rgbG = uint((horOrientation + horvertOrientation)/0x010101);
                    rgbB = uint((horOrientation + verthorOrientation)/0x010101);
                    
                    rgbR *= 0x010000;
                    rgbG *= 0x000100;
                    rgbB *= 0x000001;
                    
                    oldRgbR = nRedBmd.getPixel(x, y);
                    oldRgbG = nGreenBmd.getPixel(x, y);
                    oldRgbB = nBlueBmd.getPixel(x, y);
                    
                    nRedBmd.setPixel(x, y, rgbR + oldRgbR);
                    nGreenBmd.setPixel(x, y, rgbG + oldRgbG);
                    nBlueBmd.setPixel(x, y, rgbB + oldRgbB);
                    
                    //shift values for next pass when checking next 3x3 box
                    ll = c;
                    c = rr;
                    ul = uu;
                    uu = ur;
                    dl = dd;
                    dd = dr;
                }

            }
            
            // Next blue channel 
            for (y = SMOOTHING; y < bmd.height; y++)
            {
                // Get pixel colors from a 2x3 box of bitmap
                c = blueBmd.getPixel(SMOOTHING, y);
                ul = blueBmd.getPixel(0, y-SMOOTHING);
                ll = blueBmd.getPixel(0, y);
                dl = blueBmd.getPixel(0, y+SMOOTHING);
                uu = blueBmd.getPixel(SMOOTHING, y-SMOOTHING);
                dd = blueBmd.getPixel(SMOOTHING, y+SMOOTHING);
                
                for (x = SMOOTHING; x < bmd.width; x++)
                {
                    // Get pixel colors from right-hand column of 3x3 box
                    ur = blueBmd.getPixel(x+SMOOTHING, y-SMOOTHING);
                    rr = blueBmd.getPixel(x+SMOOTHING, y);
                    dr = blueBmd.getPixel(x+SMOOTHING, y+SMOOTHING);
                    
                    //calculate the angle of the edge for the center point c
                    // depending upon surrounding edge pattern in 3x3 box
                    vertOrientation = uint((Math.abs(ll - c) + Math.abs(rr - c)) / 2);
                    horOrientation = uint((Math.abs(uu - c) + Math.abs(dd - c)) / 2);
                    verthorOrientation = uint((Math.abs(ur - c) + Math.abs(dl - c)) / 2);
                    horvertOrientation = uint((Math.abs(dr - c) + Math.abs(ul - c)) / 2);
                   
                    // Give each instantaneous edge orientation angle a color code
                    rgbR = uint((vertOrientation + horvertOrientation)/0x010101);
                    rgbG = uint((horOrientation + horvertOrientation)/0x010101);
                    rgbB = uint((horOrientation + verthorOrientation)/0x010101);
                    
                    rgbR *= 0x010000;
                    rgbG *= 0x000100;
                    rgbB *= 0x000001;
                    
                    oldRgbR = nRedBmd.getPixel(x, y);
                    oldRgbG = nGreenBmd.getPixel(x, y);
                    oldRgbB = nBlueBmd.getPixel(x, y);
                    
                    nRedBmd.setPixel(x, y, rgbR + oldRgbR);
                    nGreenBmd.setPixel(x, y, rgbG + oldRgbG);
                    nBlueBmd.setPixel(x, y, rgbB + oldRgbB);
                    
                    //shift values for next pass when checking next 3x3 box
                    ll = c;
                    c = rr;
                    ul = uu;
                    uu = ur;
                    dl = dd;
                    dd = dr;
                }

            }
            
            /// Next green channel
            for (y = SMOOTHING; y < bmd.height; y++)
            {
                // Get pixel colors from a 2x3 box of bitmap
                c = greenBmd.getPixel(SMOOTHING, y);
                ul = greenBmd.getPixel(0, y-SMOOTHING);
                ll = greenBmd.getPixel(0, y);
                dl = greenBmd.getPixel(0, y+SMOOTHING);
                uu = greenBmd.getPixel(SMOOTHING, y-SMOOTHING);
                dd = greenBmd.getPixel(SMOOTHING, y+SMOOTHING);
                
                for (x = SMOOTHING; x < bmd.width; x++)
                {
                    // Get pixel colors from right-hand column of 3x3 box
                    ur = greenBmd.getPixel(x+SMOOTHING, y-SMOOTHING);
                    rr = greenBmd.getPixel(x+SMOOTHING, y);
                    dr = greenBmd.getPixel(x+SMOOTHING, y+SMOOTHING);
                    
                    //calculate the angle of the edge for the center point c
                    // depending upon surrounding edge pattern in 3x3 box
                    vertOrientation = uint((Math.abs(ll - c) + Math.abs(rr - c)) / 2);
                    horOrientation = uint((Math.abs(uu - c) + Math.abs(dd - c)) / 2);
                    verthorOrientation = uint((Math.abs(ur - c) + Math.abs(dl - c)) / 2);
                    horvertOrientation = uint((Math.abs(dr - c) + Math.abs(ul - c)) / 2);
                   
                    // Give each instantaneous edge orientation angle a color code
                    rgbR = uint((vertOrientation + horvertOrientation)/0x010101);
                    rgbG = uint((horOrientation + horvertOrientation)/0x010101);
                    rgbB = uint((horOrientation + verthorOrientation)/0x010101);
                    
                    rgbR *= 0x010000;
                    rgbG *= 0x000100;
                    rgbB *= 0x000001;
                    
                    oldRgbR = nRedBmd.getPixel(x, y);
                    oldRgbG = nGreenBmd.getPixel(x, y);
                    oldRgbB = nBlueBmd.getPixel(x, y);
                    
                    nRedBmd.setPixel(x, y, rgbR + oldRgbR);
                    nGreenBmd.setPixel(x, y, rgbG + oldRgbG);
                    nBlueBmd.setPixel(x, y, rgbB + oldRgbB);
                    
                    
                    //shift values for next pass when checking next 3x3 box
                    ll = c;
                    c = rr;
                    ul = uu;
                    uu = ur;
                    dl = dd;
                    dd = dr;
                }

            }
            // Copy edge information from each respective channel over to original bitmap
            bmd.copyChannel(nRedBmd, rect, pt, BitmapDataChannel.RED, BitmapDataChannel.RED);
            bmd.copyChannel(nGreenBmd, rect, pt, BitmapDataChannel.GREEN, BitmapDataChannel.GREEN);
            bmd.copyChannel(nBlueBmd, rect, pt, BitmapDataChannel.BLUE, BitmapDataChannel.BLUE);

        }
        
    }
}