陈童的博客's Archivers

From everyinch on 2011-09-18 14:13:44

摄像头的边缘检测与雪花

利用ConvolutionFilter滤镜,处理一下摄像头中的视频。计算摄像头视频中每一帧图像的边缘,使图像边缘的颜色接近于白色,而其它部分颜色接近与黑色。对于雪花来讲,检测它运动部分的颜色,如果接近白色则使雪花停止运动并逐渐消失,否则就一直飘动。通过以上分析,就可以实现比较流行的雪花落在摄像头视频图像中的边缘的效果。类文件名为EdgeTracking.as,源代码如下:
[code lang="as3"]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);
}

}
}
}[/code]
在onEnterFrame函数中,通过将视频绘制到BitmapData中,为了提升效率代码使用一个矩阵,将视频缩小1/4绘制到BitmapData里。对BitmapData分别应用了BlurFilter、ConvolutionFilter、ColorMatrixFilter以及Threshold,目的无非是更好地呈现图像的边缘。
在for循环中,实现了雪花对边缘的检测。遍历保存所有雪花的数组flakes,当雪花在舞台范围之内且它当前位置的颜色大于0x66FFFF,意味着雪花目前在图像的边缘上。否则就不在边缘上,就让雪花运动。如果在边缘上雪花不发生运动,且根据设置的随机数fadeScale逐渐降低它的alpha直至小于10。如果alpha小于10,那么重新将其定位到舞台的顶部并恢复它的alpha值。

<img class="alignnone size-medium wp-image-115" title="edgeTracking" src="http://www.everyinch.net/wp-content/uploads/2011/09/edgeTracking-300x225.jpg" alt="" width="300" height="225" />

查看完整版本: 摄像头的边缘检测与雪花

Tags: Camera, 边缘检测,


©陈童的博客