片段着色器 - 平均亮度

Rhm*_*ari 5 iphone shader opengl-es fragment-shader

是否有人知道如何在片段着色器中找到纹理的平均亮度?我可以访问RGB和YUV纹理,YUV中的Y分量是一个数组,我想从这个数组得到一个平均数.

Bra*_*son 5

我最近不得不自己做输入图像和视频帧,我作为OpenGL ES纹理.我没有为这些生成mipmap,因为我使用的是非2次幂纹理,而且你无法在iOS上的OpenGL ES 2.0中为NPOT纹理生成mipmap.

相反,我做了类似于mipmap生成的多级缩减,但稍作调整.每次降低宽度和高度都会使图像的大小减少四倍,而不是用于mipmap的两倍的正常因子.我是通过从位于四个像素的四个正方形中间的四个纹理位置进行采样来实现的,每个四个像素构成了高级图像中的4x4区域.这利用硬件纹理插值来平均四组四个像素,然后我只需平均这四个像素就可以在一个步骤中将像素减少16倍.

我在第一阶段使用RGB值的点积将图像转换为亮度,其vec3为(0.2125,0.7154,0.0721).这让我只需阅读每个后续缩小阶段的红色通道,这对iOS硬件非常有帮助.请注意,如果您已经开始使用Y通道亮度纹理,则不需要此项,但我正在处理RGB图像.

一旦图像缩小到足够小的尺寸,我就会将像素读回到CPU上,然后对剩下的几个像素进行最后一次快速迭代,得到最终的光度值.

对于640x480视频帧,这个过程在iPhone 4上产生约6毫秒的亮度值,我想我可以通过一点调整来缩短处理时间1-2毫秒.根据我的经验,这似乎比iOS设备通常比这个大小的两个二次幂图像生成mipmap更快,但我没有可靠的数字来支持它.

如果您希望看到这一点,请在我的开源GPUImage框架(以及GPUImageAverageColor超类)中查看GPUImageLuminosity类的代码.FilterShowcase示例演示了这个光度提取器的运行情况.