使用OpenGL的Android相机帧处理

Posted

技术标签:

【中文标题】使用OpenGL的Android相机帧处理【英文标题】:Android camera frame processing using OpenGL 【发布时间】:2016-01-18 20:44:42 【问题描述】:

我正在尝试在相机预览帧上应用人脸检测。我正在使用 OpenGL 和 OpenCV 在运行时处理这些相机帧。

@Override
    public void onDrawFrame(GL10 unused) 
        if (VERBOSE) 
            Log.d(TAG, "onDrawFrame tex=" + mTextureId);
        

        mSurfaceTexture.updateTexImage();
        mSurfaceTexture.getTransformMatrix(mSTMatrix);

        // TODO: need to implement
        //JniCppManager.processFrame();

        drawFrame(mTextureId, mSTMatrix);

我正在尝试实现 processFrame() 的 c++ 实现。如何从转换矩阵中获取 C++ 中的 Mat 对象?谁能给我一些解决方案的指针。

【问题讨论】:

getTransformMatrix() 中的值是一个 4x4 矩阵,以列优先顺序表示为 16 元素线性数组。 OpenCV Mat 类当然可以代表这一点,但不清楚您是在尝试获取(通常是微不足道的)转换矩阵还是像素数据本身。 感谢 Fadden 的回复。我的最终目标是根据图像识别覆盖静态图像。例如在特定地标上覆盖小胡子。我认为为此我需要像素数据。 【参考方案1】:

您的管道目前是:

相机(产生框架) SurfaceTexture(接收帧,转换为 GLES“外部”纹理) [缺少的东西] 传递给 C++ 的 RGB 字节数组

您需要为 [缺少的东西] 做的是将像素渲染到屏幕外 pbuffer 并使用glReadPixels() 将它们读回。您可以从用 Java 或本机编写的代码执行此操作;对于前者,您希望将它们读入“直接”字节缓冲区,以便您可以轻松地从本机代码访问像素。 GLES 使用的 EGL 上下文保存在线程本地存储中,因此在 GLSurfaceView 渲染线程上运行的本机代码将能够访问它。

这方面的一个例子可以在 bigflake ExtractMpegFramesTest 中找到,主要区别在于它从视频而不是相机中抓取帧。

对于 API 19+,如果您可以处理 YV12 或 NV21 而不是 RGB 的帧,您可以将相机输入到 ImageReader 并访问数据而无需复制/转换它。

【讨论】:

感谢 Fadden,您的回答非常有帮助!

以上是关于使用OpenGL的Android相机帧处理的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL没有将最近的片段绘制到相机

使用 SurfaceTexture 和 OpenGL 修改相机输出

OpenGL中的单色渲染到帧缓冲区对象?

如何使用带有 OpenGL ES 的 android 相机工作?

使用 OpenGL 更快的相机预览?

Android 在相机框架上应用效果