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

基于TrueDepth相机深度点计算两个Vision点真实距离的问题

问题:TrueDepth相机计算Vision点真实世界距离结果仅为真实值约一半

使用前置TrueDepth相机获取手上的两个Vision点,通过depthMap获取各点到相机的距离,再借助Camera Intrinsics的focalLength计算X、Y坐标,结合作为Z值的深度数据,用simd_precise_distance或自定义欧氏距离函数计算两点距离,结果一致,但仅为真实值的约一半(并非精确一半)。

曾看到Andy Jazz的帖子提到iPhone视口可能为1/2或1/3,但不确定是否可直接翻倍结果。还尝试过另一种坐标转换公式:

/*
let xrwPoint1 = (Float(convertedPoints[0].x) - cameraIntrinsics[2][0]) * distanceValue1 / cameraIntrinsics[0][0];
let yrwPoint1 = (Float(convertedPoints[0].y) - cameraIntrinsics[2][1]) * distanceValue1 / cameraIntrinsics[1][1];

let xrwPoint2 = (Float(convertedPoints[1].x) - cameraIntrinsics[2][0]) * distanceValue2 / cameraIntrinsics[0][0];
let yrwPoint2 = (Float(convertedPoints[1].y) - cameraIntrinsics[2][1]) * distanceValue2 / cameraIntrinsics[1][1];

print("xrw = ", xrwPoint1);
print("yrw = ", yrwPoint1);
*/

但该方法也不准确。目前疑惑是否需要将米制深度值转换为其他Z值后再计算距离,但毫无头绪。以下是实现的函数(保留了尝试过的注释代码):

func processPoints(_ handPoints: [CGPoint],_ depthPixelBuffer: CVImageBuffer,_ videoPixelBuffer: CVImageBuffer,_ cameraIntrinsics: simd_float3x3) {

    let convertedPoints = handPoints.map {
        cameraView.previewLayer.layerPointConverted(fromCaptureDevicePoint: $0)
    }
    
    if handPoints.count == 2 {
        
        let handVisionPoint1 = handPoints[0]
        let handVisionPoint2 = handPoints[1]
        
        let scaleFactor = CGFloat(CVPixelBufferGetWidth(depthPixelBuffer)) / CGFloat(CVPixelBufferGetWidth(videoPixelBuffer))
       
        CVPixelBufferLockBaseAddress(depthPixelBuffer, .readOnly)
        let floatBuffer = unsafeBitCast(CVPixelBufferGetBaseAddress(depthPixelBuffer), to: UnsafeMutablePointer<Float32>.self)
        
        let width = CVPixelBufferGetWidth(depthPixelBuffer)
        let height = CVPixelBufferGetHeight(depthPixelBuffer)

        let colPosition1 = Int(handVisionPoint1.x * CGFloat(width))
        let rowPosition1 = Int(handVisionPoint1.y * CGFloat(height))
        
        let colPosition2 = Int(handVisionPoint2.x * CGFloat(width))
        let rowPosition2 = Int(handVisionPoint2.y * CGFloat(height))
        
        let handVisionPixelX = Int((handVisionPoint1.x * scaleFactor).rounded())
        let handVisionPixelY = Int((handVisionPoint1.y * scaleFactor).rounded())
        
        let handVisionPixel2X = Int((handVisionPoint2.x * scaleFactor).rounded())
        let handVisionPixel2Y = Int((handVisionPoint2.y * scaleFactor).rounded())
        
        
        guard CVPixelBufferGetPixelFormatType(depthPixelBuffer) == kCVPixelFormatType_DepthFloat32 else { return }

                CVPixelBufferLockBaseAddress(depthPixelBuffer, .readOnly)

                if let baseAddress = CVPixelBufferGetBaseAddress(depthPixelBuffer) {

                        let width = CVPixelBufferGetWidth(depthPixelBuffer)

                        let index1 = colPosition1 + (rowPosition1 * width)
                        let index2 = colPosition2 + (rowPosition2 * width)

                        let offset1 = index1 * MemoryLayout<Float>.stride
                        let offset2 = index2 * MemoryLayout<Float>.stride

                        let distanceValue1 = baseAddress.load(fromByteOffset: offset1, as: Float.self)
                        let distanceValue2 = baseAddress.load(fromByteOffset: offset2, as: Float.self)
                        
                        print("DISTANCE POINT 1 IS ", distanceValue1)
                        print("DISTANCE POINT 2 IS ", distanceValue2)
                    
                    
                        /*
                        let xrwPoint1 = (Float(convertedPoints[0].x) - cameraIntrinsics[2][0]) * distanceValue1 / cameraIntrinsics[0][0];
                        let yrwPoint1 = (Float(convertedPoints[0].y) - cameraIntrinsics[2][1]) * distanceValue1 / cameraIntrinsics[1][1];
                         
                        let xrwPoint2 = (Float(convertedPoints[1].x) - cameraIntrinsics[2][0]) * distanceValue2 / cameraIntrinsics[0][0];
                        let yrwPoint2 = (Float(convertedPoints[1].y) - cameraIntrinsics[2][1]) * distanceValue2 / cameraIntrinsics[1][1];
                         
                        print("xrw = ", xrwPoint1);
                        print("yrw = ", yrwPoint1);
                        */

                        let uPoint1 = Float(convertedPoints[0].x - CGFloat(width))/2
                        let vPoint1 = Float(CGFloat(height)/2-convertedPoints[0].y)
                        
                        let uPoint2 = Float(convertedPoints[1].x - CGFloat(width))/2
                        let vPoint2 = Float(CGFloat(height)/2-convertedPoints[1].y)
                        
                        let focalLengthPx = cameraIntrinsics.columns.0.x;
                        
                        let xPoint1 = Float(uPoint1 * Float(distanceValue1) / Float(focalLengthPx))
                        let yPoint1 = Float(vPoint1 * Float(distanceValue1) / Float(focalLengthPx))
                    
                        let xPoint2 = Float(uPoint2 * Float(distanceValue2) / Float(focalLengthPx))
                        let yPoint2 = Float(vPoint2 * Float(distanceValue2) / Float(focalLengthPx))
             
                        let visionPoint1In3D = simd_float3(xPoint1, -yPoint1, distanceValue1)
                        let visionPoint2In3D = simd_float3(xPoint2, -yPoint2, distanceValue2)
                         
                        // This is the same function as euclidean function below
                        let dist = simd_precise_distance(visionPoint1In3D, visionPoint2In3D)
                    
                        print("Distance In Meters Is  ", dist)
                    
                         /*
                         X = u*Z/f;
                         Y = v*Z/f,
                         where f is camera focal length in pixels, 
                         Z is distance meter
                         u = column-width/2
                         v = height/2-row
                          
                         the distance in 3D is given by Euclidean formula:
                         d = √[(x2 - x1)² + (y2 - y1)² + (z2 - z1)²].
                          
                         */
                    
                    
                    CVPixelBufferUnlockBaseAddress(depthPixelBuffer, .readOnly)

                }
        
        CVPixelBufferUnlockBaseAddress(depthPixelBuffer, .readOnly)   
    }
    
}

恳请各位提供解决思路!


内容的提问来源于stack exchange,提问作者K_C

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 06:34:51