I am trying to make a simple camera application where the front camera can detect faces. This should be simple enough:
Create a CameraView class that inherits from UIImage and places it in the user interface. Make sure that it implements AVCaptureVideoDataOutputSampleBufferDelegate to process camera frames in real time.
class CameraView: UIImageView, AVCaptureVideoDataOutputSampleBufferDelegate
Inside the handleCamera function that is called when the CameraView is instantiated, configure an AVCapture session. Add camera input.
override init(frame: CGRect) {
super.init(frame:frame)
handleCamera()
}
func handleCamera () {
camera = AVCaptureDevice.defaultDevice(withDeviceType: .builtInWideAngleCamera,
mediaType: AVMediaTypeVideo, position: .front)
session = AVCaptureSession()
do {
try input = AVCaptureDeviceInput(device: camera);
} catch _ as NSError {
print ("ERROR: Front camera can't be used as input")
input = nil
}
if (session?.canAddInput(input) == true) {
session?.addInput(input)
}
Create a conclusion. Create a sequential output queue to pass data that will then be processed using AVCaptureVideoDataOutputSampleBufferDelegate (in this case the class itself). Add output to the session.
output = AVCaptureVideoDataOutput()
output?.alwaysDiscardsLateVideoFrames = true
outputQueue = DispatchQueue(label: "outputQueue")
output?.setSampleBufferDelegate(self, queue: outputQueue)
if(session?.canAddOutput(output) == true){
session?.addOutput(output)
}
else {
print("ERROR: Output not viable")
}
previewLayer = AVCaptureVideoPreviewLayer(session: session)
previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
previewLayer?.connection.videoOrientation = AVCaptureVideoOrientation.portrait
previewLayer?.frame = self.bounds
self.layer.addSublayer(previewLayer!)
session?.startRunning()
captureOutput, , CIImage . , .
func captureOutput(_ captureOutput: AVCaptureOutput!, didDrop sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
let cameraImage = CIImage(cvPixelBuffer: pixelBuffer!)
let accuracy = [CIDetectorAccuracy: CIDetectorAccuracyHigh]
let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: accuracy)
let faces = faceDetector?.features(in: cameraImage)
for face in faces as! [CIFaceFeature] {
print("Found bounds are \(face.bounds)")
let faceBox = UIView(frame: face.bounds)
faceBox.layer.borderWidth = 3
faceBox.layer.borderColor = UIColor.red.cgColor
faceBox.backgroundColor = UIColor.clear
self.addSubview(faceBox)
if face.hasLeftEyePosition {
print("Left eye bounds are \(face.leftEyePosition)")
}
if face.hasRightEyePosition {
print("Right eye bounds are \(face.rightEyePosition)")
}
}
}
: , , , captureOutput, . , - , , , sampleBuffer nul.
?