пиксели камеры повернуты - PullRequest
12 голосов
/ 28 июля 2011

Я хочу выполнить некоторую обработку изображений для пикселей, полученных с камеры.

Проблема в том, что пиксели камеры повернуты на 90 градусов.

Я получаю пиксели внутриМетод onPreviewFrame(byte[] data, Camera camera)

Я пытался camera.setDisplayOrientation(90);, и он отображает видео в правильной ориентации, но я все еще получаю повернутые пиксели, как указано в документации:

Это невлияет на порядок байтового массива, передаваемого в Android.Hardware.Camera.IPreviewCallback.OnPreviewFrame (Byte [], Android.Hardware.Camera), изображениях JPEG или записанных видео.1015 *

parameters.setRotation(90);
camera.setParameters(parameters);

но это не сработало.

Я использую Android 2.2

enter image description here

Верхнее изображение показывает SurfaceView при использовании camera.setDisplayOrientation(90);

Второе изображение получается внутри onPreviewFrame(byte[] data, Camera camera) из массива data.Как видите, массив data вращается.

Ответы [ 4 ]

7 голосов
/ 15 июля 2015

Хотя я немного опаздываю на вечеринку, вот метод, который я написал, который другие могут найти полезным для поворота изображения YUV420sp (NV21). Похоже, что ни один из других методов, которые я видел в SO, на самом деле не делал этого.

public static byte[] rotateNV21(final byte[] yuv,
                                final int width,
                                final int height,
                                final int rotation)
{
  if (rotation == 0) return yuv;
  if (rotation % 90 != 0 || rotation < 0 || rotation > 270) {
    throw new IllegalArgumentException("0 <= rotation < 360, rotation % 90 == 0");
  }

  final byte[]  output    = new byte[yuv.length];
  final int     frameSize = width * height;
  final boolean swap      = rotation % 180 != 0;
  final boolean xflip     = rotation % 270 != 0;
  final boolean yflip     = rotation >= 180;

  for (int j = 0; j < height; j++) {
    for (int i = 0; i < width; i++) {
      final int yIn = j * width + i;
      final int uIn = frameSize + (j >> 1) * width + (i & ~1);
      final int vIn = uIn       + 1;

      final int wOut     = swap  ? height              : width;
      final int hOut     = swap  ? width               : height;
      final int iSwapped = swap  ? j                   : i;
      final int jSwapped = swap  ? i                   : j;
      final int iOut     = xflip ? wOut - iSwapped - 1 : iSwapped;
      final int jOut     = yflip ? hOut - jSwapped - 1 : jSwapped;

      final int yOut = jOut * wOut + iOut;
      final int uOut = frameSize + (jOut >> 1) * wOut + (iOut & ~1);
      final int vOut = uOut + 1;

      output[yOut] = (byte)(0xff & yuv[yIn]);
      output[uOut] = (byte)(0xff & yuv[uIn]);
      output[vOut] = (byte)(0xff & yuv[vIn]);
    }
  }
  return output;
}
5 голосов
/ 23 сентября 2011

Может быть, вы можете выполнить обработку изображения на боковой рамке и беспокоиться о повороте только при отображении (что вы уже сделали).Если нет, вам нужно повернуть кадр по старинке.Я нашел где-то код (с небольшой модификацией), который может помочь:

// load the origial bitmap
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
       R.drawable.android);

int width = bitmap.width();
int height = bitmap.height();

// create a matrix for the manipulation
Matrix matrix = new Matrix();
// rotate the Bitmap 90 degrees (counterclockwise)
matrix.postRotate(90);

// recreate the new Bitmap, swap width and height and apply transform
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
                  width, height, matrix, true);

Это легко, потому что метод createBitmap поддерживает матричное преобразование: http://developer.android.com/reference/android/graphics/Bitmap.html#createBitmap(android.graphics.Bitmap, int, int, int, int,android.graphics.Matrix, логическое значение)

4 голосов
/ 03 апреля 2013

Если вы получаете байтовый массив YUV420, то следующий метод может повернуть его на 90 градусов.

private byte[] rotateYUV420Degree90(byte[] data, int imageWidth, int imageHeight) 
{
    byte [] yuv = new byte[imageWidth*imageHeight*3/2];
    // Rotate the Y luma
    int i = 0;
    for(int x = 0;x < imageWidth;x++)
    {
        for(int y = imageHeight-1;y >= 0;y--)                               
        {
            yuv[i] = data[y*imageWidth+x];
            i++;
        }
    }
    // Rotate the U and V color components 
    i = imageWidth*imageHeight*3/2-1;
    for(int x = imageWidth-1;x > 0;x=x-2)
    {
        for(int y = 0;y < imageHeight/2;y++)                                
        {
            yuv[i] = data[(imageWidth*imageHeight)+(y*imageWidth)+x];
            i--;
            yuv[i] = data[(imageWidth*imageHeight)+(y*imageWidth)+(x-1)];
            i--;
        }
    }
    return yuv;
}

(Обратите внимание, что это может работать, только если ширина и высота имеют коэффициент 4)

2 голосов
/ 01 мая 2012

Вы можете повернуть необработанные данные следующим образом:

// Rotate the data for Portait Mode
byte[] rotatedData = new byte[data.length];
for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++)
        rotatedData[x * height + height - y - 1] = data[x + y * width];
}

Где «ширина» и «высота» - это предварительно установленные размеры для изображения предварительного просмотра, используя:

Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(width, height);
camera.setParameters(parameters);

Затем вы можете соответствующим образом использовать повернутые данные.

Я использовал этот метод только для сканирования QR-кода, и он, кажется, работает отлично.Не уверен, как это может повлиять на другие приложения.

...