如何在 iOS 上获取相机校准数据?又名 AVCameraCalibrationData

Nic*_*gen 3 computer-vision ios avkit ios11 arkit

据我了解,AVCameraCalibrationData 只能通过 AVCaptureDepthDataOutput 使用。那是对的吗?

另一方面,AVCaptureDepthDataOutput 只能通过 iPhone X 前摄像头或 iPhone Plus 后摄像头访问,还是我弄错了?

我想要做的是获取 AVCaptureVideoDataOutput SampleBuffer 的 FOV。特别是,它应该匹配所选的预设(全高清、照片等)。

Cha*_*ler 8

这是 swift 5 中更完整/更新的代码示例,它是根据以前的答案组合在一起的。这将为您提供 iPhone 相机的内部矩阵。

基于:

// session setup
captureSession = AVCaptureSession()

let captureVideoDataOutput = AVCaptureVideoDataOutput()

captureSession?.addOutput(captureVideoDataOutput)

// enable the flag
if #available(iOS 11.0, *) {
    captureVideoDataOutput.connection(with: .video)?.isCameraIntrinsicMatrixDeliveryEnabled = true
} else {
    // ...
}

// `isCameraIntrinsicMatrixDeliveryEnabled` should be set before this
captureSession?.startRunning()
Run Code Online (Sandbox Code Playgroud)

现在里面AVCaptureVideoDataOutputSampleBufferDelegate.captureOutput(...)

if #available(iOS 11.0, *) {
    if let camData = CMGetAttachment(sampleBuffer, key:kCMSampleBufferAttachmentKey_CameraIntrinsicMatrix, attachmentModeOut:nil) as? Data {
        let matrix: matrix_float3x3 = camData.withUnsafeBytes { pointer in
                if let baseAddress = pointer.baseAddress {
                    return baseAddress.assumingMemoryBound(to: matrix_float3x3.self).pointee
                } else {
                    return matrix_float3x3()
                }
            }
        print(matrix)
        // > simd_float3x3(columns: (SIMD3<Float>(1599.8231, 0.0, 0.0), SIMD3<Float>(0.0, 1599.8231, 0.0), SIMD3<Float>(539.5, 959.5, 1.0)))
    }
} else {
    // ...
}
Run Code Online (Sandbox Code Playgroud)


ric*_*ter 5

AVCameraCalibrationData只能从深度数据输出或照片输出中获取。

但是,如果您需要的只是 FOV,则您只需要该类提供的部分信息 —相机内在矩阵— 您可以从AVCaptureVideoDataOutput.

  1. 设置cameraIntrinsicMatrixDeliveryEnabled在上AVCaptureConnection连接相机设备捕获会话。(请注意,您应该先检查cameraIntrinsicMatrixDeliverySupported;并非所有捕获格式都支持内在函数。)

  2. 当视频输出提供样本缓冲区时,检查每个样本缓冲区的附件以获取kCMSampleBufferAttachmentKey_CameraIntrinsicMatrix密钥。如CMSampleBuffer.h(有人应该提交有关将此信息放入在线文档的雷达)中所述,该附件的值是一个CFData编码 a matrix_float3x3,并且该矩阵的 (0,0) 和 (1,1) 元素是水平和以像素为单位的垂直焦距。

  • 我发现这篇关于如何以matrix_float3x3形式访问该数据的文章也很有帮助 - /sf/ask/3399570051/ -a-48-byte-cfdata?noredirect=1&amp;lq=1 如果您只需要内在数据(而不是其他相机校准数据),那么与此结合是理想的情况。 (2认同)

Bou*_*rne 5

背景:当被问及相机校准时,许多堆栈溢出响应都引用了内部数据,包括本文接受的答案,但校准数据通常包括内部数据、外部数据、镜头畸变等。它们都列在此处iOS 文档。作者提到他们只是在寻找 FOV,它在样本缓冲区中,而不是在相机校准数据中。所以最终,我认为他的问题得到了回答。但是如果你发现这个问题是在寻找实际的相机校准数据,这会让你失望。就像答案所说的那样,您只能在特定条件下获得校准数据,我将在下面详细介绍。

在我回答其余部分之前,我只想说,如果您只是在寻找内在矩阵,那么这里接受的答案很好,通过上面概述的方法。如果您将它用于计算机视觉,这就是我使用它的目的,有时这就是所需要的。但是对于非常酷的东西,你会想要一切!所以我将继续解释如何达到这个目标:

我将假设您已准备好通用相机应用程序代码。在该代码中,拍摄照片时,您可能会调用 photoOutput 函数,如下所示:

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {...
Run Code Online (Sandbox Code Playgroud)

输出参数将有一个值,您可以参考以查看是否支持称为isCameraCalibrationDataDeliverySupported 的相机校准,例如,要打印出来,请使用以下内容:

print("isCameraCalibrationDataDeliverySupported: \(output.isCameraCalibrationDataDeliverySupported)")
Run Code Online (Sandbox Code Playgroud)

请注意,在我链接到的文档中,它仅在特定场景中受支持:

“只有当 isDualCameraDualPhotoDeliveryEnabled 属性为 true 时,此属性的值才能为 true。要启用相机校准传递,请在照片设置对象中设置 isCameraCalibrationDataDeliveryEnabled 属性。”

所以这很重要,注意这一点以避免不必要的压力。使用实际值进行调试并确保启用了正确的环境。

有了所有这些,您应该从以下位置获取实际的相机校准数据:

photo.cameraCalibrationData
Run Code Online (Sandbox Code Playgroud)

只需拉出该对象即可获得您正在寻找的特定值,例如:

photo.cameraCalibrationData?.extrinsicMatrix
photo.cameraCalibrationData?.intrinsicMatrix
photo.cameraCalibrationData?.lensDistortionCenter
etc.
Run Code Online (Sandbox Code Playgroud)

基本上我上面链接的文档中列出的所有内容。