You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:15:14