基于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
相关产品推荐
相关产品推荐

