利用ConvolutionFilter滤镜,处理一下摄像头中的视频。计算摄像头视频中每一帧图像的边缘,使图像边缘的颜色接近于白色,而其它部分颜色接近与黑色。对于雪花来讲,检测它运动部分的颜色,如果接近白色则使雪花停止运动并逐渐消失,否则就一直飘动。通过以上分析,就可以实现比较流行的雪花落在摄像头视频图像中的边缘的效果。类文件名为EdgeTracking.as,源代码如下:
package{ import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.events.Event; import flash.filters.BlurFilter; import flash.filters.ColorMatrixFilter; import flash.filters.ConvolutionFilter; import flash.geom.Matrix; import flash.geom.Point; import flash.geom.Rectangle; import flash.media.Camera; import flash.media.Video; [SWF(width="640", height="480", backgroundColor="0x000000", frameRate="30")] public class EdgeTracking extends Sprite{ private var _width:Number=160; private var _height:Number=120; private var scale:Number=0; private var cam:Camera; private var video:Video; private var bmpd:BitmapData; private var contrastMatrix:Array; private var mat:Matrix; private var rect:Rectangle; private var point:Point; private var fadeScale:Number=0; private var flakes:Array=new Array(); private var counts:uint; public function EdgeTracking(){ scale=640 / _width; bmpd=new BitmapData(_width, _height, false); rect=new Rectangle(0, 0, _width, _height); point=new Point(0, 0); mat=new Matrix(1 / scale, 0, 0, 1 / scale, 0, 0); var ca:Number=1.2; var cb:Number=-40; contrastMatrix=[ca, ca, ca, 0, cb, ca, ca, ca, 0, cb, ca, ca, ca, 0, cb, 0, 0, 0, 1, 0]; cam=Camera.getCamera(); cam.setMode(640, 480, 30); video=new Video(640, 480); video.attachCamera(cam); addChild(video); addEventListener(Event.ENTER_FRAME, onEnterFrame); } private function onEnterFrame(e:Event):void{ bmpd.draw(video, mat); bmpd.applyFilter(bmpd, rect, point, new BlurFilter(5, 5, 1)); bmpd.applyFilter(bmpd, rect, point, new ConvolutionFilter(3, 3, [0, 3, 0, 0.5, -6, 0.5, 0, 2, 0], 0.2, 0, true, true)); bmpd.applyFilter(bmpd, rect, point, new BlurFilter(5, 2, 1)); bmpd.applyFilter(bmpd, rect, point, new ColorMatrixFilter(contrastMatrix)); bmpd.threshold(bmpd, rect, point, ">", 0xFF666688, 0xFFFFFED8, 0xFFFFFF, false); var bmp:Bitmap=new Bitmap(bmpd); addChild(bmp); for (var i:int=0; i < flakes.length; i++){ var flake:snowFlake=flakes[i]; var xpos:Number=Math.round(flake.x/scale); var ypos:Number=Math.round(flake.y/scale); if (ypos > 5 && xpos > 5 && ypos < _height - 5 && xpos < _width - 5 && bmpd.getPixel(xpos, ypos - 1) > 0x66FFFF || bmpd.getPixel(xpos, ypos) > 0x66FFFF){ fadeScale=fadeScale+Math.round(Math.random() * 4); if (fadeScale > 20){ flake.alpha-=20; if (flake.alpha < 10){ flake.x=Math.random()*600+20; flake.y=-Math.random()*50; flake.alpha=Math.random()*20+80; } } } else{ fadeScale=0; flake.blow(); } if (ypos > stage.stageHeight){ flake.x=Math.random()*600+20; flake.y=-Math.random() * 50; return; } if (xpos < 0){ flake.x+=stage.stageWidth; } else if (xpos > stage.stageWidth){ flake.x-=stage.stageWidth; } } if(counts>800){ return; } var j:uint=Math.round(Math.random()*4); while(j--){ ++counts; var snow:snowFlake = new snowFlake(); addChild(snow); snow.x=Math.random()*600+20; snow.y=-Math.random()*50; flakes.push(snow); } } } }
在onEnterFrame函数中,通过将视频绘制到BitmapData中,为了提升效率代码使用一个矩阵,将视频缩小1/4绘制到BitmapData里。对BitmapData分别应用了BlurFilter、ConvolutionFilter、ColorMatrixFilter以及Threshold,目的无非是更好地呈现图像的边缘。
在for循环中,实现了雪花对边缘的检测。遍历保存所有雪花的数组flakes,当雪花在舞台范围之内且它当前位置的颜色大于0x66FFFF,意味着雪花目前在图像的边缘上。否则就不在边缘上,就让雪花运动。如果在边缘上雪花不发生运动,且根据设置的随机数fadeScale逐渐降低它的alpha直至小于10。如果alpha小于10,那么重新将其定位到舞台的顶部并恢复它的alpha值。
转载请注明:陈童的博客 » 摄像头的边缘检测与雪花