Ask Your Question

Revision history [back]

Issue of Camera-Screen Orientation in Android, using OpenCV

I'm developing an Android application, and I'm using OpenCV4Android in the development, in the version 2.4.9.

I have opened a video stream using the JavaCameraView class. My problem is the bad orientation of the Camera compared to the position of the device. I'm using a Samsung Galaxy S4, and the default orientation of OpenCV camera seems to be landscape left.

To solve this problem, I've used this solution. I've extended the JavaCameraView class, adding to the new class this methods:

private void getScreenRotationOnPhone() {

    final Display display = ((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();

    switch (display.getRotation()) {
        case Surface.ROTATION_0:
            System.out.println("SCREEN_ORIENTATION_PORTRAIT");
            setDisplayOrientation(mCamera, 90);
            try {
                mCamera.setPreviewDisplay(getHolder());
            } catch (IOException e) {
                e.printStackTrace();
            }
            break;

        case Surface.ROTATION_90:
            System.out.println("SCREEN_ORIENTATION_LANDSCAPE");
            break;

        case Surface.ROTATION_180:
            System.out.println("SCREEN_ORIENTATION_REVERSE_PORTRAIT");
            break;

        case Surface.ROTATION_270:
            System.out.println("SCREEN_ORIENTATION_REVERSE_LANDSCAPE");
            setDisplayOrientation(mCamera, 180);
            try {
                mCamera.setPreviewDisplay(getHolder());
            } catch (IOException e) {
                e.printStackTrace();
            }
            break;
    }
}

private void getScreenRotationOnTablet() {

    final Display display = ((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();

    switch (display.getRotation()) {
        case Surface.ROTATION_0:
            System.out.println("SCREEN_ORIENTATION_LANDSCAPE");
            break;

        case Surface.ROTATION_90:
            System.out.println("SCREEN_ORIENTATION_REVERSE_PORTRAIT");
            break;

        case Surface.ROTATION_180:
            System.out.println("SCREEN_ORIENTATION_REVERSE_LANDSCAPE");
            break;

        case Surface.ROTATION_270:
            System.out.println("SCREEN_ORIENTATION_PORTRAIT");
            break;
    }
}

public static boolean isTablet(Context ctx){
    return (ctx.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}

So, in the initializeCamera method, before the mCamera.startPreview(), I've added the following code:

                if(isTablet(getContext()) == Boolean.FALSE){
                    this.getScreenRotationOnPhone();
                }else{
                   this.getScreenRotationOnTablet();
                }

This code works, and the application is not slowed (I could use also the flip method, or rotation matrix, in the onCameraFrame method of my activity, ma in this way my performances get worse).

The only problem is when my orientation of device changes from landscape right to landscape left and vice-versa, without going through portrait mode. After this change, my Camera is turned 180 degrees with respect to natural position.

Here there are two images that show the problem. first step second step

Related Question on StackOverflow: link.