iOS平台如何获取AVCameraCalibrationData及相关技术问题咨询
嘿,我来帮你把这些关于iOS相机校准数据的问题一一理清:
1. AVCameraCalibrationData的获取途径
你的第一个认知有偏差——AVCameraCalibrationData并非只能通过AVCaptureDepthDataOutput获取,它有多个获取渠道:
- 从
AVCaptureDepthData中提取:当你使用AVCaptureDepthDataOutput时,输出的depthData对象自带cameraCalibrationData属性; - 从
AVCapturePhoto中获取:iOS 11及以上版本中,拍摄得到的AVCapturePhoto直接提供cameraCalibrationData属性,也可以从它的metadata字典里找到相关校准信息; - 从
AVCaptureVideoDataOutput的SampleBuffer中提取:通过CMSampleBufferGetCameraCalibrationData(sampleBuffer)函数就能从视频帧中拿到校准数据,不过这需要设备支持且会话配置正确。
2. AVCaptureDepthDataOutput的设备支持范围
你的认知也不够全面,它不止支持iPhone X前置摄像头和iPhone Plus后置摄像头:
- 从iPhone X开始的绝大多数iPhone机型(包括iPhone 11/12/13/14全系列等)的前置原深感摄像头,以及后置双摄/三摄系统(哪怕是非Plus机型,比如iPhone 11后置双摄)都支持该输出;
- 部分配备LiDAR扫描仪的iPad Pro机型也支持深度数据输出;
- 建议在代码里通过
AVCaptureDevice.isDepthDataDeliverySupported方法来检查当前设备是否支持,避免硬编码判断机型。
3. 获取匹配所选预设的视场角(FOV)
要拿到和当前预设(比如全高清、照片模式)匹配的FOV,有两种可靠方式:
方式一:通过相机校准数据计算
从SampleBuffer中提取校准数据后,结合图像分辨率计算FOV,代码示例如下:
func calculateFOV(from sampleBuffer: CMSampleBuffer) { guard let calibrationData = CMSampleBufferGetCameraCalibrationData(sampleBuffer), let formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer) else { return } // 获取内参矩阵中的焦距值 let intrinsicMatrix = calibrationData.intrinsicMatrix let focalLengthX = intrinsicMatrix[0][0] let focalLengthY = intrinsicMatrix[1][1] // 获取当前帧的图像尺寸 let dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription) let imageWidth = CGFloat(dimensions.width) let imageHeight = CGFloat(dimensions.height) // 计算水平、垂直FOV(弧度转角度) let horizontalFOV = 2 * atan(imageWidth / (2 * focalLengthX)) * 180 / .pi let verticalFOV = 2 * atan(imageHeight / (2 * focalLengthY)) * 180 / .pi print("水平FOV: \(String(format: "%.2f", horizontalFOV))°,垂直FOV: \(String(format: "%.2f", verticalFOV))°") }
方式二:直接读取设备的activeFormat属性
每个AVCaptureDevice.Format都自带videoFieldOfView属性(水平视场角),而你设置的会话预设会对应到当前激活的format,直接读取即可:
func getCurrentFOV(from captureDevice: AVCaptureDevice) -> CGFloat? { return captureDevice.activeFormat.videoFieldOfView }
如果需要垂直FOV,可以通过宽高比换算:
let horizontalFOV = captureDevice.activeFormat.videoFieldOfView let dimensions = captureDevice.activeFormat.formatDescription.dimensions let aspectRatio = CGFloat(dimensions.height) / CGFloat(dimensions.width) let verticalFOV = 2 * atan(tan(horizontalFOV * .pi / 360) * aspectRatio) * 180 / .pi
这两种方式都能保证FOV和当前所选预设匹配,后者更直接,前者则能拿到更精准的、和当前帧完全对应的校准数据。
内容的提问来源于stack exchange,提问作者Nicolas Degen
相关产品推荐
相关产品推荐

