2011-07-28 45 views
12

Tôi muốn thực hiện một số xử lý hình ảnh cho các điểm ảnh nhận được từ máy ảnh.pixel camera xoay

Vấn đề là các pixel từ máy ảnh được xoay 90 độ.

Im nhận được các điểm ảnh bên trong phương pháp onPreviewFrame(byte[] data, Camera camera)

tôi đã cố gắng camera.setDisplayOrientation(90); và nó sẽ hiển thị các video trong định hướng đúng, nhưng tôi vẫn nhận được các điểm ảnh xoay như đã nêu trong tài liệu:

này không không ảnh hưởng đến thứ tự của mảng byte được truyền trong Android.Hardware.Camera.IPreviewCallback.OnPreviewFrame (Byte [], Android.Hardware.Camera), ảnh JPEG hoặc video đã quay.

Tôi cũng đã cố gắng:

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

nhưng điều đó không làm việc.

Tôi đang sử dụng android 2,2

enter image description here

hình ảnh trên cho thấy SurfaceView khi sử dụng camera.setDisplayOrientation(90);

Hình ảnh thứ hai được nhận bên onPreviewFrame(byte[] data, Camera camera) từ mảng data. Như bạn có thể thấy mảng data được xoay.

Trả lời

5

Có thể bạn có thể thực hiện xử lý hình ảnh trên khung ngang và chỉ lo lắng về xoay khi bạn hiển thị hình ảnh (mà bạn đã thực hiện). Nếu không, bạn cần phải xoay khung theo cách cũ. Tôi tìm thấy một số mã ở đâu đó (với một thay đổi nhỏ) có thể giúp:

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

Đây là dễ dàng bởi vì phương pháp createBitmap hỗ trợ một ma trận chuyển đổi: http://developer.android.com/reference/android/graphics/Bitmap.html#createBitmap(android.graphics.Bitmap, int, int, int, int, android.graphics.Matrix, boolean)

2

Bạn có thể xoay các dữ liệu thô như sau:

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

đâu 'width' và 'chiều cao' là kích thước cài đặt trước cho hình ảnh xem trước của bạn sử dụng:

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

Sau đó, bạn có thể sử dụng dữ liệu xoay theo đó.

Tôi chỉ sử dụng phương pháp này để quét mã QR và nó có vẻ hoạt động hoàn hảo. Bạn không chắc chắn cách nó có thể ảnh hưởng đến các ứng dụng khác.

+0

Điều này không có tác dụng, đã đưa ra ArrayIndexOutOFBoundsException. –

+0

Miễn là hình ảnh xem trước bạn nhận được khớp với giá trị chiều rộng và chiều cao thì bạn không nên nhận được ngoại lệ bị ràng buộc. Đây là mã chính xác tôi đang sử dụng tại thời điểm này và hoạt động tốt. – Scott

+0

Dữ liệu thô được quay tốt nhưng chất lượng hình ảnh giảm xuống, sau khi sử dụng đoạn mã của bạn, tôi không thể có được chất lượng hình ảnh phù hợp với những gì tôi đã nhận được trước đây, bạn có thể giải thích thêm một số điểm quay hay không. cho cùng. Sự trợ giúp của bạn sẽ được đánh giá cao. –

4

Nếu bạn nhận được mảng byte YUV420 thì phương pháp sau có thể xoay 90 độ này.

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

(Lưu ý rằng điều này chỉ có thể làm việc nếu chiều rộng và chiều cao là một yếu tố của 4)

+1

không hoạt động! Xin hãy giúp tôi với điều này đã cho một ArrayIndexOutOFBoundsException – therealprashant

6

Trong khi tôi là một chút muộn để đảng, đây là một phương pháp tôi đã viết rằng những người khác có thể tìm thấy hữu ích để xoay ảnh YUV420sp (NV21).Không có phương pháp nào khác tôi thấy trên SO dường như thực sự làm điều đó.

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

thận trọng: Điều này có vẻ bắt nguồn từ https://github.com/SMSSecure/SMSSecure/blob/master/src/org/smssecure/smssecure/util/BitmapUtil.java và dự án là đã gắn thẻ GPLv3. Các công cụ tìm kiếm vi phạm GPL có thể gắn cờ chương trình của bạn nếu bạn sử dụng. – laalto

+0

nó có nguồn gốc từ https://github.com/WhisperSystems/Signal-Android/blob/master/src/org/thought/vi/securesms/util/BitmapUtil.java nguồn: Tôi đã viết và đặt ở đó. – jake

+0

Cảm ơn, có vẻ như dự án hit đầu tiên là một nhánh của dự án của bạn. Dù sao, có GPLv3 và các công cụ tìm kiếm vi phạm GPL có thể gắn cờ mã bằng đoạn mã này. (Đối với tôi: Tôi đã xem xét một đoạn mã độc quyền nơi đoạn mã này nổi bật và bắt đầu googling nó xuất phát từ đâu. Nó bây giờ đã bị xóa khỏi không gian mã độc quyền.) – laalto