ActionScript 3.0综合应用案例(图像识别+位图滤镜+Molehill)
2011-03-25 23:37
357 查看
本文是对ActionScript3.0的一个综合应用案例,涉及到图像识别,位图滤镜以及Molehill底层API等方面的知识。请确保安装了AdobeLabs里发布的FlashPlayer11,0,0,58(代号Incubator),本案例的开发环境如下:
FlashBuilder4
FlexSDK4.5Hero(Build19786)
AGALMinAssembler
请参考这篇文章在FlashBuilder里配置Incubator的开发环境:
如何通过FlexSDK或者FlashProfessional来开发测试Incubator
请点击图片查看最终效果,以确保运行时安装无误。
本文的几个知识点:
简单的识别动作的方法
水波效果的原理
使用Molehill底层API绘制水波平面
简单的识别动作的方法
这个案例里的动作识别原理非常之简单,简而言之就是对比两张图片然后找出不同的区域,所以如果把摄像头对准车水马龙的大街,那么结果将是一幅波涛汹涌的场面。
如果你从来没有和摄像头打过交道,那么请看下面的这几行代码:
请参考这篇文章在FlashBuilder里配置Incubator的开发环境:
请点击图片查看最终效果,以确保运行时安装无误。
本文的几个知识点:
简单的识别动作的方法
水波效果的原理
使用Molehill底层API绘制水波平面
简单的识别动作的方法
这个案例里的动作识别原理非常之简单,简而言之就是对比两张图片然后找出不同的区域,所以如果把摄像头对准车水马龙的大街,那么结果将是一幅波涛汹涌的场面。
如果你从来没有和摄像头打过交道,那么请看下面的这几行代码:
varcam:Camera=Camera.getCamera("0"); cam.setMotionLevel(100); video=newVideo(800,600); video.attachCamera(cam);
摄像头可以将捕捉来的图像放在一个Video的实例里,然后既可以用attachChild(video)直接放在舞台上,也可以作为位图源在后续的BitmapData中绘制。比如这样:
sourceBitmapData=newBitmapData(video.width,video.height); sourceBitmapData.draw(video,drawMatrix);
前面提到了,简单的动作捕捉就是对前后两帧的图像进行像素对比,这需要对图像进行逐行扫描。但是如果按照原图像的大小比如800×600来扫描,那么在两层for循环中需要一共检测480,000个像素点,这对CPU来说是一个不小的开销,所以我们不这样做。一个技巧是利用bitmapData.draw的其中一个参数Matrix将原始图像“缩放”到一个小的bimapData上,比如下面就是缩放成80×60的一个例子:
//video(800x600) drawMatrix=newMatrix(.1,0,0,.1,0,0); sourceBitmapData.draw(video,drawMatrix);
代码中,Matrix的第一个和第四个参数分别是横向与纵向的缩放比例,Matrix不是一个新的类,有关Matrix的使用请参考ActionScript帮助文档。
下一步就是在每帧都与前一帧图片对比,扫描所有像素,将颜色差异超过一定值的点标记出来,最后取所有标记点的中心点,这个点就是我们要捕捉的动点。
sourceBitmapData.draw(video,drawMatrix); varsumx:Number=0; varsumy:Number=0; vartotal:int=0; for(vari:int=0;i<sourceBitmapData.width;i++){ for(varj:int=0;j<sourceBitmapData.height;j++){ vargap:Number=Math.abs(sourceBitmapData.getPixel(i,j)-lastBitmapData.getPixel(i,j)); if(gap>2000000){ total++; sumx+=i; sumy+=j; } } } lastBitmapData=sourceBitmapData.clone(); vartargetPoint:Point=newPoint(sumx/total,sumy/total);
水波效果的原理 这个效果好多年前就见过,至今依然印象深刻,我认为是对ConvolutionFilter,DisplacementMapFilter和BendMode应用的一个经典案例(本案例中没有用到DisplacementMapFilter)。下面我再来介绍一下这个水波效果的原理以及代码。
ConvolutionFilter(卷积滤镜)可以模拟波的传播与反射。以前我介绍过这个滤镜,它是用一个(M,N)矩阵来表示一个像素受其周围各像素颜色的影响程度。比如下面的这个矩阵,它表示一个点周围的8个点对它的颜色影响都是1。
//定义矩阵的列数与行数 varmatrixX:Number=3; varmatrixY:Number=3; varmatrix:Array=newArray( 1,1,1, 1,1,1, 1,1,1 ); //这个参数是矩阵各个数值之和,如果为0则取1 vardiv:int=9; convolutionFilter=newConvolutionFilter(matrixX,matrixY,matrix,div,-0.2);
卷积滤镜会把这个公式应用在图片上的每个像素点上面,如果每帧都运行一次,那么最后的结果就是颜色值突出的点会向周围扩散,最后所有的像素点颜色等同。这和波向周围传播的表现形式一模一样。而如果这种传播到达了图像边缘,其反应可以由ConvolutionFilter构造函数的第7个参数clamp决定,如果值是true,那么这种扩散会朝图片内部反射。这又和波的反射特性不谋而合。
卷积滤镜模拟波的传播与反射效果 但只是通过卷积滤镜是做不到上图的效果,还要使用图形叠加来完成波峰和波谷的交替。图形叠加(BlendMode)表示两层图形叠加在一起时,上下两层图像是如何影响的。它包括一系列的效果,具体说明请参考 ActionScript帮助文档。利用图形叠加效果中的Add和Different,可以分别创造出波峰和波谷的特效。 全部代码如下,这里面bitmapData3,bitmapData2,bitmapData1可以理解为N,N-1,N-2帧的主位图,N是当前帧。由于卷积滤镜的扩散作用,这三个位图的面积顺序应该是bitmapData3最大,bitmapData1最小。它们分别的作用是:bitmapData1负责绘制波谷,bitmapData2负责绘制波峰,bitmapData3是主位图,用来加滤镜。 //应用缓冲运动计算运动点的位置 movePoint.x+=(sumx/total-movePoint.x)/2; movePoint.y+=(sumy/total-movePoint.y)/2; //首先给bitmapData2绘制一个很小的母环,增加一个新的波峰。 bitmapData2.setPixel(movePoint.x-1,movePoint.y,0x0000FF); bitmapData2.setPixel(movePoint.x+1,movePoint.y,0x0000FF); bitmapData2.setPixel(movePoint.x,movePoint.y-1,0x0000FF); bitmapData2.setPixel(movePoint.x,movePoint.y+1,0x0000FF); //将bitmapData2绘制到当前的位图bitmapData3上,并加上卷积滤镜,完成水波的一次扩散。 bitmapData3.applyFilter(bitmapData2,bitmapData3,newPoint(),convolutionFilter); //用bitmapData3给自身加一个ADD叠加效果以强化水波,不然无法传播。 bitmapData3.draw(bitmapData3,mat,null,BlendMode.ADD); //用更早一帧的位图给bitmapData3反色绘制,用来强化波谷。 bitmapData3.draw(bitmapData1,mat,null,BlendMode.DIFFERENCE); //给bitmapData补充颜色,延长波的传播距离 bitmapData3.draw(bitmapData3,mat,colorTransform); //保存新一轮的bitmapData1,bitmapData2,为下一帧绘制做准备。 bitmapData1=bitmapData2; bitmapData2=bitmapData3.clone(); 使用Molehill底层API绘制水波平面 最后就是如何将水波的效果利用Molehill的底层API绘制到3D舞台上。这里需要顶点着色器和片段着色器的基础知识,我在这篇文章中有过详细的介绍:深入浅出了解Molehill的底层API-顶点着色器与片段着色器 好了,假设你现在已经知道如何使用VertexShader和FragmentShader来绘制三角形,我们来看看如何绘制一个由若干三角形组成的平面。关于这个命题,我的朋友EdwardHuang在这篇文章里有一个不错的例子,本文关于搭建顶点模型的一些代码就是援引自那里。 在平面中搭建顶点的工程与我们在2D里排列图标的道理一样简单,只需一对for循环便可以实现: for(varj:int=0;j<=meshRowNum;j++){ for(vari:int=0;i<=meshColNum;i++){ meshPool.push( 4*i/meshColNum-2,-2,5-4*j/meshRowNum, 0,.5*j/meshRowNum,j/meshRowNum); if(i<meshColNum&&j<meshRowNum){ indexPool.push(dotId,dotId+1,dotId+meshColNum+2); indexPool.push(dotId,dotId+meshColNum+1,dotId+meshColNum+2); } dotId++; } } meshPool是一个数组,用来寄存所有的顶点(位置、颜色),以便接下来给顶点缓冲提供数据。这里有一个细节需要提一下。如果按照逐列扫描的顺序,在我的MacBookPro/OpenGL上运行的结果中会出现三角形Depths排序混乱的情况,所以我采用了逐行扫描,即先j后i。究竟是为什么说实话我也没有找到原因,目前正在和我们的产品经理以及QE团队沟通中,以确定这到底是不是一个Bug。 代码中关于indexPool的部分,如果用下图来解释就很清楚: 图中meshColNum是4,一共有5列顶点,由于是逐行扫描,所以每个点的dotId为横向递增,纵向为等差数列(间隔为5,即meshColNum+1)。在每一个方格中用四点双面法绘制两个三角形,其中蓝色的三角形由点0,1,6组成,绿色的三角形由0,5,6组成。所以公式可以归纳成这样,由N点开始的两个三角形为(N,N+1,N+meshColNum+2)和(N,N+meshColNum+1,N+meshColNum+2)。这样IndexBuffer的序列就很容易被定义出来。 在定义了顶点缓冲、着色器、索引缓冲、透视矩阵常量等信息之后(详见上面提到的文章),最后一部就是在每一帧都调用的方法中更新顶点的纵坐标值,使得它与水波位图中相应像素点的颜色值成正比,这样水波的波形就会被绘制在3D空间中。 privatefunctionrender():void{ vardotId:int=0; for(varj:int=0;j<=meshRowNum;j++){ for(vari:int=0;i<=meshColNum;i++){ //取出相应点在位图中的颜色值 varc:int=bitmapData3.getPixel(Math.round((bitmapData3.width-1)*i/meshColNum), Math.round((bitmapData3.height-1)*j/meshRowNum) ); //由于主位图水波用蓝色绘制,所以这里不用进行额外的位运算 meshPool[dotId*6+1]=-2-.5*(c)/0xFF; dotId++; } } vertextBuffer.uploadFromVector(meshPool,0,meshPool.length/6); context3D.clear(0,0,0); context3D.drawTriangles(indexBuffer,0); context3D.present(); } 全部代码请在这里下载: WaterControl.as
相关文章推荐
- ActionScript 3.0综合应用案例(图像识别+位图滤镜+Molehill)
- [ActionScript 3.0] AS3中的位图(BitmapData)应用
- [ActionScript 3.0] AS3 ConvolutionFilter卷积滤镜的应用
- Actionscript 3.0 编程实例一 Timer应用 (写给初学的朋友)
- 图像识别-C++读取bmp位图入门
- 应用示例:图像文字识别
- Word/Excel文秘/行政办公应用技巧与综合案例操作
- TensorFlow在图像识别中的应用
- 稳扎稳打Silverlight(38) - 3.0滤镜之BlurEffect, DropShadowEffect, 自定义滤镜, 3D效果之PlaneProjection, 位图API之WriteableBitmap
- [ActionScript 3.0] AS3实现滤镜叠加效果
- 18 理解反射的概念19构造方法的反射应用20成员变量的反射 21成员变量反射的综合案例22成员方法的反射
- 纯Python综合图像处理小工具(3)10种滤镜算法
- GDI+ 在Delphi程序的应用 -- GDI+图像与GDI位图的相互转换
- Javascript图像处理―亮度对比度应用案例
- [机器学习笔记]Note16--应用示例:图像文字识别
- Linux下Apache与MySQL+PHP的综合应用案例 推荐
- [译]CS231n 卷积神经网络对于图像识别的应用--(一)(CS231n Convolutional Neural Networks for Visual Recognition)
- Linux下Apache与MySQL+PHP的综合应用案例
- TensorFlow在图像识别中的应用
- 企业中squid+iptables多模块的综合应用案例