Как получить точные расстояния между кадрами изображения в реальном мире с камеры 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
}
}