Как конвертировать android.media.Image в растровый объект?

В android, я получаю объект Image отсюда https://inducesmile.com/android/android-camera2-api-example-tutorial/ в этом учебнике. Но я хочу теперь перебирать значения пикселей, знает ли кто-нибудь, как я могу это сделать? Должен ли я преобразовать его в что-то еще и как я могу это сделать?

Спасибо

Ответ 1

Если вы хотите все петли по всему пикселю, вам нужно сначала преобразовать его в объект Bitmap. Теперь, когда я вижу в исходном коде, что он возвращает Image, вы можете напрямую преобразовать байты в растровое изображение.

    Image image = reader.acquireLatestImage();
    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
    byte[] bytes = new byte[buffer.capacity()];
    buffer.get(bytes);
    Bitmap bitmapImage = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, null);

Затем, как только вы получите объект bitmap, вы можете теперь перебирать все пиксели.

Ответ 2

https://docs.oracle.com/javase/1.5.0/docs/api/java/nio/ByteBuffer.html#get%28byte[]%29

Согласно документации Java: метод buffer.get передает байты из этого буфера в заданный массив назначения. Вызов этого метода в форме src.get(a) ведет себя точно так же, как и вызов

 src.get(a, 0, a.length) 

Ответ 3

На самом деле у вас есть два вопроса в одном 1) Как вы зацикливаете бросать android.media.Image пикселей 2) Как конвертировать android.media.image в растровое изображение

1-е легко. Обратите внимание, что объект Image, который вы получаете с камеры, это просто YUV-кадр, где компоненты Y и U + V находятся в разных плоскостях. Во многих случаях обработки изображений вам нужна только плоскость Y, то есть серая часть изображения. Чтобы получить его, я предлагаю следующий код:

    Image.Plane[] planes = image.getPlanes();
    int yRowStride = planes[0].getRowStride();
    byte[] yImage = new byte[yRowStride];
    planes[0].getBuffer().get(yImage);

Байт-буфер yImage - это фактически серые пиксели кадра. Таким же образом вы можете получить детали U + V. Обратите внимание, что они могут быть сначала U, а V после, или V и после него U, и, возможно, являются взаимозаменяемыми (это типичный случай с Camera2 API). Таким образом, вы получаете UVUV....

В целях отладки я часто записываю фрейм в файл и пытаюсь открыть его с помощью приложения Vooya (Linux), чтобы проверить формат.

2-й вопрос немного сложнее. Чтобы получить объект Bitmap, я нашел пример кода из проекта TensorFlow здесь. Наиболее интересная функция для вас - "convertImageToBitmap", которая вернет вам значения RGB.

Чтобы преобразовать их в настоящий битмап, сделайте следующее:

  Bitmap rgbFrameBitmap;
  int[] cachedRgbBytes;
  cachedRgbBytes = ImageUtils.convertImageToBitmap(image, cachedRgbBytes, cachedYuvBytes);
  rgbFrameBitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
  rgbFrameBitmap.setPixels(cachedRgbBytes,0,image.getWidth(), 0, 0,image.getWidth(), image.getHeight());

Примечание. Существует больше вариантов преобразования YUV в кадры RGB, поэтому, если вам нужно значение пикселей, возможно, растровое изображение - не лучший выбор, поскольку оно может потреблять больше памяти, чем нужно, чтобы просто получить значения RGB.

Ответ 4

1-Сохраните путь к файлу изображения в виде строковой переменной. Чтобы декодировать содержимое файла изображения, вам нужен путь к файлу, сохраненный в вашем коде в виде строки. Используйте следующий синтаксис в качестве руководства:

String picPath = "/mnt/sdcard/Pictures/mypic.jpg";

2 - Создать растровый объект и использовать BitmapFactory:

Bitmap picBitmap;
Bitmap picBitmap = BitmapFactory.decodeFile(picPath);