Неточности расстояния между пикселями камеры TrueDepth ⇐ IOS
Неточности расстояния между пикселями камеры TrueDepth
Я использую фронтальную камеру TrueDepth в сочетании с Vision для распознавания точек на изображении и проведения некоторых измерений. Я понимаю, что координаты Vision нормализованы, поэтому я конвертирую нормализованные точки Vision в CGPoints, соответствующие представлению, а затем сопоставляю их с глубиной данных в dataOutputSynchronizer, чтобы получить значение z. Затем, используя встроенные функции камеры, я пытаюсь получить расстояние между двумя точками в трехмерном пространстве.
Я успешно нашел точки и (я полагаю) преобразовал их в точки экрана. Я думаю, что эти точки CGP ничем не отличаются от тех, если бы я коснулся их экрана.
Моя проблема заключается в том, что, несмотря на то, что преобразованные точки CGPoint остаются в основном одинаковыми (моя рука немного перемещается во время тестирования, но остается в основном плоской по отношению к камере), и я пытаюсь вычислить положение глубины таким же образом, глубины могут быть совершенно разными, особенно пункт 2. Точка глубины 2 кажется более точной с точки зрения расчетного расстояния (моя рука находится примерно в 1 футе от камеры), но она сильно варьируется и все равно не точна.
Вот распечатка консоли с соответствующими данными
Найдено 2 точки признанные баллы [(499.08930909633636, 634.0807711283367), (543.7462849617004, 1061.8824380238852)] ТОЧКА ГЛУБИНЫ 1 = 3,6312041 ТОЧКА ГЛУБИНЫ 2 = 0,2998223 найдено 2 точки признанные баллы [(498.33644700050354, 681.3769372304281), (602.3667773008347, 1130.4955183664956)] ТОЧКА ГЛУБИНЫ 1 = 3,6276162 ТОЧКА ГЛУБИНЫ 2 = 0,560331 Вот часть соответствующего кода.
dataOutputSynchronizer
func dataOutputSynchronizer (_ синхронизатор: AVCaptureDataOutputSynchronizer, DidOutputsynchronizedDataCollection: AVCaptureSynchronizedDataCollection) { вар HandPoints: [CGPoint] = [] // Читаем все выходные данные охранный рендеринг включен, пусть syncedDepthData: AVCaptureSynchronizedDepthData = SynchronizedDataCollection.synchronizedData (для: deepDataOutput) как? AVCaptureSynchronizedDepthData, пусть syncedVideoData: AVCaptureSynchronizedSampleBufferData = SynchronizedDataCollection.synchronizedData (для: videoDataOutput) как? AVCaptureSynchronizedSampleBufferData еще { // работаем только с синхронизированными парами возвращаться } если syncedDepthData.lengthDataWasDropped || syncedVideoData.sampleBufferWasDropped { возвращаться } пусть глубинаPixelBuffer = syncedDepthData.DepthData.DepthDataMap Guard let videoPixelBuffer = CMSampleBufferGetImageBuffer(syncedVideoData.sampleBuffer) else { возвращаться } // Получаем камеруIntrinsics Guard let cameraIntrinsics = syncedDepthData.lengthData.cameraCalibrationData?.intrinsicMatrix else { возвращаться } пусть изображение = CIImage (cvPixelBuffer: videoPixelBuffer) пусть обработчик = VNImageRequestHandler( cmSampleBuffer: syncedVideoData.sampleBuffer, ориентация: .вверх, параметры: [:] ) делать { попробуйте handler.perform([handPoseRequest]) сторожить пусть результаты =handPoseRequest.results?.prefix(2), !results.isEmpty еще { возвращаться } var распознаваемые точки: [VNRecouncedPoint] = [] попробуйте results.forEach {наблюдение в пусть пальцы = попробуйте наблюдение.recouncedPoints(.all) если пусть middleTipPoint = пальцы[.middleDIP] { признанныеPoints.append(middleTipPoint) } if let запястье = пальцы[.запястье] { признанныеPoints.append(wristPoint) } } // Сохраняем точки в HandPoints, если они являются уверенными точками HandPoints = признанныеPoints.filter { $0.доверие > 0,90 } .карта { // Корректируем Y CGPoint(x: $0.location.x, y: 1 - $0.location.y) } // Обрабатываем найденные точки DispatchQueue.main.sync { self.processPoints(handPoints,lengthPixelBuffer,videoPixelBuffer,cameraIntrinsics) } } ловить { // Будьте изящнее здесь } } Точки процесса
funcprocessPoints(_handPoints: [CGPoint],_ deepPixelBuffer: CVImageBuffer,_ videoPixelBuffer: CVImageBuffer,_ cameraIntrinsics: simd_float3x3) { // Это преобразует нормализованную точку в точки экрана // cameraView.previewLayer — это AVCaptureVideoPreviewLayer внутри UIView пусть ConvertPoints = HandPoints.map { cameraView.previewLayer.layerPointConverted(fromCaptureDevicePoint: $0) } // Нам нужны 2 точки руки, чтобы получить расстояние если HandPoints.count == 2 { print("Найдено 2 точки"); print("распознанные точки") печать (конвертированные точки) пусть HandVisionPoint1 = ConvertPoints[0] пусть HandVisionPoint2 = ConvertPoints[1] пусть ScaleFactor = CGFloat(CVPixelBufferGetWidth(глубинаPixelBuffer)) / CGFloat(CVPixelBufferGetWidth(videoPixelBuffer)) / CGFloat(CVPixelBufferGetWidth(videoPixelBuffer)) CVPixelBufferLockBaseAddress(глубинаPixelBuffer, .readOnly) let floatBuffer = unsafeBitCast (CVPixelBufferGetBaseAddress (глубинаPixelBuffer), to: UnsafeMutablePointer.self) пусть ширина = CVPixelBufferGetWidth (глубинаPixelBuffer) пусть высота = CVPixelBufferGetHeight (глубинаPixelBuffer) lethandVisionPixelX = Int((handVisionPoint1.x * ScaleFactor).rounded()) lethandVisionPixelY = Int((handVisionPoint1.y * ScaleFactor).rounded()) lethandVisionPixe2X = Int((handVisionPoint2.x * ScaleFactor).rounded()) lethandVisionPixe2Y = Int((handVisionPoint2.y * ScaleFactor).rounded()) CVPixelBufferLockBaseAddress(глубинаPixelBuffer, .readOnly) пусть rowDataPoint1 = CVPixelBufferGetBaseAddress (глубинаPixelBuffer)! +handVisionPixelY * CVPixelBufferGetBytesPerRow(глубинаPixelBuffer) lethandVisionPoint1Depth = rowDataPoint1.assumingMemoryBound(to: Float32.self)[handVisionPixelX] print("ТОЧКА ГЛУБИНЫ 1 = ",handVisionPoint1Depth) пусть rowDataPoint2 = CVPixelBufferGetBaseAddress (глубинаPixelBuffer)! +handVisionPixe2Y * CVPixelBufferGetBytesPerRow(глубинаPixelBuffer) lethandVisionPoint2Depth = rowDataPoint2.assumingMemoryBound(to: Float32.self)[handVisionPixe2X] print("ТОЧКА ГЛУБИНЫ 2 = ",handVisionPoint2Depth) //Int((ширина — touchPoint.x) * (высота — touchPoint.y)) } Сейчас я думаю, что моя логика поиска правильного пикселя на карте глубины неверна. Если это не так, то мне интересно, не синхронизирован ли поток данных. Но, честно говоря, я сейчас немного растерян. Спасибо за любую помощь!
Я использую фронтальную камеру TrueDepth в сочетании с Vision для распознавания точек на изображении и проведения некоторых измерений. Я понимаю, что координаты Vision нормализованы, поэтому я конвертирую нормализованные точки Vision в CGPoints, соответствующие представлению, а затем сопоставляю их с глубиной данных в dataOutputSynchronizer, чтобы получить значение z. Затем, используя встроенные функции камеры, я пытаюсь получить расстояние между двумя точками в трехмерном пространстве.
Я успешно нашел точки и (я полагаю) преобразовал их в точки экрана. Я думаю, что эти точки CGP ничем не отличаются от тех, если бы я коснулся их экрана.
Моя проблема заключается в том, что, несмотря на то, что преобразованные точки CGPoint остаются в основном одинаковыми (моя рука немного перемещается во время тестирования, но остается в основном плоской по отношению к камере), и я пытаюсь вычислить положение глубины таким же образом, глубины могут быть совершенно разными, особенно пункт 2. Точка глубины 2 кажется более точной с точки зрения расчетного расстояния (моя рука находится примерно в 1 футе от камеры), но она сильно варьируется и все равно не точна.
Вот распечатка консоли с соответствующими данными
Найдено 2 точки признанные баллы [(499.08930909633636, 634.0807711283367), (543.7462849617004, 1061.8824380238852)] ТОЧКА ГЛУБИНЫ 1 = 3,6312041 ТОЧКА ГЛУБИНЫ 2 = 0,2998223 найдено 2 точки признанные баллы [(498.33644700050354, 681.3769372304281), (602.3667773008347, 1130.4955183664956)] ТОЧКА ГЛУБИНЫ 1 = 3,6276162 ТОЧКА ГЛУБИНЫ 2 = 0,560331 Вот часть соответствующего кода.
dataOutputSynchronizer
func dataOutputSynchronizer (_ синхронизатор: AVCaptureDataOutputSynchronizer, DidOutputsynchronizedDataCollection: AVCaptureSynchronizedDataCollection) { вар HandPoints: [CGPoint] = [] // Читаем все выходные данные охранный рендеринг включен, пусть syncedDepthData: AVCaptureSynchronizedDepthData = SynchronizedDataCollection.synchronizedData (для: deepDataOutput) как? AVCaptureSynchronizedDepthData, пусть syncedVideoData: AVCaptureSynchronizedSampleBufferData = SynchronizedDataCollection.synchronizedData (для: videoDataOutput) как? AVCaptureSynchronizedSampleBufferData еще { // работаем только с синхронизированными парами возвращаться } если syncedDepthData.lengthDataWasDropped || syncedVideoData.sampleBufferWasDropped { возвращаться } пусть глубинаPixelBuffer = syncedDepthData.DepthData.DepthDataMap Guard let videoPixelBuffer = CMSampleBufferGetImageBuffer(syncedVideoData.sampleBuffer) else { возвращаться } // Получаем камеруIntrinsics Guard let cameraIntrinsics = syncedDepthData.lengthData.cameraCalibrationData?.intrinsicMatrix else { возвращаться } пусть изображение = CIImage (cvPixelBuffer: videoPixelBuffer) пусть обработчик = VNImageRequestHandler( cmSampleBuffer: syncedVideoData.sampleBuffer, ориентация: .вверх, параметры: [:] ) делать { попробуйте handler.perform([handPoseRequest]) сторожить пусть результаты =handPoseRequest.results?.prefix(2), !results.isEmpty еще { возвращаться } var распознаваемые точки: [VNRecouncedPoint] = [] попробуйте results.forEach {наблюдение в пусть пальцы = попробуйте наблюдение.recouncedPoints(.all) если пусть middleTipPoint = пальцы[.middleDIP] { признанныеPoints.append(middleTipPoint) } if let запястье = пальцы[.запястье] { признанныеPoints.append(wristPoint) } } // Сохраняем точки в HandPoints, если они являются уверенными точками HandPoints = признанныеPoints.filter { $0.доверие > 0,90 } .карта { // Корректируем Y CGPoint(x: $0.location.x, y: 1 - $0.location.y) } // Обрабатываем найденные точки DispatchQueue.main.sync { self.processPoints(handPoints,lengthPixelBuffer,videoPixelBuffer,cameraIntrinsics) } } ловить { // Будьте изящнее здесь } } Точки процесса
funcprocessPoints(_handPoints: [CGPoint],_ deepPixelBuffer: CVImageBuffer,_ videoPixelBuffer: CVImageBuffer,_ cameraIntrinsics: simd_float3x3) { // Это преобразует нормализованную точку в точки экрана // cameraView.previewLayer — это AVCaptureVideoPreviewLayer внутри UIView пусть ConvertPoints = HandPoints.map { cameraView.previewLayer.layerPointConverted(fromCaptureDevicePoint: $0) } // Нам нужны 2 точки руки, чтобы получить расстояние если HandPoints.count == 2 { print("Найдено 2 точки"); print("распознанные точки") печать (конвертированные точки) пусть HandVisionPoint1 = ConvertPoints[0] пусть HandVisionPoint2 = ConvertPoints[1] пусть ScaleFactor = CGFloat(CVPixelBufferGetWidth(глубинаPixelBuffer)) / CGFloat(CVPixelBufferGetWidth(videoPixelBuffer)) / CGFloat(CVPixelBufferGetWidth(videoPixelBuffer)) CVPixelBufferLockBaseAddress(глубинаPixelBuffer, .readOnly) let floatBuffer = unsafeBitCast (CVPixelBufferGetBaseAddress (глубинаPixelBuffer), to: UnsafeMutablePointer.self) пусть ширина = CVPixelBufferGetWidth (глубинаPixelBuffer) пусть высота = CVPixelBufferGetHeight (глубинаPixelBuffer) lethandVisionPixelX = Int((handVisionPoint1.x * ScaleFactor).rounded()) lethandVisionPixelY = Int((handVisionPoint1.y * ScaleFactor).rounded()) lethandVisionPixe2X = Int((handVisionPoint2.x * ScaleFactor).rounded()) lethandVisionPixe2Y = Int((handVisionPoint2.y * ScaleFactor).rounded()) CVPixelBufferLockBaseAddress(глубинаPixelBuffer, .readOnly) пусть rowDataPoint1 = CVPixelBufferGetBaseAddress (глубинаPixelBuffer)! +handVisionPixelY * CVPixelBufferGetBytesPerRow(глубинаPixelBuffer) lethandVisionPoint1Depth = rowDataPoint1.assumingMemoryBound(to: Float32.self)[handVisionPixelX] print("ТОЧКА ГЛУБИНЫ 1 = ",handVisionPoint1Depth) пусть rowDataPoint2 = CVPixelBufferGetBaseAddress (глубинаPixelBuffer)! +handVisionPixe2Y * CVPixelBufferGetBytesPerRow(глубинаPixelBuffer) lethandVisionPoint2Depth = rowDataPoint2.assumingMemoryBound(to: Float32.self)[handVisionPixe2X] print("ТОЧКА ГЛУБИНЫ 2 = ",handVisionPoint2Depth) //Int((ширина — touchPoint.x) * (высота — touchPoint.y)) } Сейчас я думаю, что моя логика поиска правильного пикселя на карте глубины неверна. Если это не так, то мне интересно, не синхронизирован ли поток данных. Но, честно говоря, я сейчас немного растерян. Спасибо за любую помощь!
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Расчет расстояния между двумя точками обзора с использованием точки глубины камеры TrueDepth
Anonymous » » в форуме IOS - 0 Ответы
- 59 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Использование камеры TrueDepth на iPhone для разработки системы распознавания лиц
Anonymous » » в форуме Python - 0 Ответы
- 66 Просмотры
-
Последнее сообщение Anonymous
-