iOS GLSL。有没有办法使用GLSL着色器创建图像直方图?

iOS GLSL。有没有办法使用GLSL着色器创建图像直方图?,ios,image-processing,glsl,histogram,Ios,Image Processing,Glsl,Histogram,在StackOverflow的其他地方,有人问了一个关于depthbuffer直方图的问题 我正在编写一个iOS图像处理应用程序,我对这个问题很感兴趣,但不清楚提供的答案。那么,是否可以通过GLSL使用GPU创建图像直方图?是的,可以。这显然不是最好的方法,但它确实是iOS中可用的最好的方法,因为OpenCL不受支持。您将失去优雅,您的代码可能不会那么简单,但几乎所有OpenCL功能都可以通过着色器实现 如果有帮助,DirectX11附带了一个FFT示例,用于计算着色器。请参阅DX11 Augu

在StackOverflow的其他地方,有人问了一个关于depthbuffer直方图的问题


我正在编写一个iOS图像处理应用程序,我对这个问题很感兴趣,但不清楚提供的答案。那么,是否可以通过GLSL使用GPU创建图像直方图?

是的,可以。这显然不是最好的方法,但它确实是iOS中可用的最好的方法,因为OpenCL不受支持。您将失去优雅,您的代码可能不会那么简单,但几乎所有OpenCL功能都可以通过着色器实现


如果有帮助,DirectX11附带了一个FFT示例,用于计算着色器。请参阅DX11 August SDK发行说明。

是的,虽然在iOS上比您想象的更具挑战性。这是一个完全在GPU上生成并绘制的红色柱状图,与实时视频源相对应:

在这个问题上,你的链接是一个很好的起点。建议使用散射来建立图像中颜色通道的直方图。散射是一个过程,在该过程中,将点栅格传递给顶点着色器,然后让该着色器读取该点的颜色。然后将该点处所需颜色通道的值写入X坐标(Y和Z坐标为0)。然后,片段着色器在目标中的该坐标处绘制一个1像素宽的半透明点

该目标是一个1像素高、256像素宽的图像,每个宽度位置代表一个颜色单元。通过写出具有低alpha通道(或低RGB值)的点,然后使用加法混合,可以根据特定颜色值在图像中出现的次数为每个箱子累积更高的值。然后可以读取这些直方图像素以供以后处理

在iOS上的着色器中执行此操作的主要问题是,尽管如此,Apple明确表示顶点着色器中的纹理读取在iOS上不起作用。我在我所有的iOS 5.0设备上都试过了,但没有一台能够在顶点着色器中执行纹理读取(屏幕变黑,没有引发GL错误)

为了解决这个问题,我发现我可以读取输入图像的原始像素(通过
glReadPixels()
或),并将这些字节作为带有GL_UNSIGNED_字节类型的顶点数据传入。以下代码实现了这一点:

glReadPixels(0, 0, inputTextureSize.width, inputTextureSize.height, GL_RGBA, GL_UNSIGNED_BYTE, vertexSamplingCoordinates);

[self setFilterFBO];

[filterProgram use];

glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);

glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
glEnable(GL_BLEND);

glVertexAttribPointer(filterPositionAttribute, 4, GL_UNSIGNED_BYTE, 0, (_downsamplingFactor - 1) * 4, vertexSamplingCoordinates);
glDrawArrays(GL_POINTS, 0, inputTextureSize.width * inputTextureSize.height / (CGFloat)_downsamplingFactor);

glDisable(GL_BLEND);
在上面的代码中,您会注意到我使用了一个步幅来只对图像像素的一小部分进行采样。这是因为您可以写出的最低不透明度或灰度级别为1/256,这意味着当图像中的255个像素具有该颜色值时,每个箱子都会变为最大值。因此,我必须减少处理的像素数,以便在这个有限的窗口内显示直方图的范围。我正在寻找一种方法来扩展这个动态范围

从顶点着色器开始,用于执行此操作的着色器如下所示:

 attribute vec4 position;

 void main()
 {
     gl_Position = vec4(-1.0 + (position.x * 0.0078125), 0.0, 0.0, 1.0);
     gl_PointSize = 1.0;
 }
最后使用片段着色器:

 uniform highp float scalingFactor;

 void main()
 {
     gl_FragColor = vec4(scalingFactor);
 }
在我的开源框架中可以找到一个有效的实现。抓取并运行FilterShowcase示例,自己查看直方图分析和绘图


这一实现存在一些性能问题,但这是我能想到的在iOS上的GPU上实现这一点的唯一方法。我愿意接受其他建议。

感谢您的快速响应。干杯。你确定那篇文章相关吗?他们在哪里使用着色器计算柱状图?我只是指出,因为它涉及两个主题,并用粗体表示,这只是为了让他开始。也许这是一个坏主意,即使在陈述之后。我应该删除它吗?我只是想确保那篇文章没有遗漏什么。我自己也在做一个基于OpenGL ES着色器的直方图实现,但那篇文章中没有任何内容接近我所做的,所以我想我可能错过了一些细节。如果它只是对GLSL的广泛引用,那么在这种情况下可能根本没有帮助。汤米在上述相关问题中的回答是一个更好的起点。当我自己的实现正常工作时,我会回答。我正在尝试准备一个简单的示例。非常酷。只是一个小小的吹毛求疵:值
0.0078125
将值箱偏移一个灰度值。使用(2.0/255.0=0.00784313725)将255映射到2(减去1之前)。