Device camera direction excluding device landscape/portrait orientation

对着背影说爱祢 提交于 2020-04-13 06:23:30

问题


I need to get the direction of the front facing camera excluding the devices orientation (landscape/portrait). I tried to represent this using Core Motion and accessing device attitude. Here I tried to access the Euler angles and exclude the yaw, however this doesn't seem to work as when rotating the device more that one Euler angle value changes. I am also considering using the orientation quaternion but I don't have experience using them. I need this information in a serialisable manner as I would later need to determine if a different device has it's camera pointed in the same direction ( this device may be either iOS or Android).

To reiterate: if a user is pointing his phone camera (main camera not selfie one) towards the statue of liberty, what would be the best way to encode this information regardless if the user is holding the phone in portrait or landscape, such that if another user is in the same location he would know the direction in which to point his camera?


回答1:


I believe that in order to achieve this, you can use CLLocation. As you main objective is to find the cardinal point towards which the phone points, you can do things like:

fun locationManager(_ manager: CLLocationManager, didUpdateHeading heading: CLHeading) {
   let angle = newHeading.trueHeading.toRadians // convert from degrees to radians
   // do what you please with this information
}

As stated in this tutorial:

The trueHeading is the angle between that vector and the vector starting from the same point but pointing towards the true north. If your phone points exactly to the True North you’ll get a heading of 0 (zero) degrees, if it points towards East you’ll get 90 degrees etc.

Now, as stated here, the device orientation can cause some trouble:

Unfortunately, if the user orientates the device into Landscape Mode, the reported headings will be incorrect, or at least look incorrect to the user. This will become especially important when you look at augmented reality interfaces later in the book; such interfaces are generally viewed in Landscape Left mode.

BUT! There is a solution for this problem:

And you can use something like this to retrieve the heading you are looking for:

-(float)magneticHeading:(float)heading 
        fromOrientation:(UIDeviceOrientation) orientation {

    float realHeading = heading;
    switch (orientation) {1
          case UIDeviceOrientationPortrait:
               break;
          case UIDeviceOrientationPortraitUpsideDown:
               realHeading = realHeading + 180.0f;
               break;
          case UIDeviceOrientationLandscapeLeft:
               realHeading = realHeading + 90.0f;
               break;
          case UIDeviceOrientationLandscapeRight:
               realHeading = realHeading - 90.0f;
               break;
          default:
               break;
    }
    while ( realHeading > 360.0f ) {
          realHeading = realHeading - 360;
    }
    return realHeading;
}

Sorry about the different languages (Swift - Objective C), but in order to fully understand the problem and find a complete solution I would recommend to read into the sources:

  • Medium Compass Tutorial
  • O'Reilly's Compass Tutorial

Hope this helps! Let me know.




回答2:


There is 4 type of them. one is deprecated:

  1. public static final int ORIENTATION_UNDEFINED = 0;
  2. public static final int ORIENTATION_PORTRAIT = 1;
  3. public static final int ORIENTATION_LANDSCAPE = 2:
  4. @Deprecated public static final int ORIENTATION_SQUARE = 3;

You can learn with

val orientation: Int = resources.configuration.orientation

If you want to learn specific angle and position you should use Sensor service with this.sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

and for exact position

sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)?.let { this.rotationVector = it}

this class also has different features like.

TYPE_ACCELEROMETER

Measures the acceleration force in m/s2 that is applied to a device on all three physical axes (x, y, and z), including the force of gravity.

Motion detection (shake, tilt, etc.).

TYPE_GRAVITY

Measures the force of gravity in m/s2 that is applied to a device on all three physical axes (x, y, z).

Motion detection (shake, tilt, etc.).

TYPE_GYROSCOPE

Measures a device’s rate of rotation in rad/s around each of the three physical axes (x, y, and z).

Rotation detection (spin, turn, etc.).

TYPE_LINEAR_ACCELERATION

Measures the acceleration force in m/s2 that is applied to a device on all three physical axes (x, y, and z), without the force of gravity.

Monitoring acceleration along a single axis.

TYPE_ROTATION_VECTOR

Measures the orientation of a device by providing the three elements of the device’s rotation vector.

Motion detection and rotation detection.




回答3:


In android, I use setRotation() method to rotted the camera.

setRotation(camera, parameters, requestedCameraId);

private void setRotation(Camera camera, Camera.Parameters parameters, int cameraId) {
    WindowManager windowManager =
            (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
    int degrees = 0;

    //get current display rotation
    int rotation = windowManager.getDefaultDisplay().getRotation();

    switch (rotation) {
        case Surface.ROTATION_0:
            degrees = 0;
            break;
        case Surface.ROTATION_90:
            degrees = 90;
            break;
        case Surface.ROTATION_180:
            degrees = 180;
            break;
        case Surface.ROTATION_270:
            degrees = 270;
            break;
        default:
            Log.e(TAG, "Bad rotation value: " + rotation);
    }

    CameraInfo cameraInfo = new CameraInfo();
    Camera.getCameraInfo(cameraId, cameraInfo);

    int angle;
    int displayAngle;
    if (cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT) {
        angle = (cameraInfo.orientation + degrees) % 360;
        displayAngle = (360 - angle) % 360; // compensate for it being mirrored
    } else {  // back-facing
        angle = (cameraInfo.orientation - degrees + 360) % 360;
        displayAngle = angle;
    }

    // This corresponds to the rotation constants.
    // mRotation = angle / 90;

    camera.setDisplayOrientation(displayAngle);
    parameters.setRotation(angle);
}

I hope this is work for you.



来源:https://stackoverflow.com/questions/60507826/device-camera-direction-excluding-device-landscape-portrait-orientation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!