【问题标题】:Simultaneous camera preview and processing同步相机预览和处理
【发布时间】:2013-08-26 16:58:25
【问题描述】:

我正在设计一个具有 OpenGL 处理管道(着色器集合)并同时要求最终用户查看未处理相机预览的应用程序。

举个例子,假设您想向用户显示相机预览,同时计算从相机接收到的场景中红色对象的数量,但您使用的任何着色器都可以计算对象,例如用户不应该看到色调过滤等。

我该如何正确设置?

我知道我可以设置摄像头预览,然后在回调中接收 YUV 格式的摄像头帧数据,然后将其转储到 OpenGL 纹理并以这种方式处理帧,但是,这会带来性能问题。我必须将数据从相机硬件往返传输到 VM,然后将其传递回 GPU 内存。我正在使用SurfaceTexture 直接以 OpenGL 可理解的格式从相机获取数据,并将其传递给我的着色器以解决此问题。

我以为我可以向最终用户显示相同的未处理SurfaceTexture,但TextureView 没有构造函数或设置器,我可以将SurfaceTexture 传递给我希望它呈现。它总是创建自己的。

这是我当前设置的概述:

  • GLRenderThread:此类从 Thread 扩展,设置 OpenGL 上下文、显示等,并使用 SurfaceTexture 作为表面(eglCreateWindowSurface 的第三个参数)。
  • GLFilterChain:对输入纹理执行检测的着色器集合。
  • 相机:使用单独的 SurfaceTexture 作为 GLFilterChain 的输入并抓取相机的预览
  • 最后是一个显示 GLRenderThread 的 SurfaceTexture 的 TextureView

显然,通过这种设置,我向用户展示了处理后的帧,这不是我想要的。此外,帧的处理不是实时的。基本上,我通过链运行来自相机的输入一次,一旦完成所有过滤器,我调用updateTexImage 以从相机中获取下一帧。我在 Nexus 4 上的处理速度约为每秒 10 帧。

我觉得我可能需要使用 2 个 GL 上下文,一个用于实时预览,一个用于处理,但我不确定。我希望有人能把我推向正确的方向。

【问题讨论】:

标签: android opengl-es


【解决方案1】:

你能上传一些你正在使用的代码吗?

您也许可以在为最初用于显示预览的表面视图创建并绑定到表面视图的纹理上调用 glDrawArrays,然后刷新它并将单独的纹理与您的其他纹理绑定以进行分析?像

GLES20.glUseProgram(simpleProgram);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textures[0]);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

GLES20.glUseProgram(crazyProgram);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textures[1]);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

您的相机的预览表面纹理绑定到纹理[0],然后为纹理[1] 创建单独的表面纹理

也许?

【讨论】:

  • 我的代码跨越了许多类,但我会尝试为问题添加一个摘要。所以回顾一下你的想法:simpleProgram 只是将 gl_FragColor 设置为输入像素的值。 crazyProgram 进行实际处理。我根本不会使用 TextureView,而是使用 GLSurfaceView 向用户显示预览。我如何将纹理[0] 复制到纹理[1] 中,如何实时保持相机预览?根据我的理解,在我使用 crazyProgram 之前,我必须绑定一个非默认帧缓冲区,这意味着下一个相机预览必须等到 crazyProgram 完成所有处理。
【解决方案2】:

除非您的处理速度比实时速度慢,否则答案很简单:只需保持原始相机纹理不变,将处理后的图像计算为不同的纹理并在单个 GLView 中并排显示给用户.保持一个线程,因为所有的处理都发生在 GPU 上。多线程只会使问题复杂化。

处理步骤的数量并不重要,因为可以有任意数量的中间纹理(另见乒乓)永远不会显示给用户 - 没有人强迫你这样做。

实时的概念在这里可能令人困惑。只需将帧视为不可分割的时间快照。通过这样做,您将忽略图像从相机到屏幕所需的延迟,但如果您可以将其保持在交互式帧速率(例如每秒至少 20 帧),那么这主要是忽略。

另一方面,如果您的处理速度较慢,您需要选择在相机输入中引入延迟并仅每第 N 帧处理一次,或者交替实时显示每个相机帧并让下一个处理帧滞后。为此,您可能需要两个单独的渲染上下文来启用异步处理,这在 Android 上可能很难做到(或者可能就像创建第二个 GLView 一样简单,因为您可以在上下文之间没有数据共享的情况下生活)。

【讨论】:

    猜你喜欢
    • 2012-03-20
    • 2015-09-04
    • 1970-01-01
    • 2014-10-17
    • 1970-01-01
    • 2021-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多