swift通过摄像头读取每一帧的图片,并且做识别做人脸识别

jopen 9年前

最近帮别人做一个项目,主要是使用摄像头做人脸识别

github地址:https://github.com/qugang/AVCaptureVideoTemplate

要使用IOS的摄像头,需要使用AVFoundation 库,库里面的东西我就不介绍。

启动摄像头需要使用AVCaptureSession 类。

然后得到摄像头传输的每一帧数据,需要使用AVCaptureVideoDataOutputSampleBufferDelegate 委托。

首先在viewDidLoad 里添加找摄像头设备的代码,找到摄像头设备以后,开启摄像头

captureSession.sessionPreset = AVCaptureSessionPresetLow  let devices = AVCaptureDevice.devices()  for device in devices {    if (device.hasMediaType(AVMediaTypeVideo)) {      if (device.position == AVCaptureDevicePosition.Front) {        captureDevice = device as?AVCaptureDevice        if captureDevice != nil {          println("Capture Device found")          beginSession()        }      }    }  }

beginSession,开启摄像头:

func beginSession() {    var err : NSError? = nil    captureSession.addInput(AVCaptureDeviceInput(device: captureDevice, error: &err))    let output = AVCaptureVideoDataOutput()    let cameraQueue = dispatch_queue_create("cameraQueue", DISPATCH_QUEUE_SERIAL)    output.setSampleBufferDelegate(self, queue: cameraQueue)    output.videoSettings = [kCVPixelBufferPixelFormatTypeKey: kCVPixelFormatType_32BGRA]    captureSession.addOutput(output)    if err != nil {      println("error: \(err?.localizedDescription)")    }    previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)    previewLayer?.videoGravity = "AVLayerVideoGravityResizeAspect"    previewLayer?.frame = self.view.bounds    self.view.layer.addSublayer(previewLayer)    captureSession.startRunning()  }

开启以后,实现captureOutput 方法:

func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {    if(self.isStart)    {      let resultImage = sampleBufferToImage(sampleBuffer)      let context = CIContext(options:[kCIContextUseSoftwareRenderer:true])      let detecotr = CIDetector(ofType:CIDetectorTypeFace,  context:context, options:[CIDetectorAccuracy: CIDetectorAccuracyHigh])      let ciImage = CIImage(image: resultImage)      let results:NSArray = detecotr.featuresInImage(ciImage,options: ["CIDetectorImageOrientation" : 6])      for r in results {        let face:CIFaceFeature = r as! CIFaceFeature;        let faceImage = UIImage(CGImage: context.createCGImage(ciImage, fromRect: face.bounds),scale: 1.0, orientation: .Right)        NSLog("Face found at (%f,%f) of dimensions %fx%f", face.bounds.origin.x, face.bounds.origin.y,pickUIImager.frame.origin.x, pickUIImager.frame.origin.y)        dispatch_async(dispatch_get_main_queue()) {          if (self.isStart)          {            self.dismissViewControllerAnimated(true, completion: nil)            self.didReceiveMemoryWarning()            self.callBack!(face: faceImage!)          }          self.isStart = false        }      }    }  }

在每一帧图片上使用CIDetector 得到人脸,CIDetector 还可以得到眨眼,与微笑的人脸,如果要详细使用去官方查看API

上面就是关键代码,设置了有2秒的延迟,2秒之后开始人脸检测。

全部代码:

//  //  ViewController.swift  //  AVSessionTest  //  //  Created by qugang on 15/7/8.  //  Copyright (c) 2015年 qugang. All rights reserved.  //    import UIKit  import AVFoundation  class AVCaptireVideoPicController: UIViewController,AVCaptureVideoDataOutputSampleBufferDelegate {    var callBack :((face: UIImage) ->())?    let captureSession = AVCaptureSession()    var captureDevice : AVCaptureDevice?    var previewLayer : AVCaptureVideoPreviewLayer?    var pickUIImager : UIImageView = UIImageView(image: UIImage(named: "pick_bg"))    var line : UIImageView = UIImageView(image: UIImage(named: "line"))    var timer : NSTimer!    var upOrdown = true    var isStart = false    override func viewDidLoad() {      super.viewDidLoad()      captureSession.sessionPreset = AVCaptureSessionPresetLow      let devices = AVCaptureDevice.devices()      for device in devices {        if (device.hasMediaType(AVMediaTypeVideo)) {          if (device.position == AVCaptureDevicePosition.Front) {            captureDevice = device as?AVCaptureDevice            if captureDevice != nil {              println("Capture Device found")              beginSession()            }          }        }      }      pickUIImager.frame = CGRect(x: self.view.bounds.width / 2 - 100, y: self.view.bounds.height / 2 - 100,width: 200,height: 200)      line.frame = CGRect(x: self.view.bounds.width / 2 - 100, y: self.view.bounds.height / 2 - 100, width: 200, height: 2)      self.view.addSubview(pickUIImager)      self.view.addSubview(line)      timer =  NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "animationSate", userInfo: nil, repeats: true)            NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: "isStartTrue", userInfo: nil, repeats: false)    }    func isStartTrue(){      self.isStart = true    }    override func didReceiveMemoryWarning(){      super.didReceiveMemoryWarning()      captureSession.stopRunning()    }        func animationSate(){      if upOrdown {        if (line.frame.origin.y >= pickUIImager.frame.origin.y + 200)        {          upOrdown = false        }        else        {          line.frame.origin.y += 2        }      } else {        if (line.frame.origin.y <= pickUIImager.frame.origin.y)        {          upOrdown = true        }        else        {          line.frame.origin.y -= 2        }      }    }    func beginSession() {      var err : NSError? = nil      captureSession.addInput(AVCaptureDeviceInput(device: captureDevice, error: &err))      let output = AVCaptureVideoDataOutput()      let cameraQueue = dispatch_queue_create("cameraQueue", DISPATCH_QUEUE_SERIAL)      output.setSampleBufferDelegate(self, queue: cameraQueue)      output.videoSettings = [kCVPixelBufferPixelFormatTypeKey: kCVPixelFormatType_32BGRA]      captureSession.addOutput(output)      if err != nil {        println("error: \(err?.localizedDescription)")      }      previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)      previewLayer?.videoGravity = "AVLayerVideoGravityResizeAspect"      previewLayer?.frame = self.view.bounds      self.view.layer.addSublayer(previewLayer)      captureSession.startRunning()    }    func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {      if(self.isStart)      {        let resultImage = sampleBufferToImage(sampleBuffer)        let context = CIContext(options:[kCIContextUseSoftwareRenderer:true])        let detecotr = CIDetector(ofType:CIDetectorTypeFace,  context:context, options:[CIDetectorAccuracy: CIDetectorAccuracyHigh])        let ciImage = CIImage(image: resultImage)        let results:NSArray = detecotr.featuresInImage(ciImage,options: ["CIDetectorImageOrientation" : 6])        for r in results {          let face:CIFaceFeature = r as! CIFaceFeature;          let faceImage = UIImage(CGImage: context.createCGImage(ciImage, fromRect: face.bounds),scale: 1.0, orientation: .Right)          NSLog("Face found at (%f,%f) of dimensions %fx%f", face.bounds.origin.x, face.bounds.origin.y,pickUIImager.frame.origin.x, pickUIImager.frame.origin.y)          dispatch_async(dispatch_get_main_queue()) {            if (self.isStart)            {              self.dismissViewControllerAnimated(true, completion: nil)              self.didReceiveMemoryWarning()              self.callBack!(face: faceImage!)            }            self.isStart = false          }        }      }    }    private func sampleBufferToImage(sampleBuffer: CMSampleBuffer!) -> UIImage {      let imageBuffer: CVImageBufferRef = CMSampleBufferGetImageBuffer(sampleBuffer)      CVPixelBufferLockBaseAddress(imageBuffer, 0)      let baseAddress = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0)      let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer)      let width = CVPixelBufferGetWidth(imageBuffer)      let height = CVPixelBufferGetHeight(imageBuffer)      let colorSpace: CGColorSpaceRef = CGColorSpaceCreateDeviceRGB()      let bitsPerCompornent = 8      var bitmapInfo = CGBitmapInfo((CGBitmapInfo.ByteOrder32Little.rawValue | CGImageAlphaInfo.PremultipliedFirst.rawValue) as UInt32)      let newContext = CGBitmapContextCreate(baseAddress, width, height, bitsPerCompornent, bytesPerRow, colorSpace, bitmapInfo) as CGContextRef      let imageRef: CGImageRef = CGBitmapContextCreateImage(newContext)      let resultImage = UIImage(CGImage: imageRef, scale: 1.0, orientation: UIImageOrientation.Right)!      return resultImage    }    func imageResize (imageObj:UIImage, sizeChange:CGSize)-> UIImage{      let hasAlpha = false      let scale: CGFloat = 0.0             UIGraphicsBeginImageContextWithOptions(sizeChange, !hasAlpha, scale)      imageObj.drawInRect(CGRect(origin: CGPointZero, size: sizeChange))      let scaledImage = UIGraphicsGetImageFromCurrentImageContext()      return scaledImage    }  }