【问题标题】:Process every camera frame as Bitmap with OpenGL使用 OpenGL 将每个相机帧处理为位图
【发布时间】:2019-03-01 01:04:12
【问题描述】:

我有一个应用程序,我想在其中处理来自相机的每个给定帧以执行一些 ARCore 工作。所以我有一个实现GLSurfaceView.Renderer 的类,在这个类中我有onDrawFrame(GL10 gl) 方法。在此方法中,我想使用 Android 位图,因此我调用此代码从当前帧获取位图:

private Bitmap getTargetImageBitmapOpenGL(int cx, int cy, int w, int h) {
    try {

      if (currentTargetImageBitmap == null) {
        currentTargetImageBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);

        byteBuffer = ByteBuffer.allocateDirect(w * h * 4);
        byteBuffer.order(ByteOrder.nativeOrder());
      }

      // cy = height - cy;

      if ((cx + w / 2) > width) {
        Log.e(TAG, "TargetImage CenterPoint invalid A: " + cx + " " + cy);
        cx = width - w / 2;
      }

      if ((cx - w / 2) < 0) {
        Log.e(TAG, "TargetImage CenterPoint invalid B: " + cx + " " + cy);
        cx = w / 2;
      }

      if ((cy + h / 2) > height) {
        Log.e(TAG, "TargetImage CenterPoint invalid C: " + cx + " " + cy);
        cy = height - h / 2;
      }

      if ((cy - h / 2) < 0) {
        Log.e(TAG, "TargetImage CenterPoint invalid D: " + cx + " " + cy);
        cy = h / 2;
      }

      int x = cx - w / 2;
      int y = cy - h / 2;

      GLES20.glReadPixels(x, y, w, h, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE,
          byteBuffer);

      IntBuffer currentTargetImagebuffer = byteBuffer.asIntBuffer();

      currentTargetImagebuffer.rewind();
      currentTargetImageBitmap.copyPixelsFromBuffer(currentTargetImagebuffer);

      return currentTargetImageBitmap;

    } catch (Exception e) {
      e.printStackTrace();
    }

    return null;
  }

这个方法大约需要 90 毫秒,这对于实时处理每个传入的帧肯定太慢了,我需要这样做,因为onDrawFrame(GL10 gl) 方法也会将此帧绘制到表面视图。知道为什么这么慢吗?如果我只能读取每隔一帧的像素,但将每一帧都绘制到我的 SurfaceView 上,这也足够了。我尝试调用AsyncTask.execute()中显示的方法,但是另一个线程无法通过GLES20.glReadPixels()方法读取,因为它不是GL线程。

【问题讨论】:

    标签: java android opengl-es


    【解决方案1】:

    许多现代 GPU 可以原生解码 YUV;问题是如何让 YUV 表面进入 OpenGL ES,因为这通常不是 Open GL ES 所做的事情。大多数操作系统(包括 Android)允许您通过 EGL_image_external 扩展直接将外部表面导入 OpenGL ES,并且这些外部表面可以标记为具有自动颜色转换的 YUV。

    更好的是这都是零拷贝处理的;相机缓冲区可以直接被GPU导入和访问。

    这种导入的Android机制是通过SurfaceTexture类,这里描述了必要的用法:https://source.android.com/devices/graphics/arch-st

    【讨论】:

      猜你喜欢
      • 2016-01-18
      • 1970-01-01
      • 1970-01-01
      • 2011-05-13
      • 1970-01-01
      • 2011-08-03
      • 2010-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多