0

I am building Face detection app using OpenCv. I am processing preview frame data received on callback onPreviewFrame. I am using camera in portrait mode, whereas onPreviewFrame returns me data in landscape mode. I am rotating frame data using this code.

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

After rotating data, I am converting to byte array to OpenCv Mat. After the conversion I pass into openCv native code.

In landscape mode (without rotating preview data), I am able to get almost 20 FPS after processing camera preview. But in portrait mode, with above method, the FPS is reduced to 3 FPS. On measuring time taken by rotateYUV420Degree90, this method is the main culprit.

I am new to OpenCv. Is there any other approach that i can take to rotate preview data using java code or native code, fastly. Because of complexity of my app, i cannot use JavaCameraView provided by OpenCV.

Swati Garg
  • 995
  • 1
  • 10
  • 21
Abhishek Batra
  • 1,539
  • 1
  • 18
  • 45

2 Answers2

0

I think you have already an answer in this:

Android: How to rotate a bitmap on a center point

in your case your rotation is just mRotation = 90 degrees.

Community
  • 1
  • 1
Amitay Nachmani
  • 3,259
  • 1
  • 18
  • 21
0

Problem: Dont traverse image in column-order. Since, you are not benefited by locality of reference, the code will run very slow.

For opencv, you can use combination of transpose and flip command.

switch (angle) {
        case 0:
            srcImage.copyTo(dstImage);
            break;
        case 90:
            Core.transpose(srcImage, dstImage);
            Core.flip(dstImage, dstImage, 1);
            break;
        case 180:
            Core.flip(srcImage, dstImage, -1);
            break;
        case 270:
            Core.transpose(srcImage, dstImage);
            Core.flip(dstImage, dstImage, 0);
            break;
        default:
            Logger.error(
                "ROTATE_IMAGE_CLOCKWISE: Incorrect rotation value received: {}", 
                angle);
            return srcImage;
    }

This is the same code used to read input image when Image(jpeg) has Orientation metadata. See opencv source code here. The above code is in java.

See my answer here, to know how orientation works. Put opencv and the image from my answer together, and its very simple.

Community
  • 1
  • 1
saurabheights
  • 3,967
  • 2
  • 31
  • 50