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

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

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

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

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

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

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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

captureSession.sessionPreset = AVCaptureSessionPresetLow

let devices = AVCaptureDevice.devices()

fordevice in devices {

if(device.hasMediaType(AVMediaTypeVideo)) {

if(device.position == AVCaptureDevicePosition.Front) {

captureDevice = device as?AVCaptureDevice

ifcaptureDevice != nil {

println("Capture Device found")

beginSession()

}

}

}

}

beginSession,开启摄像头:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

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)

iferr != 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 方法:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

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])

forr 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秒之后开始人脸检测。

全部代码:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

//

// ViewController.swift

// AVSessionTest

//

// Created by qugang on 15/7/8.

// Copyright (c) 2015年 qugang. All rights reserved.

//

import UIKit

import AVFoundation

classAVCaptireVideoPicController: 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()

fordevice in devices {

if(device.hasMediaType(AVMediaTypeVideo)) {

if(device.position == AVCaptureDevicePosition.Front) {

captureDevice = device as?AVCaptureDevice

ifcaptureDevice != 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(){

ifupOrdown {

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)

iferr != 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])

forr 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

}

}

}

}

privatefunc 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)!

returnresultImage

}

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()

returnscaledImage

}

}