Пиксели камеры вращаются
Я хочу сделать некоторую обработку изображения в пикселях, полученных из камеры.
Проблема в том, что пиксели с камеры вращаются на 90 градусов.
Im получает пиксели внутри метода onPreviewFrame(byte[] data, Camera camera)
Я попробовал camera.setDisplayOrientation(90);
, и он отображает видео в правильной ориентации, но я все еще получаю повернутые пиксели, как указано в документации:
Это не влияет на порядок массива байтов, переданный в Android.Hardware.Camera.IPreviewCallback.OnPreviewFrame(байт [], Android.Hardware.Camera), изображения JPEG или записанные видеоролики.
Я также пробовал:
parameters.setRotation(90);
camera.setParameters(parameters);
но это не сработало.
Я использую Android 2.2
![enter image description here]()
Верхнее изображение показывает SurfaceView при использовании camera.setDisplayOrientation(90);
Второе изображение получено внутри onPreviewFrame(byte[] data, Camera camera)
из массива data
. Как видите, массив data
вращается.
Ответы
Ответ 1
Пока я немного опаздываю на вечеринку, здесь метод, который я написал, может оказаться полезным для поворота изображения 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;
}
Ответ 2
Возможно, вы можете выполнить обработку изображения на боковом кадре и только беспокоиться о вращении, когда вы его показываете (что вы уже сделали). Если нет, вам нужно повернуть рамку старомодным способом. Я нашел код где-нибудь (с небольшой модификацией), который может помочь:
// 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, boolean)
Ответ 3
Если вы получаете массив байтов 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)
Ответ 4
Вы можете вращать необработанные данные следующим образом:
// 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-кода, и он работает отлично. Не знаете, как это может повлиять на другие приложения.