相机像素旋转

发布于 2024-11-27 05:12:54 字数 809 浏览 0 评论 0原文

我想对从相机获得的像素进行一些图像处理。

问题在于相机的像素旋转了 90 度。

我在方法 onPreviewFrame(byte[] data, Camera camera) 中获取像素,

我尝试了 camera.setDisplayOrientation(90); 并且它以正确的方向显示视频,但是我仍然收到文档中所述的旋转像素:

这不会影响传入的字节数组的顺序 Android.Hardware.Camera.IPreviewCallback.OnPreviewFrame(Byte[], Android.Hardware.Camera)、JPEG 图片或录制的视频。

我也尝试过:

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

但是没有用。

我正在使用 android 2.2

在此处输入图像描述

使用 camera.setDisplayOrientation(90) 时顶部图像显示 SurfaceView ;

第二张图像是从 data 数组中的 onPreviewFrame(byte[] data, Camera camera) 中获取的。正如您所看到的,data 数组已旋转。

I want to do some image processing to the pixels gotten from the camera.

The problem is that the pixels from the camera are rotated 90 degrees.

Im getting the pixels inside the method onPreviewFrame(byte[] data, Camera camera)

I tried camera.setDisplayOrientation(90); and it displays the video in the correct orientation but I am still receiving the rotated pixels as stated in the documentation:

This does not affect the order of byte array passed in
Android.Hardware.Camera.IPreviewCallback.OnPreviewFrame(Byte[],
Android.Hardware.Camera), JPEG pictures, or recorded videos.

I also tried:

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

but that did not work.

I'm using android 2.2

enter image description here

Top image shows the SurfaceView when using camera.setDisplayOrientation(90);

The second image is gotten inside onPreviewFrame(byte[] data, Camera camera) from the data array. As you can see the data array comes rotated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

↙温凉少女 2024-12-04 05:12:54

虽然我来得有点晚了,但这里有一个我写的方法,其他人可能会发现它对于旋转 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;
}

While I'm a bit late to the party, here's a method I wrote that others might find useful to rotate a YUV420sp (NV21) image. None of the other methods I saw on SO seemed to actually do it.

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;
}
镜花水月 2024-12-04 05:12:54

也许您可以在横向框架上执行图像处理,并且仅在显示它时担心旋转(您已经完成了)。如果没有,您需要以老式方式旋转框架。我在某处找到了一些代码(稍加修改)可能会有所帮助:

// 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,布尔)

Maybe you can perform your image processing on the sideways frame, and only worry about rotation when you display it (which you have already done). If not, you need to rotate the frame the old fashioned way. I found some code somewhere (with a little modification) that might help:

// 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);

This is easy because the createBitmap method supports a matrix transform:
http://developer.android.com/reference/android/graphics/Bitmap.html#createBitmap(android.graphics.Bitmap, int, int, int, int, android.graphics.Matrix, boolean)

倦话 2024-12-04 05:12:54

如果您收到 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 倍时,这才可能有效)

If you are receiving a YUV420 byte array then the following method can rotate this by 90 degree.

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;
}

(Note that this might only work if the width and height is a factor of 4)

生死何惧 2024-12-04 05:12:54

您可以按如下方式旋转原始数据:

// 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);

然后您可以相应地使用旋转数据。

我只用过这种方法来扫描二维码,看起来效果很好。不确定它会如何影响其他应用程序。

You can rotate the raw data as follows:

// 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];
}

Where 'width' and 'height' are the pre-set sizes for your preview image using:

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

You can then use your rotated data accordingly.

I've only used this method for QR Code scanning and it appears to work perfectly. Not sure how it might effect other applications.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文