为什么我的面部检测代码不能使用CIDetector正常工作?

时间:2017-04-07 05:06:34

标签: ios camera avfoundation avcapture cidetector

我正在尝试检测iOS相机应用中的脸部,但它doesn't work properly,而works properly in Camera.app。请注意:

  • 我的应用中未检测到第一张脸,仅在Camera.app。
  • 中检测到
  • 对于第三张脸 - 东亚女人 - Camera.app正确地在她的脸上画了一个矩形,而我的应用程序绘制了一个远远低于她脸的矩形。
  • 在我的应用中未检测到奥巴马的脸,仅在Camera.app。
  • 当相机从普京的脸上缩小时,我的应用程序在他的右半边画一个矩形,将其切成两半,而Camera.app正确地在他的脸上画一个矩形。

为什么会这样?

我的代码如下。你看错了吗?

首先,我按如下方式创建视频输出:

let videoOutput = AVCaptureVideoDataOutput()
videoOutput.videoSettings =
    [kCVPixelBufferPixelFormatTypeKey as AnyHashable: 
    Int(kCMPixelFormat_32BGRA)]

session.addOutput(videoOutput)

videoOutput.setSampleBufferDelegate(faceDetector, queue: faceDetectionQueue)

这是代表:

class FaceDetector: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate {
  func captureOutput(_ captureOutput: AVCaptureOutput!,
                     didOutputSampleBuffer sampleBuffer: CMSampleBuffer!,
                     from connection: AVCaptureConnection!) {
    let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
    let features = FaceDetector.ciDetector.features(
        in: CIImage(cvPixelBuffer: imageBuffer))

    let faces = features.map { $0.bounds }
    let imageSize = CVImageBufferGetDisplaySize(imageBuffer)

    let faceBounds = faces.map { (face: CIFeature) -> CGRect in
        var ciBounds = face.bounds

        ciBounds = ciBounds.applying(
            CGAffineTransform(scaleX: 1/imageSize.width, y: -1/imageSize.height))
        CGRect(x: 0, y: 0, width: 1, height: -1).verifyContains(ciBounds)

        let bounds = ciBounds.applying(CGAffineTransform(translationX: 0, y: 1.0))
        CGRect(x: 0, y: 0, width: 1, height: 1).verifyContains(bounds)
        return bounds
    }
    DispatchQueue.main.sync {
      facesUpdated(faceBounds, imageSize)
    }
  }

  private static let ciDetector = CIDetector(ofType: CIDetectorTypeFace,
      context: nil,
      options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])!
}

facesUpdated()回调如下:

class PreviewView: UIView {
  private var faceRects = [UIView]()

  private static func makeFaceRect() -> UIView {
    let r = UIView()
    r.layer.borderWidth = FocusRect.borderWidth
    r.layer.borderColor = FocusRect.color.cgColor
    faceRects.append(r)
    addSubview(r)
    return r
  }

  private func removeAllFaceRects() {
    for faceRect in faceRects {
      verify(faceRect.superview == self)
      faceRect.removeFromSuperview()
    }
    faceRects.removeAll()
  }

  private func facesUpdated(_ faces: [CGRect], _ imageSize: CGSize) {
    removeAllFaceRects()

    let faceFrames = faces.map { (original: CGRect) -> CGRect in
        let face = original.applying(CGAffineTransform(scaleX: bounds.width, y: bounds.height))
        verify(self.bounds.contains(face))
        return face
    }

    for faceFrame in faceFrames {
      let faceRect = PreviewView.makeFaceRect()
      faceRect.frame = faceFrame
    }
  }
}

我也尝试了以下内容,但他们没有帮助:

  1. 将AVCaptureVideoDataOutput的videoSettings设置为nil。
  2. 将CIDetector的方向明确设置为纵向。这个测试的手机是纵向的,所以没关系。
  3. 设置和删除CIDetectorTracking:true
  4. 设置和删除CIDetectorAccuracy:CIDetectorAccuracyHigh
  5. 仅通过查看检测到的第一个特征,尝试仅跟踪一张脸。
  6. 用CVImageBufferGetEncodedSize()取代CVImageBufferGetDisplaySize() - 它们无论如何都是相同的,为1440 x 1080。

0 个答案:

没有答案