Search code examples
actionscript-3videoaugmented-realitynoiseflartoolkit

adding noise to a video in actionscript


Before I begin, I would like to apologize if what I'm going to ask is to be considered as super newbie question.

so I was trying out Lee Brimelow's tutorial on creating a simple AR scene using actionscript3. (http://blog.theflashblog.com/?p=901) It worked out pretty well, considering I have never created something out of Adobe Flex Builder before. (I installed Flex Builder right after I saw those tutorial)

here is the source code

package {

    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.media.Camera;
    import flash.media.Video;
    import flash.utils.ByteArray;

    import org.libspark.flartoolkit.core.FLARCode;
    import org.libspark.flartoolkit.core.param.FLARParam;
    import org.libspark.flartoolkit.core.raster.rgb.FLARRgbRaster_BitmapData;
    import org.libspark.flartoolkit.core.transmat.FLARTransMatResult;
    import org.libspark.flartoolkit.detector.FLARSingleMarkerDetector;
    import org.libspark.flartoolkit.support.pv3d.FLARBaseNode;
    import org.libspark.flartoolkit.support.pv3d.FLARCamera3D;
    import org.papervision3d.lights.PointLight3D;
    import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
    import org.papervision3d.materials.utils.MaterialsList;
    import org.papervision3d.objects.primitives.Cube;
    import org.papervision3d.render.BasicRenderEngine;
    import org.papervision3d.scenes.Scene3D;
    import org.papervision3d.view.Viewport3D;

    [SWF(width="640", height="480", frameRate="30", backgroundColor="#FFFFFF")]

    public class FLARdemo extends Sprite
    {
        [Embed(source="pat1.pat", mimeType="application/octet-stream")]
        private var pattern:Class;

        [Embed(source="camera_para.dat", mimeType="application/octet-stream")]
        private var params:Class;

        private var fparams:FLARParam;
        private var mpattern:FLARCode;
        private var vid:Video;
        private var cam:Camera;
        private var bmd:BitmapData;
        private var raster:FLARRgbRaster_BitmapData;
        private var detector:FLARSingleMarkerDetector;
        private var scene:Scene3D;
        private var camera:FLARCamera3D;
        private var container:FLARBaseNode;
        private var vp:Viewport3D;
        private var bre:BasicRenderEngine;
        private var trans:FLARTransMatResult;

        public function FLARdemo()
        {
            setupFLAR();
            setupCamera();
            setupBitmap();
            setupPV3D();
            addEventListener(Event.ENTER_FRAME, loop);
        }

        private function setupFLAR():void
        {
            fparams = new FLARParam();
            fparams.loadARParam(new params() as ByteArray);
            mpattern = new FLARCode(16, 16);
            mpattern.loadARPatt(new pattern());
        }

        private function setupCamera():void
        {
            vid = new Video(640, 480);
            cam = Camera.getCamera();
            cam.setMode(640, 480, 30);
            vid.attachCamera(cam);
            addChild(vid);
        }

        private function setupBitmap():void
        {
            bmd = new BitmapData(640, 480);
            bmd.draw(vid);
            raster = new FLARRgbRaster_BitmapData(bmd);
            detector = new FLARSingleMarkerDetector(fparams, mpattern, 80);
        }

        private function setupPV3D():void
        {
            scene = new Scene3D();
            camera = new FLARCamera3D(fparams);
            container = new FLARBaseNode();
            scene.addChild(container);

            var pl:PointLight3D = new PointLight3D();
            pl.x = 1000;
            pl.y = 1000;
            pl.z = -1000;

            var ml:MaterialsList = new MaterialsList({all: new FlatShadeMaterial(pl)});

            var Cube1:Cube = new Cube(ml, 30, 30, 30);                  
            var Cube2:Cube = new Cube(ml, 30, 30, 30);
            Cube2.z = 50
            var Cube3:Cube = new Cube(ml, 30, 30, 30);
            Cube3.z = 100

            container.addChild(Cube1);
            container.addChild(Cube2);
            container.addChild(Cube3);

            bre = new BasicRenderEngine();
            trans = new FLARTransMatResult();

            vp = new Viewport3D;
            addChild(vp);
        }

        private function loop(e:Event):void
        {
            bmd.draw(vid);

            try
            {
                if(detector.detectMarkerLite(raster, 80) && detector.getConfidence() > 0.5)
                {
                    detector.getTransformMatrix(trans);
                    container.setTransformMatrix(trans);
                    bre.renderScene(scene, camera, vp);
                }
            }
            catch(e:Error){}
        }
    }
}

what I am asking is : is it possible for us to add some noise in the final video output? I'm trying to find out the PSNR by adding noises respectively. can I do some convolution between the noise and the video?

oh btw I'm doing this for my assignment in college. My prof wanted me to explain how exactly the FlarToolKit works. (details such as Matrix Projections, Obtaining Errors by doing Iterative Method, etc.)

Thank you. Prama


Solution

  • Creating fine-grained noise dynamically is computationally expensive, so I generate low-res noise and scale it up. In your project, simply add the bitmap setup code after the addEventListener call and then add the single line to generate the noise to your activity loop.

    package 
    {
        import flash.display.Bitmap;
        import flash.display.BitmapData;
        import flash.display.BlendMode;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.geom.Matrix;
        import flash.media.Camera;
        import flash.media.Video;
        import flash.utils.getTimer;
    
        public class NoiseMain extends Sprite
        {
            protected static const VID_WIDTH : uint = 640;
            protected static const VID_HEIGHT : uint = 480;
    
            protected static const NOISE_SCALE_X : Number = 4;
            protected static const NOISE_SCALE_Y : Number = 2;
    
            protected var _vid : Video;
            protected var _noise : BitmapData;
            protected var _composite : BitmapData;
            protected var _matrix : Matrix;
    
            public function NoiseMain()
            {
                // We're creating a webcam outlet, but not adding it to the stage since we want to post-process the image.
                _vid = new Video(VID_WIDTH, VID_HEIGHT);
                var cam : Camera = Camera.getCamera();
                cam.setMode(VID_WIDTH, VID_HEIGHT, 30);
                _vid.attachCamera(cam);     
    
                var w : uint = Math.ceil(VID_WIDTH / NOISE_SCALE_X);
                var h : uint = Math.ceil(VID_HEIGHT / NOISE_SCALE_Y);
    
                _noise = new BitmapData(w, h, false, 0xFFFFFF);
                _composite = new BitmapData(VID_WIDTH, VID_HEIGHT, false, 0x000000);
                var bmp : Bitmap = new Bitmap(_composite);
                addChild(bmp);
    
                _matrix = new Matrix(NOISE_SCALE_X, 0, 0, NOISE_SCALE_Y);
    
                stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
            }
    
            protected function enterFrameHandler(evt : Event) : void
            {
                _noise.noise(getTimer(), 204, 255, 7, true);
                _composite.lock();
                _composite.draw(_vid);
                _composite.draw(_noise, _matrix, null, BlendMode.MULTIPLY); 
                _composite.unlock();        
            }
        }
    }
    

    EDIT: I've revised my example to be more in line with what you're trying to do. You can tweak the noise scale constants to change the "texture" of the noise as well as messing with the strength of the noise (the 2nd and 3rd arguments to the noise() method) and the visual appearance of the noise by changing the BlendMode in the 2nd draw() call).