图像视频滤镜算法---颜色滤镜

 

承接上一篇滤镜初识,本文将介绍第一种滤镜:颜色滤镜。

颜色滤镜

颜色滤镜即调色滤镜,也是最常见的滤镜,任何通过调节图像像素值的亮度、对比度、饱和度、色相等等方法,得到的不同于原图像颜色的效果,都统称为颜色滤镜。

我们来做一个颜色增强滤镜,以此说明,方便大家更好的理解。

如下图所示,我们对一副图在PS中进行饱和度调整(饱和度提高41):

那么,我们在这个过程中,算法实际上做了对一副图S进行饱和度+41的操作,我们使用这个操作对其他图进行处理,那么这个操作就是一个颜色增强滤镜。

我们编程实现这个滤镜操作:

  • 1,PS饱和度调节算法原理

假设原图像素P,RGB颜色空间对应颜色分量为R/G/B,饱和度调整参数为saturation,范围[-100,100];

原理伪代码如下:

  • 2,C语言实现
int f_Stauration(unsigned char* srcData, int width, int height, int stride, int saturation)
{
	unsigned char* pSrc = srcData;
	int r, g, b, rgbMin, rgbMax;
	int k = saturation / 100.0f * 128;
	int alpha = 0;
	for(int j = 0; j < height; j++)
	{
		for(int i = 0; i < width; i++)
		{
			r = pSrc[2];
			g = pSrc[1];
			b = pSrc[0];
			rgbMin = MIN2(MIN2(r, g), b);
			rgbMax = MAX2(MAX2(r, g), b);
			int delta = (rgbMax - rgbMin);
			int value = (rgbMax + rgbMin);
			if(delta ==0)
			{
				pSrc += 4;
				continue;
			}			
			int L = value >> 1;
			int S = L < 128 ? (delta << 7) / value : (delta << 7) / (510 - value);
			if(k >= 0)
			{
				alpha = k + S >= 128 ? S : 128 - k;
				alpha = 128 * 128 / alpha - 128;
			}
			else
				alpha = k;
			r = r + ((r - L) * alpha >> 7);
			g = g + ((g - L) * alpha >> 7);
			b = b + ((b - L) * alpha >> 7);
			pSrc[0] = CLIP3(b, 0, 255);
			pSrc[1] = CLIP3(g, 0, 255);
			pSrc[2] = CLIP3(r, 0, 255);
			pSrc += 4;
		}
	}
	return 0;
}
  • 3,颜色增强滤镜实现
int f_ColorFilter(unsigned char* srcData, int width, int height, int stride)
{
	return f_Saturation(srcData, width, height, stride, 41);
}

效果图如下:

上述过程实际上就是一个完整的制作颜色滤镜的过程,大家可以了解到什么是颜色滤镜,我们通过PS模拟滤镜效果,然后编程实现这个滤镜效果,用这个算法程序去处理其他的用户照片,这个算法程序就叫做一个滤镜算法,这里分类为颜色滤镜算法。

了解了颜色滤镜之后,我们来讲解一下LUT滤镜。

LUT滤镜

LUT是Look Up Table的缩写,俗称为颜色查找表。颜色查找表有1D LUT、2D LUT、3D LUT三种。

  • 1D LUT

1D LUT只能控制gamma值、RGB平衡(灰阶)和白场(white point),形如下图一个256x1大小的1D LUT。

这张图中记录了0-255的像素映射值,我们通过查表的方式来获取对应RGB值的映射值,由于一个RGB对应一个输出,每个输出之间是相互独立的,因此,这种1D LUT只能实现gamma值,线性对比度亮度调节等等简单的功能,下面是使用1D LUT进行亮度调节的效果:

1D LUT也有着很多应用,比如Instagram app,它的滤镜实现中,就使用了很多1D LUT,有兴趣的可以去了解一下。

  • 2D LUT

2D LUT可以控制颜色饱和度和亮度,在完整的色彩空间中进行线性缩放,但是也无法控制颜色的非线性变换,它与1D LUT的区别就是采用了二维坐标来记录颜色的映射关系。

我们以图层混合为例,2D LUT的一种样例图如下:

这种2D LUT的左上角为黑色,右下角为白色,大小为256x256,分别对应图像像素的RGB值范围,使用中假设像素值为M,那么对应到LUT样例图中M行M列的位置,该位置的映射值就是像素M对应的效果值。我们使用该样例图来实现正片叠底的图层混合效果如下:

上面所述这种2D LUT目前在图像类的手机app中非常常见,比如美图秀秀等,对于一些图层混合,我们不需要使用复杂的程序计算,也不需要使用3D LUT来占用更多的资源,直接使用2D LUT,即可满足实时处理的速度需求和资源空间节省的需求。

  • 3D LUT

3D LUT非常适合用于精确的颜色校准工作,因为它们能够处理所有的显示校准的问题,从简单的gamma值、颜色范围和追踪错误,到修正高级的非线性属性、颜色串扰(去耦)、色相、饱和度、亮度等。

RGB 可以表示的颜色数量为 256*256*256 = 16,777,216,如果要记录每种颜色的映射结果,那么颜色表需要 一千六百多万条记录,这显然无法应用到实际的工程中。为了简化起见,Lev Zelensky发表了一个基准颜色表,将每相近的 4 种颜色采用一条记录存储,这样颜色表只需要64 * 64 * 64 = 262,144 条记录。这个表如下:

目前这种LUT的应用最为广泛,因为他可以记录各种非线性的颜色变换,对于颜色滤镜中的图像处理而言,可以大大简化程序逻辑与算法复杂度。

这种LUT的大小为512X512,分为64个大小为64X64的颜色方格,它的颜色关系如下:

假设像素P的三个分量为R/G/B

对于每个小方格,X方向代表R像素值,Y方向代表了G像素值,该方格的位置代表了B像素值。

查找原理

举例说明,对于像素P(200,0,100),R=200,G=0,B=100,P在LUT中的位置为D:

我们首先根据B=100来确定我们要找的R和G是在哪一个小方格中,我们设定左上角的第一个小方格为0,从左到右,从上到下依次排列64个小方格,对应的B值依次为i*4,范围正好在0-255之内,实际上是0-252,最大值63*4=252,那么,根据B计算出我们要找的是哪个方格,现在B=100,B/4=25,因此,在第26个小方格,也就是LUT的第四行第二列。

我们在第26个小方格中寻找最终的位置D,R=200,我们在该小方格水平方向上计算,200/4=50,因此,D位置的X坐标为50,同理,G=0,那么Y坐标为0;

这样我们就找到了像素P(200,0,100)在LUT中的位置:第四行第二列的小方格中,坐标(50,0);

于是,P在LUT中映射后的结果值就是D对应的RGB值;

上述过程就是LUT的颜色映射过程,即查表过程。

我们使用C语言来实现LUT的查表如下:

 int  f_Filter512(unsigned  char*  srcData,  int  width  ,int  height,  int  stride,  unsigned  char*Map)
{
    int  i,  j,  r,  g,  b,  offset,  pos,  nx,  ny,  k;
    unsigned  char*  pSrc  =  srcData;
    offset  =  stride  -  (width  <<  2);
    for(j  =  0;  j  <  height;  j++)
    {
        for(i  =  0;  i  <  width;  i++)
        {
            b  =  pSrc[0];
            g  =  pSrc[1];
            r  =  pSrc[2];
            k  =  (b  >>  2);
            nx  =  (int)(r  >>  2)  +  ((k  -  ((k  >>  3)  <<  3))  <<  6);
            ny  =  (int)(((b  >>  5)  <<  6)  +  (g  >>  2));
            pos  =  (nx  <<  2)  +  (ny  <<  11);
            pSrc[0]  =  Map[pos];
            pSrc[1]  =  Map[pos  +  1];
            pSrc[2]  =  Map[pos  +  2]; 
            pSrc  +=  4;
        }
        pSrc  +=  offset;
    }
    return    0;
};

该代码中,Map数据即为512X512的LUT数据,此处格式统一为32位BGRA数据。

滤镜效果图举例如下:

512X512大小的LUT使用方法总结如下:

  1. 使用PS调色或者使用程序编程实现所需调色效果;
  2. 使用1中的PS动作操作或者是程序算法处理Fig.7中的LUT样例图,得到滤镜LUT;
  3. 使用本文提供的C代码接口对其他图像进行LUT调色;

3D LUT滤镜实际使用中并非指定的某一种,也可以根据自己需求,在正确的理论基础之上,创造更多的LUT样例图,目前,我们经常看到的如下几种:

每一种的查表原理都是类似的,大家可以自行推导即可,这里提醒一点,512X512大小的LUT是不需要插值处理的,因为每种颜色屏蔽了4位之后,实际上并不影响我们的感官效果,如果LUT大小小于了这个尺寸,那么,在使用过程中是需要进行插值运算才能达到不影响感官的效果的,这一点请注意一下。

上面就是本节内容,希望大家能对颜色滤镜有个清晰的认识!

本人QQ:1358009172

  • 8
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Trent1985

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值