如何计算FOV?

初始背景

我正在开发基于增强现实应用程序的位置,我需要获得视野[FOV](我只是在方向改变时更新值,所以我正在寻找一种方法,当我调用它时可以得到这个值)

目标是使“度统治者”与现实相关,如下所示: Degree Ruler  -  AR App

我已经在使用AVCaptureSession来显示摄像机流; 和一个与CAShapeLayer的路径来绘制标尺。 这工作得很好,但现在我必须使用视场值将我的元素放在正确的位置(例如,选择160°和170°之间的正确空间!)。

实际上,我用这些来源硬编码这些值: https ://stackoverflow.com/a/3594424/3198096(特别感谢@ hotpaw2!)但我不确定它们是完全精确的,这不是处理iPhone 5等我无法从官方渠道获取价值(Apple!),但有一个链接显示我认为我需要的所有iDevice的值(4,4S,5,5S): AnandTech | 关于iphone 5s相机改进的一些想法 。

注意 :经过个人测试和其他一些在线研究,我很确定这些值是不准确的! 这也迫使我使用外部库来检查我使用哪种型号的iPhone来手动初始化我的FOV ……我必须检查所有支持设备的值。

我更喜欢“代码解决方案”

看完这篇文章后: iPhone:实时video颜色信息,焦距,光圈? ,我试图从建议的AVCaptureStillImageOutput获取exif data 。 之后,我可以从exif数据中读取焦距 ,然后通过公式计算水平和垂直视野! (或者直接获得如此处所示的FOV: http : //www.brianklug.org/2011/11/a-quick-analysis-of-exif-data-from-apples-iphone-4s-camera-samples/ – – 注意 :经过一定数量的更新后,似乎我们无法直接从exif获取视野!)


实际点

来源 : http : //iphonedevsdk.com/forum/iphone-sdk-development/112225-camera-app-working-well-on-3gs-but-not-on-4s.html和修改后的EXIF数据无法保存正确

这是我正在使用的代码:

 AVCaptureDevice* camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; if (camera != nil) { captureSession = [[AVCaptureSession alloc] init]; AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:camera error:nil]; [captureSession addInput:newVideoInput]; captureLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:captureSession]; captureLayer.frame = overlayCamera.bounds; [captureLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; previewLayerConnection=captureLayer.connection; [self setCameraOrientation:[[UIApplication sharedApplication] statusBarOrientation]]; [overlayCamera.layer addSublayer:captureLayer]; [captureSession startRunning]; AVCaptureStillImageOutput *stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil]; [stillImageOutput setOutputSettings:outputSettings]; [captureSession addOutput:stillImageOutput]; AVCaptureConnection *videoConnection = nil; for (AVCaptureConnection *connection in stillImageOutput.connections) { for (AVCaptureInputPort *port in [connection inputPorts]) { if ([[port mediaType] isEqual:AVMediaTypeVideo] ) { videoConnection = connection; break; } } if (videoConnection) { break; } } [stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error) { NSData *imageNSData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer]; CGImageSourceRef imgSource = CGImageSourceCreateWithData((__bridge_retained CFDataRef)imageNSData, NULL); NSDictionary *metadata = (__bridge NSDictionary *)CGImageSourceCopyPropertiesAtIndex(imgSource, 0, NULL); NSMutableDictionary *metadataAsMutable = [metadata mutableCopy]; NSMutableDictionary *EXIFDictionary = [[metadataAsMutable objectForKey:(NSString *)kCGImagePropertyExifDictionary]mutableCopy]; if(!EXIFDictionary) EXIFDictionary = [[NSMutableDictionary dictionary] init]; [metadataAsMutable setObject:EXIFDictionary forKey:(NSString *)kCGImagePropertyExifDictionary]; NSLog(@"%@",EXIFDictionary); }]; } 

这是输出:

 { ApertureValue = "2.52606882168926"; BrightnessValue = "0.5019629837352776"; ColorSpace = 1; ComponentsConfiguration = ( 1, 2, 3, 0 ); ExifVersion = ( 2, 2, 1 ); ExposureMode = 0; ExposureProgram = 2; ExposureTime = "0.008333333333333333"; FNumber = "2.4"; Flash = 16; FlashPixVersion = ( 1, 0 ); FocalLenIn35mmFilm = 40; FocalLength = "4.28"; ISOSpeedRatings = ( 50 ); LensMake = Apple; LensModel = "iPhone 4S back camera 4.28mm f/2.4"; LensSpecification = ( "4.28", "4.28", "2.4", "2.4" ); MeteringMode = 5; PixelXDimension = 1920; PixelYDimension = 1080; SceneCaptureType = 0; SceneType = 1; SensingMethod = 2; ShutterSpeedValue = "6.906947890818858"; SubjectDistance = "69.999"; UserComment = "[SD] kCGImagePropertyExifUserComment"; WhiteBalance = 0; } 

我想我拥有计算FOV所需的一切。 但他们是正确的价值观吗? 因为看了很多不同的网站给出了不同的焦距值,我有点困惑! 我的PixelDimensions似乎也错了!

通过http://en.wikipedia.org/wiki/Angle_of_view这是我计划使用的公式:

 FOV = (IN_DEGREES( 2*atan( (d) / (2 * f) ) )); // d = sensor dimensions (mm) // f = focal length (mm) 

我的问题

我的方法和我的公式看起来是否正确,如果是,我将哪些值传递给函数?


精度

  • 如果你对统治者如何与现实相匹配,我认为我需要使用FOV; 我会接受答案!
  • 在增强现实视图控制器中禁用缩放,因此在初始化摄像机时我的视野是固定的,并且在用户旋转手机之前无法更改!

也很抱歉我的英语错误,我是法国人……

在iOS 7及更高版本中,您可以按照以下方式执行操作:

 float FOV = camera.activeFormat.videoFieldOfView; 

camera是你的AVCaptureDevice 。 根据您为video会话选择的预设, 即使在同一设备上也可以更改。 它是水平视野(以度为单位),因此您需要根据显示尺寸计算垂直视野。

这是Apple的参考资料 。

根据FOV方程,您需要焦距和传感器尺寸。 Exif数据具有焦距但不具有传感器尺寸。 我发现只有一个摄像机供应商(佳能)在元数据中提供传感器尺寸 – 这就是他们的CRW原始文件。 因此,您必须根据相机或智能手机查找传感器尺寸的表格。 以下维基百科链接列出了许多相机和一些较新的iPhone的传感器尺寸。 该列表接近Wiki文章的末尾。 http://en.wikipedia.org/wiki/Image_sensor_format

此类信息的另一个来源可能是各种摄影博客。 希望这可以帮助。

如果使用数码变焦,请将焦距乘以变焦值。 Exif数据包含缩放系数。

摄影博客和网站,如http://www.kenrockwell.com,有很多关于相机传感器尺寸的信息。

校正:实际上有焦平面X分辨率和焦平面Y分辨率(以像素为单位)和焦平面分辨率单位的Exif标签,从这些标签和图像尺寸,您可以计算传感器尺寸。 但并非所有相机都提供那些Exif标签。 例如,iPhone 4不提供这些标签。

回答你的问题:

我的方法和配方看起来是正确的吗?

也许,但它们看起来也太复杂了。

…如果是,我会将哪些值传递给函数?

我不知道,但如果目标是计算HFOV和VFOV,这里是一个代码示例,它以编程方式找到水平视角,这是目前可以在Swift中访问的唯一视角,然后计算垂直视角基于iPhone 6,16:9的宽高比。

  let devices = AVCaptureDevice.devices() var captureDevice : AVCaptureDevice? for device in devices { if (device.hasMediaType(AVMediaTypeVideo)) { if(device.position == AVCaptureDevicePosition.Back) { captureDevice = device as? AVCaptureDevice } } } if let retrievedDevice = captureDevice { var HFOV : Float = retrievedDevice.activeFormat.videoFieldOfView var VFOV : Float = ((HFOV)/16.0)*9.0 } 

如果你想让它工作,还记得导入AVFoundation!

Apple还发布了一个列表,其中包含所有相机规格细节,包括FOV(Field of View)。

https://developer.apple.com/library/ios/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Cameras/Cameras.html

值匹配可以使用以下方法检索的值:

float FOV = camera.activeFormat.videoFieldOfView;

视场直径是您在观察显微镜时可以看到的光圈直径。

如果一行中大约十个圆形单元可以跨越视场直径,并且如果您知道以毫米为单位的直径,则可以将总直径除以适合查找每个单元格大小的单元格数。

总直径除以适合的细胞数等于每个细胞的大小(直径)

如果视场直径为1.5mm,如果它们排成一行,则十个单元格适合,则每个单元格为:

1.5mm / 10 = 0.15mm

0.15毫米

请记住,每次更改放大倍率时,都可以更改可以看到的光圈直径。 所以每个放大倍数都有自己的直径。

如果在显微镜下放置标尺,放大的越多,您可以看到的标尺上的线条数量就越少。