首页 > 代码库 > ActionScript3游戏中的图像编程(连载九十二)

ActionScript3游戏中的图像编程(连载九十二)

总目录:http://blog.csdn.net/iloveas2014/article/details/38304477

 

4.5.6 卷积运算对像素的影响机制

      在外力影响较小的情况下,物质间会不断地均匀扩散着(包括固体也能扩散,只是固体分子的距离较小,引力较大,所以一般感觉不出来,比如煤炭放墙边一段时间后,墙也会慢慢变黑,哈,扯远了),而我们也知道,外力无时无刻不在影响着这个世界。比如,人会往高处走,水会往低处流。而在社会学上,囤积居奇,劫贫济富这样的不道德行为我们也都司空见惯了。所以,处理图像像素间关系,实现色彩分配的卷积矩阵也同样具备着使颜色实现不均匀分布的本领,也就是增强对比度,使图像变得清晰的能力。

 

      首先,我们来分析一下模糊矩阵如何让图像变得模糊,我们假设图像上有一个3*3的区域,里面9个点的颜色为:

 

      那么,中间的像素点a与周边任何一个点的对比度都是(a-b),下面我们用3*3的模糊矩阵 对中间的点进行卷积运算,得到的结果是(8b+a)/9。这时候,对比度就变成了(8b+a)/9 – b = a/9 – b/9 = (a-b)/9,对比度比原来下降了8/9,加上结果色融入了周边像素的数值,所以卷积以后的图像就变得模糊了。

 

      在结果式(8b+a)/9中,a和b是图像固有的颜色,所以不能修改,分母9是divisor,在确保让它等于矩阵元素总和的前提下最好也先别进行改动,而8则是卷积矩阵中周边8个点的总和,可被随意修改,而a前面的系数1就正好等于矩阵中间的元素值,也允许修改。所以,我们就把重点落到b和a前面的系数上。

 

      从计算的过程来看,之所以导致对比度降低,是因为卷积后的结果,b所占的比例太高,导致与周边的色彩b对比减弱。现在a和b在结果色中所占的比例为1:8,我们要把a调大或者b调小,比如让b=4,那么结果将等于(4b+a)/5,与周边像素的对比度就从(a-b)/9上升到(a-b)/5了,这时候的矩阵看起来应该是这个样子:

 

       (把4平均分配到周边8个点上)

 

      如果b的系数继续减少,那么对比度将会继续增强,直到b=0,结果色就等于a了,它将不对图像进行任何变换,对比度不发生变化。此时的矩阵除中间的元素是1之外,其它都是0,也就是我们之前讲到的无变换矩阵了。

 

      按照这样的趋势,如果b<0,那么结果就是对比度增强的矩阵了,让b=-8,卷积矩阵就等于。用for循环实现这个矩阵的代码如下:

 

var value:Number = -1;//是否位于中心点(对于偶数矩阵,这样的点有4个,而奇数矩阵则只有1个)if(Math.abs((matrixSize + 1) * 0.5 - matrixX) < 1 && Math.abs((matrixSize + 1) * 0.5 - matrixY) < 1){ value = http://www.mamicode.com/1;>

 

      如果对文本应用getConFilter(5, 0, false)滤镜,就会得到如图 4.64的效果。

 

 

图 4.64 测试对比度增强矩阵

 

      看到了一个类似于浮雕描边的效果,但总体来说,边缘还是变得比较模糊,如果把matrixSize调大,模糊的效果就更明显了(图 4.65)。

 

图 4.65 matrixSize设置为9时的效果

 

      是matrix是负数divisor引起的吗?我们不妨计算一下。

 

      这时候,外面的8个点等于-1,所以结果色等于(-8b+a)/(-7),对比度=(-8b+a)/(-7)-b=(b-a)/7,对比度仍然比原来的(a-b)减弱了不少。但是这种对比是反向的,所以a和b的色彩有发生交换的趋势,于是形成了描边。

 

      究其原因,就是负数系数的b除以负数divisor之后得到了一个比较大的正数,于是结果色中b的成分仍然较大。

 

      之前已经验证过,b>0时,对比度一定减弱,b=0时对比度不变,现在连b<0也无法把对比度增强,那看来只能在a上做文章了。

 

      现在的主要矛盾在于b系数与divisor总是同号,致使b始终是正数,无法与a拉开差距。所以,我们得把a的系数调上去,比如9,就得到矩阵,此时的divisor等于1。
9刚好等于矩阵元素的数量,但对于行数为偶数的矩阵(如4*4)来说,中心元素包含4个,所以这时候中心元素的值就不能简单地等于4*4=16了,而是要先算出周边元素的总和:-1*(4*4-4)=-12,然后中心元素的总和就应该等于13了,再平均分配到4个中心元素中,得到13/4。

 

      对于偶数方阵,总的运算公式是(1 + (matrixSize*matrixSize – 4)) / 4,因此核心算法应修改如下:

 

var value:Number = -1;if(Math.abs((matrixSize + 1) * 0.5 - matrixX) < 1 && Math.abs((matrixSize + 1) * 0.5 - matrixY) < 1){//是否位于中心点(对于偶数矩阵,这样的点有4个,而奇数矩阵则只有1个) value = http://www.mamicode.com/(matrixSize | 1) ? (matrixSize * matrixSize) : ((1 + matrixSize * matrixSize - 4) / 4);>


      修改以后,运行效果如图 4.66所示。

 

图 4.66 修正divisor后的效果

 

      的确得到了与模糊扩散相反的效果,边缘的像素往内收缩了一圈,但不是很明显,可能是由于色彩过于简单,这样的变换起到的作用不大。

 

      我们尝试把文本的色彩弄丰富一点,在不依赖素材的情况下,可以考虑将第3章的纹理滤镜用到这里,同时给文本填充上紫色#9966FF:

 

_main_txt.defaultTextFormat = new TextFormat("Microsoft YaHei", 80, 0x9966FF, true);var con:ConvolutionFilter = getConFilter(9, 0, false);var bev:BevelFilter = new BevelFilter(-17, 205, 0xFFCC00, 1, 0x660000, 1, 10, 10);_main_txt.filters = [bev];


 

      不使用ConvolutionFilter的情况下,斜角滤镜的运行效果如图 4.67所示。

 

图 4.67 用滤镜填充纹理

 

      我们对这个带纹理填充的文本应用ConvolutionFilter,即把con滤镜追加到bev之后,就得到如图 4.68的效果。

 

图 4.68 对纹理文本使用卷积滤镜

 

      很多像素被挖空了,导致我们很难从中找到啥规律出来。不过此处我们可以把preserveAlpha改成true,因为文本的色彩丰富了,不处理alpha通道也一样能看到比较明显的效果(图 4.69)。

 

 

图 4.69 设置preserveAlpha=true

 

      很多像素变成了白色(这绝非透明,因为preserveAlpha不会影响alpha通道),跟纹理的对比相当强烈,但似乎有点过度了,导致文本的底色彻底消失,所以我们不妨将矩阵的尺寸调小一点,比如3*3(图 4.70)或者5*5(图 4.71)。

图 4.70 3*3锐化矩阵的效果
 

图 4.71 5*5锐化矩阵的效果


      显然,随着矩阵尺寸的增大,色彩之间的差距逐渐被拉开,同时纹理边缘的清晰度也在不断提高,其作用与模糊恰好相反,数学上通常称之为模糊矩阵的反卷积矩阵,而图形学上则称之为锐化。

 

      在锐化矩阵中,矩阵元素总和和divisor都等于1,实际上,还有一种很特殊的卷积矩阵,矩阵元素的总和等于0,这个时候,相信大家都能猜到大概的效果了,对比度较弱的地方,将会呈现为黑色(preserveAlpha=true的情况下)。

 

      这个矩阵是,与锐化矩阵相比,它仅仅是中间点的数值少了1,所以元素的总和是0,使得图像容易出现黑色。

 

      getConFilter的写法调整为:

 

value = http://www.mamicode.com/(matrixSize | 1) ? (matrixSize * matrixSize - 1) : ((matrixSize * matrixSize - 4) / 4);>


 

      这时候,divisor将等于0,不过大家不必担心,遇到这样的情况,Adobe会自动按1来处理。

 

      运行效果如图 4.72所示。

 

图 4.72 矩阵元素总和为0

 

      单从这一例子来看,把矩阵元素总和设置为0的意义似乎不是很大,而实际上,把色彩变成纯黑或者纯白,并且抽离出纹理的边缘之后,我们就可以用它来制作素描,浮雕等Photoshop滤镜效果,如果再与混合模式配合使用,其创造力更会大大增强。

 


 

ActionScript3游戏中的图像编程(连载九十二)