Обрабатывать каждый кадр камеры как растровое изображение с помощью OpenGL - PullRequest
0 голосов
/ 28 февраля 2019

У меня есть приложение, в котором я хочу обработать каждый данный кадр с камеры, чтобы сделать кое-что из 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.

1 Ответ

0 голосов
/ 28 февраля 2019

Многие современные графические процессоры могут декодировать YUV изначально;вопрос заключается в том, как получить поверхность YUV в OpenGL ES, поскольку обычно это не то, что делает Open GL ES.Большинство операционных систем (включая Android) позволяют импортировать внешние поверхности непосредственно в OpenGL ES через расширение EGL_image_external, и эти внешние поверхности могут быть помечены как YUV с автоматическим преобразованием цвета.

Еще лучше, это всеобрабатывается ноль-копия;буфер камеры можно напрямую импортировать и получать к нему доступ с помощью графического процессора.

Этот механизм Android для импорта осуществляется через класс SurfaceTexture, и его необходимое описание описано здесь: https://source.android.com/devices/graphics/arch-st

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...