图像滤镜算法之灰度图

屏幕快照 2016-02-29 下午9.36.52.png

年前偶然接触Love2D这个2D引擎,研究了一周,后来一直放下。无论从工具支持,还是开发方法上,都显得很别扭。所以一直以来都当它一个玩具。前几天偶然想到,其实Love2D用来做shader的算法试验工具还是非常不错的。因为使用lua语言,也相对简单许多,只需要关心shader的代码即可,其他的都无需关心,因为也不用它来完成游戏开发。

GPU计算中shader非常重要,这里就不再增加篇幅说明,这次来试验一个非常简单的图像算法,将一张彩色图片变为黑白图片。

如果你稍微接触过计算机成像技术,就可以发现,我们所有颜色大量使用RGB模式计算。这里RGB分别表示,红色,绿色,蓝色的颜色分量,一般值为0到255之间。三个颜色互相叠加能够产生16777216种颜色。但是人眼能够识别的颜色仅仅只有其中一部分,但不乏一些神级别的人物能够看出更多的差别。

好了,现在我们来说一下如何将一张彩色图片编程黑白图,或者说灰度图。

首先使用Love2D渲染一张彩色图片(我觉得自己还是很上镜的。。。。。)。最终效果如下:

屏幕快照 2016-02-29 下午9.24.07.png

想实现这个效果,你需要编写下面的Lua代码,并在Love2D种运行。

function love.load()
	image = love.graphics.newImage("img.jpg")
end

function love.draw()
	love.graphics.draw(image)
end

下面我们稍微加一点点代码,让图像变为灰度图。

function love.load()
	image = love.graphics.newImage("img.jpg")

	myShader = love.graphics.newShader[[
    vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){
  		vec4 pixel = Texel(texture, texture_coords );
  		number average = (pixel.r+pixel.b+pixel.g)/3.0;
  		pixel.r = average;
  		pixel.g = average;
  		pixel.b = average;
  		return pixel;
	}
  ]]
end

function love.draw()
	love.graphics.setShader(myShader)
	love.graphics.draw(image)
	love.graphics.setShader()
end

运行后,效果如下:

屏幕快照 2016-02-29 下午9.24.19.png

事实上,你还可以使用另外的方法让图像的颜色深度发生变化。例如下面这样:

屏幕快照 2016-02-29 下午9.28.54.png

屏幕快照 2016-02-29 下午9.29.34.png

屏幕快照 2016-02-29 下午9.30.01.png

三张图片的颜色深度完全不同,我只修改了shader的一部分,即可改变效果。

三个图,修改的shader代码如下:

pixel.g = pixel.r;
pixel.b = pixel.r;
pixel.r = pixel.g;
pixel.b = pixel.g;
pixel.r = pixel.b;
pixel.g = pixel.b;

从上面的代码不难看出,想然一个颜色从彩色变为灰色,我们需要让RGB三个颜色值相同即可。但值设置为多少并没有强制要求。对于一张图片种所有的颜色信息来说,只要我们按照统一的方式进行变换,则他们直接的色差会保持不变。从而保留了图片种的色差信息,这种信息能够让我们分辨出照片种的不同形状与物体。

通常情况下,我们取值可以设置为RGB三个值的平均值,这个值最为适中,而其他颜色则相对会损失原有图片种的明暗分界线的信息。

简单总结一下灰度图计算公式:

灰度颜色值 =(R+G+B)/3 R = 灰度颜色值 G = 灰度颜色值 B = 灰度颜色值