Улучшение отслеживания тела VNDetectHumanBodyPoseRequest - PullRequest
2 голосов
/ 14 июля 2020

Я пытаюсь улучшить производительность рисования скелета с отслеживанием тела для VNDetectHumanBodyPoseRequest даже на расстоянии более 5 метров и с помощью стабильной камеры iPhone XS.

Отслеживание имеет низкую достоверность по нижним правым конечностям моего тела заметное отставание и есть дрожание. Я не могу воспроизвести продемонстрированную производительность в демонстрационном видео WWD C этого года .

Вот соответствующий код, адаптированный из образца кода Apple :

class Predictor {
  func extractPoses(_ sampleBuffer: CMSampleBuffer) throws -> [VNRecognizedPointsObservation] {
    let requestHandler = VNImageRequestHandler(cmSampleBuffer: sampleBuffer, orientation: .down)
    
    let request = VNDetectHumanBodyPoseRequest()
    
    do {
      // Perform the body pose-detection request.
      try requestHandler.perform([request])
    } catch {
      print("Unable to perform the request: \(error).\n")
    }
    
    return (request.results as? [VNRecognizedPointsObservation]) ?? [VNRecognizedPointsObservation]()
  }
}

Я захватил видеоданные и обрабатываю образцы буферов здесь:

class CameraViewController: AVCaptureVideoDataOutputSampleBufferDelegate {

  func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    let observations = try? predictor.extractPoses(sampleBuffer)
    observations?.forEach { processObservation($0) }
  }

  func processObservation(_ observation: VNRecognizedPointsObservation) {
    
    // Retrieve all torso points.
    guard let recognizedPoints =
            try? observation.recognizedPoints(forGroupKey: .all) else {
      return
    }
    
    let storedPoints = Dictionary(uniqueKeysWithValues: recognizedPoints.compactMap { (key, point) -> (String, CGPoint)? in
      return (key.rawValue, point.location)
    })
    
    DispatchQueue.main.sync {
      let mappedPoints = Dictionary(uniqueKeysWithValues: recognizedPoints.compactMap { (key, point) -> (String, CGPoint)? in
        guard point.confidence > 0.1 else { return nil }
        let norm = VNImagePointForNormalizedPoint(point.location,
                                                  Int(drawingView.bounds.width),
                                                  Int(drawingView.bounds.height))
        return (key.rawValue, norm)
      })
      
      let time = 1000 * observation.timeRange.start.seconds
      
      
      // Draw the points onscreen.
      DispatchQueue.main.async {
        self.drawingView.draw(points: mappedPoints)
      }
    }
  }
}

Функция drawingView.draw предназначена для пользовательского UIView поверх обзора камеры, и dr aws точек с использованием подслоев CALayer. Код AVCaptureSession точно такой же, как код примера здесь .

Я пробовал использовать вариант VNDetectHumanBodyPoseRequest(completionHandler:), но это не повлияло на производительность для меня. Я мог бы попробовать сглаживание с помощью фильтра скользящего среднего .. но все еще есть проблема с прогнозами выбросов, которые очень неточны.

Что мне не хватает?

...