简体   繁体   中英

How to know the Field of View Angle of iPhone or iPad's Camera

In Android, the API provides the field of view angle:

  1. Camera.Parameters.getHorizontalViewAngle()
  2. Camera.Parameters.getVerticalViewAngle()

What's the equivalent in iOS? I don't want to pre-write those values because it's not flexible.

I'm not entirely sure what "horizontal" and "vertical" mean in this context, but I think of two calculations, the rotation about the "z" axis (ie how level we are with the horizon in the photo), and how much it's tilted forward and backward (ie the rotation about the "x" axis, namely is it pointing up or down). You can do this using Core Motion . Just add it to your project and then you can do something like:

  1. Make sure to import CoreMotion header:

     #import <CoreMotion/CoreMotion.h> 
  2. Define a few class properties:

     @property (nonatomic, strong) CMMotionManager *motionManager; @property (nonatomic, strong) NSOperationQueue *deviceQueue; 
  3. Start the motion manager:

     - (void)startMotionManager { self.deviceQueue = [[NSOperationQueue alloc] init]; self.motionManager = [[CMMotionManager alloc] init]; self.motionManager.deviceMotionUpdateInterval = 5.0 / 60.0; [self.motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryZVertical toQueue:self.deviceQueue withHandler:^(CMDeviceMotion *motion, NSError *error) { [[NSOperationQueue mainQueue] addOperationWithBlock:^{ CGFloat x = motion.gravity.x; CGFloat y = motion.gravity.y; CGFloat z = motion.gravity.z; // how much is it rotated around the z axis CGFloat rotationAngle = atan2(y, x) + M_PI_2; // in radians CGFloat rotationAngleDegrees = rotationAngle * 180.0f / M_PI; // in degrees // how far it it tilted forward and backward CGFloat r = sqrtf(x*x + y*y + z*z); CGFloat tiltAngle = (r == 0.0 ? 0.0 : acosf(z/r); // in radians CGFloat tiltAngleDegrees = tiltAngle * 180.0f / M_PI - 90.0f); // in degrees }]; }]; } 
  4. When done, stop the motion manager:

     - (void)stopMotionManager { [self.motionManager stopDeviceMotionUpdates]; self.motionManager = nil; self.deviceQueue = nil; } 

I'm not doing anything with the values here, but you can save them in class properties which you can then access elsewhere in your app. Or you could dispatch UI updates back to the main queue right from here. A bunch of options.

Since this is iOS 5 and higher, if the app is supporting earlier versions you might also want to weakly link Core Motion then then check to see everything is ok, and if not, just realize that you're not going to be capturing the orientation of the device:

if ([CMMotionManager class]) 
{
    // ok, core motion exists
}

And, in case you're wondering about my fairly arbitrary choice of twelve times per second, in the Event Handling Guide for iOS , they suggest 10-20/second if just checking the orientation of the device.

In iOS 7.0+, you can obtain FOV angle of a camera by reading this property. https://developer.apple.com/documentation/avfoundation/avcapturedeviceformat/1624569-videofieldofview?language=objc

AVCaptureDevice *camera;
camera = ...
float fov = [[camera activeFormat] videoFieldOfView];
NSLog("FOV=%f(deg)", fov);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM