Как получить точные расстояния между кадрами изображения в реальном мире с камеры iphone?

Я пытаюсь найти точные расстояния от камеры, чтобы закончить кадр изображения. Я использовал фронтальную камеру iPhone 11. Я щелкнул фотографию с фронтальной камеры в портретном режиме и получил карту глубины, преобразовав ее в KCVPixelformat_type_DepthFloat32У меня получился массив 480*640.

Итак, я попытался определить центральное расстояние до кадра, используя это:

CVPixelBufferLockBaseAddress(depthDataMap, CVPixelBufferLockFlags(rawValue: 0)) 
let depthPointer = unsafeBitCast(CVPixelBufferGetBaseAddress(depthDataMap), to: UnsafeMutablePointer<Float32>.self) 
let point = CGPoint(x: 240,y: 320) 
let width = CVPixelBufferGetWidth(depthDataMap) 
let distanceAtXYPoint = depthPointer[Int(point.y * CGFloat(width) + point.x)]

Я получаю приблизительное центральное расстояние. Но расстояния между углами рамы могут сильно отличаться от реальных. Поэтому меня смущают эти полученные расстояния на карте глубины. Как я могу получить точные реальные расстояния от изображения карты глубины с передней или задней камеры с iPhone? Это код, который я пытался определить расстояние:

func depthDataMap() -> CVPixelBuffer? {

    // 1
    guard let fileURL = Bundle.main.url(forResource: name, withExtension: ext) as CFURL? else {
        return nil
    }

    // 2
    guard let source = CGImageSourceCreateWithURL(fileURL, nil) else {
        return nil
    }

    // 3
    guard let auxDataInfo = CGImageSourceCopyAuxiliaryDataInfoAtIndex(source, 0,
                                                                      kCGImageAuxiliaryDataTypeDisparity) as? [AnyHashable : Any] else {
                                                                        return nil
    }

    // 4
    var depthData: AVDepthData

    do {
        // 5
        depthData = try AVDepthData(fromDictionaryRepresentation: auxDataInfo)

    } catch {
        return nil
    }

    // 6
    if depthData.depthDataType != kCVPixelFormatType_DepthFloat32 {
        depthData = depthData.converting(toDepthDataType: kCVPixelFormatType_DepthFloat32)
    }
    let depthDataMap = depthData.depthDataMap //AVDepthData ->
    print(depthDataMap.printDebugInfo())
    // depthDataMap.normalize()


    //
    // Set Accuracy feedback
    //
    let accuracy = depthData.depthDataAccuracy
    switch (accuracy) {
    case .absolute:
        /*
         NOTE - Values within the depth map are absolutely
         accurate within the physical world.
         */
        print("Absolute")
        break
    case .relative:
        /*
         NOTE - Values within the depth data map are usable for
         foreground/background separation, but are not absolutely
         accurate in the physical world. iPhone always produces this.
         */
        print("Relative")
    }

    print()
    //
    // We convert the data
    //
    CVPixelBufferLockBaseAddress(depthDataMap, CVPixelBufferLockFlags(rawValue: 0))
    let depthPointer = unsafeBitCast(CVPixelBufferGetBaseAddress(depthDataMap), to: UnsafeMutablePointer<Float32>.self)


    print("Max value:\(depthDataMap.grayPixelData().max())")
    print("Min value:\(depthDataMap.grayPixelData().min())")
    print(depthDataMap.grayPixelData())

    let point = CGPoint(x: 240,y: 320)
    let width = CVPixelBufferGetWidth(depthDataMap)
    let distanceAtXYPoint = depthPointer[Int(point.y * CGFloat(width) + point.x)]

    //
    // Set UI
    //
    print("Center point:\(distanceAtXYPoint) metres") //Returns distance in meters?
    print("\(depthData.isDepthDataFiltered)")


    //
    return depthData.depthDataMap
}
}
#endif

extension CVPixelBuffer {

    func grayPixelData() -> [Float32] {
        CVPixelBufferLockBaseAddress(self, CVPixelBufferLockFlags(rawValue: 0))
        let width = CVPixelBufferGetWidth(self)
        let height = CVPixelBufferGetHeight(self)
        var pixelData = [Float32](repeating: 0, count: Int(width * height))
        for yMap in 0 ..< height {
            let rowData = CVPixelBufferGetBaseAddress(self)! + yMap * CVPixelBufferGetBytesPerRow(self)
            let data = UnsafeMutableBufferPointer<Float>(start: rowData.assumingMemoryBound(to: Float.self), count: width)
            for index in 0 ..< width {
                pixelData[index +  width * yMap] = Float32(data[index / 2])
            }
        }
        CVPixelBufferUnlockBaseAddress(self, CVPixelBufferLockFlags(rawValue: 0))
        return pixelData
    }
}

0 ответов

Другие вопросы по тегам