我有一个非常具体的问题,但希望有人可以帮助我。我正在使用AVFoundation创建具有实时预览的摄像机。我使用AVCaptureVideoDataOutput获取单个帧,并使用AVCaptureMetadataOutput检测面部。我还使用Dlib的面部界标预测器来显示用户脸上的界标点,并测量他们的眼睛之间的眼间距离。最后,我使用了AVAssetWriter,以便可以录制视频。
视图控制器上具有椭圆形状,因此用户知道将脸放在何处。当眼距在一定距离之间时,我希望椭圆变成蓝色,以便用户知道他们的脸在正确的位置。
目前,我已经通过从SessionHandler类向视图控制器发送通知来实现这一点。此方法有效,但是会导致视频中的每秒帧严重下降。我的速度是25fps(由我手动设置),现在是8-16。
还有没有其他方法可以通知视图控制器椭圆应该变为绿色?
这是发生问题的我的代码。我知道发生了很多事。
// MARK: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAudioOutputSampleBufferDelegate
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
if !currentMetadata.isEmpty {
let boundsArray = currentMetadata
.compactMap { $0 as? AVMetadataFaceObject }
.map { (faceObject) -> NSValue in
let convertedObject = output.transformedMetadataObject(for: faceObject, connection: connection)
return NSValue(cgRect: convertedObject!.bounds)
}
if user.hasDlib {
wrapper?.doWork(on: sampleBuffer, inRects: boundsArray)
// Get the interocular distance so face is the correct place in the oval
let interocularDistance = wrapper?.getEyeDistance()
//print("Interocular Distance: \(interocularDistance)")
if user.hasInterocularDistance {
if interocularDistance! < 240 || interocularDistance! > 315 {
let name = Notification.Name(rawValue: setRemoveGreenEllipse)
NotificationCenter.default.post(name: name, object: nil)
//print("face not correct distance")
if videoRecorder.isRecording {
eyeDistanceCounter += 1
//print(eyeDistanceCounter)
if eyeDistanceCounter == 30 {
cancelledByUser = false
cancelledByEyeDistance = true
videoRecorder.cancel()
eyeDistanceCounter = 0
}
}
} else {
//print("face correct distance")
eyeDistanceCounter = 0
let name = Notification.Name(rawValue: setGreenEllipse)
NotificationCenter.default.post(name: name, object: nil)
}
}
}
} else {
// Check if face is detected during recording. If it isn't, then cancel recording
if videoRecorder.isRecording {
noFaceCount += 1
if noFaceCount == 50 {
cancelledByUser = false
videoRecorder.cancel()
noFaceCount = 0
}
}
}
if layer.status == .failed {
layer.flush()
}
layer.enqueue(sampleBuffer)
let writable = videoRecorder.canWrite()
if writable {
if videoRecorder.sessionAtSourceTime == nil {
// Start Writing
videoRecorder.sessionAtSourceTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
videoRecorder.videoWriter.startSession(atSourceTime: videoRecorder.sessionAtSourceTime!)
print("video session started")
}
if videoRecorder.videoWriterInput.isReadyForMoreMediaData {
// write video buffer
videoRecorder.videoWriterInput.append(sampleBuffer)
//print("video buffering")
}
}
}
答案 0 :(得分:0)
例如,您可能每30帧调用一次通知,而不是每帧调用一次。
如果在同一视图控制器中,则还可以直接调用颜色更改功能。如果没有,您可以定义一个委托方法并直接反对发送通知。