人脸识别与人脸检测(都是采用系统的方法)

这篇文章的人脸识别与人脸检测并不能进行高层次,高深度的操作,只是可以用来识别摄像头拍摄时是否有人脸存在,以及后期对于人脸的检测。然并不能去判断这个人在这图上出现几次,是否是同一个人。。仅用于学习系统对于人脸的开发的方法

1:对于人脸的识别

首先预加载一些输入,输出的属性

1.1 加载摄像头

-(AVCaptureDevice *)cameraDevice {

if (_cameraDevice == nil) {

_cameraDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

NSError *error = nil;

if ([_cameraDevice lockForConfiguration:&error]) {

if ([_cameraDevice isSmoothAutoFocusSupported]) {// 平滑对焦

_cameraDevice.smoothAutoFocusEnabled = YES;

}

if ([_cameraDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {// 自动持续对焦

_cameraDevice.focusMode = AVCaptureFocusModeContinuousAutoFocus;

}

if ([_cameraDevice isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure ]) {// 自动持续曝光

_cameraDevice.exposureMode = AVCaptureExposureModeContinuousAutoExposure;}

if ([_cameraDevice isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance]) {// 自动持续白平衡

_cameraDevice.whiteBalanceMode = AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance;

}

[_cameraDevice unlockForConfiguration];

}}

return _cameraDevice;}


1.2 加载 核心组件AVCaptureSession

-(AVCaptureSession *)session {

if (_session == nil) {

_session = [[AVCaptureSession alloc] init];

_session.sessionPreset = AVCaptureSessionPresetHigh;

// 2、设置输入:由于模拟器没有摄像头,因此最好做一个判断

NSError *error = nil;

AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:self.cameraDevice error:&error];

//        [_device unlockForConfiguration];

if (error) {

NSLog(@"没有摄像设备");

}else {

if ([_session canAddInput:input]) {

[_session addInput:input];

NSError *error = nil;

[_cameraDevice lockForConfiguration:&error];

//调焦距,放大焦距

if (_cameraDevice.activeFormat.videoMaxZoomFactor > 2) {

_cameraDevice.videoZoomFactor = 2;

}else{

_cameraDevice.videoZoomFactor =_cameraDevice.activeFormat.videoMaxZoomFactor;

}}

if ([_session canAddOutput:self.videoDataOutput]) {

[_session addOutput:self.videoDataOutput];

}

if ([_session canAddOutput:self.metadataOutput]) {

[_session addOutput:self.metadataOutput];

}}}

return _session;

}

1.3  加载其他输出AVCaptureVideoDataOutput,AVCaptureMetadataOutput

-(AVCaptureMetadataOutput *)metadataOutput {

if (_metadataOutput == nil) {

_metadataOutput = [[AVCaptureMetadataOutput alloc]init];

[_metadataOutput setMetadataObjectsDelegate:self queue:self.queue];

}

return _metadataOutput;

}


-(AVCaptureVideoDataOutput *)videoDataOutput {

if (_videoDataOutput == nil) {

_videoDataOutput = [[AVCaptureVideoDataOutput alloc] init];

_videoDataOutput.alwaysDiscardsLateVideoFrames = YES;

_videoDataOutput.videoSettings = @{(id)kCVPixelBufferPixelFormatTypeKey:self.outPutSetting};

}

return _videoDataOutput;

}

1.3 session的开始,与停止

[self.session startRunning];

[self.session stopRunning];

1.4 温馨提示:加入对于摄像头权限的判断


2 人脸识别(系统)AVCaptureMetadataOutputObjectsDelegate 主要是这个代理方法,大家可以去看看这个API

2.1 这个方法用于检测摄像头里是否存在人脸

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{

if (metadataObjects.count) {

AVMetadataMachineReadableCodeObject *metadataObject = metadataObjects.firstObject;

AVMetadataObject *transformedMetadataObject = [self.previewLayer transformedMetadataObjectForMetadataObject:metadataObject];

CGRect faceRegion = transformedMetadataObject.bounds;

if (metadataObject.type == AVMetadataObjectTypeFace) {

NSLog(@"是否包含头像:%d, facePathRect: %@, faceRegion: %@",CGRectContainsRect(self.faceDetectionFrame, faceRegion),NSStringFromCGRect(self.faceDetectionFrame),NSStringFromCGRect(faceRegion));

// 为videoDataOutput设置代理,程序就会自动调用下面的代理方法,捕获每一帧图像

NSLog(@"%@", metadataObjects);

if (!self.videoDataOutput.sampleBufferDelegate) {

[self.videoDataOutput setSampleBufferDelegate:self queue:self.queue];

}}}}

2.2  从输出的数据流捕捉单一的图像帧,回调频率很快。AVCaptureVideoDataOutputSampleBufferDelegate

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {

if ([self.outPutSetting isEqualToNumber:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange]] || [self.outPutSetting isEqualToNumber:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange]]) {

CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

if ([captureOutput isEqual:self.videoDataOutput]) {

UIImage *image = [UIImage getImageStream:imageBuffer];//获取到人脸图片了

// 图片获取将videoDataOutput的代理去掉,防止频繁调用AVCaptureVideoDataOutputSampleBufferDelegate方法而引起的“混乱”

if (self.videoDataOutput.sampleBufferDelegate) {

[self.videoDataOutput setSampleBufferDelegate:nil queue:self.queue];

}}} else {

NSLog(@"输出格式不支持");

}}

2.3 至此,我们已经从摄像头中检测到了人脸的图片了,但是却无法进行人脸的识别,因此我们要用到ciimage


3 .人脸检测

3.1 由于摄像头获取的图片比较大,我们要将图片进行压缩,最好是保证图片控件的大小跟图片压缩之后的一致

- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize

{

UIImage *sourceImage = _IDImage;

UIImage *newImage = nil;

CGSize imageSize = sourceImage.size;

CGFloat width = imageSize.width;

CGFloat height = imageSize.height;

CGFloat targetWidth = targetSize.width;

CGFloat targetHeight = targetSize.height;

CGFloat scaleFactor = 0.0;

CGFloat scaledWidth = targetWidth;

CGFloat scaledHeight = targetHeight;

CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

if (CGSizeEqualToSize(imageSize, targetSize) == NO)

{

CGFloat widthFactor = targetWidth / width;

CGFloat heightFactor = targetHeight / height;

if (widthFactor > heightFactor)

scaleFactor = widthFactor; // scale to fit height

else

scaleFactor = heightFactor; // scale to fit width

scaledWidth= width * scaleFactor;

scaledHeight = height * scaleFactor;

// center the image

if (widthFactor > heightFactor)

{

thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;

}

else if (widthFactor < heightFactor)

{

thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;

}

}

UIGraphicsBeginImageContext(targetSize); // this will crop

CGRect thumbnailRect = CGRectZero;

thumbnailRect.origin = thumbnailPoint;

thumbnailRect.size.width= scaledWidth;

thumbnailRect.size.height = scaledHeight;

[sourceImage drawInRect:thumbnailRect];

newImage = UIGraphicsGetImageFromCurrentImageContext();

if(newImage == nil)

NSLog(@"could not scale image");

//pop the context to get back to the default

UIGraphicsEndImageContext();

return newImage;

}


3.2 人脸检测 featuresInImage,CIFaceFeature

-(void)recognitionFaces{

CIContext * context = [CIContext contextWithOptions:nil];

UIImage * imageInput = [_IDImageView image];

CIImage * image = [CIImage imageWithCGImage:imageInput.CGImage];

NSDictionary * param = [NSDictionary dictionaryWithObject:CIDetectorAccuracyHigh forKey:CIDetectorAccuracy];

CIDetector * faceDetector = [CIDetector detectorOfType:CIDetectorTypeFace context:context options:param];

NSArray * detectResult = [faceDetector featuresInImage:image];//主要方法

UIView * resultView = [[UIView alloc] initWithFrame:CGRectMake(10, 135.5, 355, 238)];//_IDImageView.frame一致

[self.view addSubview:resultView];

for (CIFaceFeature * faceFeature in detectResult) {

//detectResult 这个数组就是有多少个人头

UIView *faceView = [[UIView alloc] initWithFrame:faceFeature.bounds];//脸

faceView.layer.borderColor = [UIColor redColor].CGColor;

faceView.layer.borderWidth = 1;

[resultView addSubview:faceView];

if (faceFeature.hasLeftEyePosition) {

UIView * leftEyeView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 5)];//左眼

[leftEyeView setCenter:faceFeature.leftEyePosition];

leftEyeView.layer.borderWidth = 1;

leftEyeView.layer.borderColor = [UIColor redColor].CGColor;

[resultView addSubview:leftEyeView];

}

if (faceFeature.hasRightEyePosition) {

//右眼

UIView * rightEyeView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 5)];

[rightEyeView setCenter:faceFeature.rightEyePosition];

rightEyeView.layer.borderWidth = 1;

rightEyeView.layer.borderColor = [UIColor redColor].CGColor;

[resultView addSubview:rightEyeView];

}

if (faceFeature.hasMouthPosition) {

UIView * mouthView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 5)];

[mouthView setCenter:faceFeature.mouthPosition];

mouthView.layer.borderWidth = 1;

mouthView.layer.borderColor = [UIColor redColor].CGColor;

[resultView addSubview:mouthView];

}

}

[resultView setTransform:CGAffineTransformMakeScale(1, -1)];

}

这样我们就结束了,附上demo图一张


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容