摄像头的边缘检测与雪花

二维粒子 everyinch 4607℃ 0评论

利用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值。

分享&收藏

转载请注明:陈童的博客 » 摄像头的边缘检测与雪花

喜欢 (2)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
'; } if( dopt('d_footcode_b') ) echo dopt('d_footcode'); ?>