简体   繁体   English

如何从 AVDepthData 缓冲区读取 CGPoint 的深度数据

[英]How to read depth data at a CGPoint from AVDepthData buffer

I am attempting to find the depth data at a certain point in the captured image and return the distance in meters .我试图在捕获的图像中的某个点找到深度数据,并以meters返回距离。

I have enabled depth data and am capturing the data alongside the image.我启用了深度数据,并在图像旁边捕获数据。 I get the point from the X,Y coordinates of the center of the image (and when pressed) and convert it to the buffers index using我从图像中心(以及按下时)的 X、Y 坐标获取点,并使用以下方法将其转换为缓冲区索引

Int((width - touchPoint.x) * (height - touchPoint.y))

with WIDTH and HEIGHT being the dimensions of the captured image. WIDTHHEIGHT是捕获图像的尺寸。 I am not sure if this is the correct method to achieve this though.我不确定这是否是实现这一目标的正确方法。

I handle the depth data as such:我这样处理深度数据:

func handlePhotoDepthCalculation(point : Int) {

    guard let depth = self.photo else {
        return
    }

    //
    // Convert Disparity to Depth
    //
    let depthData = (depth.depthData as AVDepthData!).converting(toDepthDataType: kCVPixelFormatType_DepthFloat32)
    let depthDataMap = depthData.depthDataMap //AVDepthData -> CVPixelBuffer

    //
    // Set Accuracy feedback
    //
    let accuracy = depthData.depthDataAccuracy
    switch (accuracy) {
    case .absolute:
        /* 
        NOTE - Values within the depth map are absolutely 
        accurate within the physical world.
        */
        self.accuracyLbl.text = "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.
        */
        self.accuracyLbl.text = "Relative"
    }

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

    //
    // Get depth value for image center
    //
    let distanceAtXYPoint = depthPointer[point]

    //
    // Set UI
    //
    self.distanceLbl.text = "\(distanceAtXYPoint) m" //Returns distance in meters?
    self.filteredLbl.text = "\(depthData.isDepthDataFiltered)" 
}

I am not convinced I am getting the correct position.我不相信我得到了正确的位置。 From my research as well it looks like accuracy is only returned in .relative or .absolute and not a float/integer?从我的研究,以及它看起来像精度仅在返回.relative.absolute而不是浮点值/整?

To access the depth data at a CGPoint do:要访问 CGPoint 的深度数据,请执行以下操作:

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

I hope it works.我希望它有效。

Values indicating the general accuracy of a depth data map.指示深度数据图的一般精度的值。

The accuracy of a depth data map is highly dependent on the camera calibration data used to generate it.深度数据图的准确性高度依赖于用于生成它的相机校准数据。 If the camera's focal length cannot be precisely determined at the time of capture, scaling error in the z (depth) plane will be introduced.如果在拍摄时无法精确确定相机的焦距,则会引入 z(深度)平面中的缩放误差。 If the camera's optical center can't be precisely determined at capture time, principal point error will be introduced, leading to an offset error in the disparity estimate.如果在捕获时无法精确确定相机的光心,则会引入主点误差,导致视差估计中出现偏移误差。 These values report the accuracy of a map's values with respect to its reported units.这些值报告地图值相对于其报告单位的准确性。

case relative案件相关

Values within the depth data map are usable for foreground/background separation, but are not absolutely accurate in the physical world.深度数据图中的值可用于前景/背景分离,但在物理世界中并非绝对准确。

case absolute绝对大小写

Values within the depth map are absolutely accurate within the physical world.深度图中的值在物理世界中绝对准确。

You have get CGPoint from AVDepthData buffer like hight and width like follow code.您已经从 AVDepthData 缓冲区获得了 CGPoint,如高度和宽度,如跟随代码。

// Useful data
 let width = CVPixelBufferGetWidth(depthDataMap) 
 let height = CVPixelBufferGetHeight(depthDataMap) 

In Apple's sample project they use the code below.在 Apple 的示例项目中,他们使用以下代码。

Texturepoint is the touch point projected to metal view used in the sample project. Texturepoint 是投影到示例项目中使用的金属视图的接触点。

// scale
let scale = CGFloat(CVPixelBufferGetWidth(depthFrame)) / CGFloat(CVPixelBufferGetWidth(videoFrame))
let depthPoint = CGPoint(x: CGFloat(CVPixelBufferGetWidth(depthFrame)) - 1.0 - texturePoint.x * scale, y: texturePoint.y * scale)
        
assert(kCVPixelFormatType_DepthFloat16 == CVPixelBufferGetPixelFormatType(depthFrame))
CVPixelBufferLockBaseAddress(depthFrame, .readOnly)
let rowData = CVPixelBufferGetBaseAddress(depthFrame)! + Int(depthPoint.y) * CVPixelBufferGetBytesPerRow(depthFrame)
// swift does not have an Float16 data type. Use UInt16 instead, and then translate
var f16Pixel = rowData.assumingMemoryBound(to: UInt16.self)[Int(depthPoint.x)]
CVPixelBufferUnlockBaseAddress(depthFrame, .readOnly)
        
var f32Pixel = Float(0.0)
var src = vImage_Buffer(data: &f16Pixel, height: 1, width: 1, rowBytes: 2)
var dst = vImage_Buffer(data: &f32Pixel, height: 1, width: 1, rowBytes: 4)
vImageConvert_Planar16FtoPlanarF(&src, &dst, 0)
        
// Convert the depth frame format to cm
let depthString = String(format: "%.2f cm", f32Pixel * 100)

Access depth data at pixel position:在像素位置访问深度数据:

let depthDataMap: CVPixelBuffer = ...
let pixelX: Int = ...
let pixelY: Int = ...

CVPixelBufferLockBaseAddress(self, .readOnly)
let bytesPerRow = CVPixelBufferGetBytesPerRow(depthDataMap)
let baseAddress = CVPixelBufferGetBaseAddress(depthDataMap)!
assert(kCVPixelFormatType_DepthFloat32 == CVPixelBufferGetPixelFormatType(depthDataMap))

let rowData = baseAddress + pixelY * bytesPerRow
let distance = rowData.assumingMemoryBound(to: Float32.self)[pixelX]

CVPixelBufferUnlockBaseAddress(self, .readOnly)

For me the values where incorrect and inconsistent when accessing the depth by对我来说,访问深度时不正确和不一致的值

let depthPointer = unsafeBitCast(CVPixelBufferGetBaseAddress(depthDataMap), to: UnsafeMutablePointer<Float32>.self)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM