图像查表法原理,网上有很多资料有介绍,本文主要参考了
https://blog.csdn.net/danffer1985/article/details/78692992
这篇博客,本文仅做自己的知识梳理和记录。如博主有意见可留言。
lookup查表法,简而言之就是,根据原图的像素的RGB值,找到颜色表上的对应位置,然后用颜色表上的RGB值替换原图上的像素的RGB值。基本过程如下:
首先讲一下颜色表是怎么来的。
先上图
lookup.png
这张表对应的是没有经过处理的RGB色彩空间。你可以尝试下,用这张图来查表的话,输出的图像和原图是一样的。
这张表其实是标准RGB立方体色彩空间转换而来的,标准RGB空间如下:
图片来自https://www.cnblogs.com/Free-Thinker/p/5569792.html
它是把三维的色彩空间,沿着蓝色到黑色的方向,像切豆腐一样,一片一片切下来,切了64刀,每一刀得到一个正方形切面(也就是lookup图的一个小正方形),平摊到二维平面上的。所以我们看到,lookup图的左上角的小方块,对应的是RGB空间图右侧的立方体的右上侧的那一面。
我们再看lookup.png这张图,每个小正方形,沿着x轴方向是红色的渐变(从0到255),沿着y轴方向是绿色的渐变(从0到255)。而蓝色的渐变,实际上它是在第三维,经过上面说的从三维立方体切割平铺到了64个小正方形中了。整张图的分辨率是512x512,每个小正方形的分辨率就是512 / 8 = 64,那么渐变的精度就是256 / 64 = 4。
接下来我们分析一下GPUImageLookupFilter的着色器代码,看看如何查表的。代码如下:
NSString *const kGPUImageLookupFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2; // TODO: This is not used
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2; // lookup texture
uniform lowp float intensity;
void main()
{
highp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
//蓝色通道,textureColor.b的范围为(0,1),blueColor范围为(0,63)
highp float blueColor = textureColor.b * 63.0;
//quad1为小于且最靠近要查找颜色所在位置的小正方形
highp vec2 quad1;
quad1.y = floor(floor(blueColor) / 8.0);
quad1.x = floor(blueColor) - (quad1.y * 8.0);
//quad2为大于且最靠近要查找颜色所在位置的小正方形
highp vec2 quad2;
quad2.y = floor(ceil(blueColor) / 8.0);
quad2.x = ceil(blueColor) - (quad2.y * 8.0);
highp vec2 texPos1;
//因为一行有8个小正方形,所以小正方形的边长,转换为纹理坐标时,就是0.125。quad1的位置就是quad1.x * 0.125和quad1.y * 0.125。
//后面0.5/512.0 + ((0.125 - 1.0/512.0) * r);这项,可以写成0.125*r + (0.5-r)/512,实际上就是红色通道对应的位置。绿色通道同理。
texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);
highp vec2 texPos2;
//quad2和quad1差不多
texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);
lowp vec4 newColor1 = texture2D(inputImageTexture2, texPos1);
lowp vec4 newColor2 = texture2D(inputImageTexture2, texPos2);
//真正的颜色在newColor1和newColor2之间。fract是取分数部分。
lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));
gl_FragColor = mix(textureColor, vec4(newColor.rgb, textureColor.w), intensity);
}
);
注释貌似不能很好的解释清楚,再加一张图吧,别的就无能为力了...
网友评论