人脸识别特指利用分析比较人脸视觉特征信息进行身份鉴别的计算机技术,主要用于身份识别。采用快速人脸检测技术可以从监控视频图像中实时查找人脸,并与人脸数据库进行实时比对,从而实现快速身份识别。
人脸的识别过程一般分以下3个步骤:
(1)首先建立人脸的面纹数据库。可以通过照相机或摄像机采集人脸的面像图片,将这些面像图片生成面纹编码保存到数据库中。
(2)获取当前人脸面像图片。即通过照相机或摄像机采集人脸的面像图片,将当前的面像文件生成面纹编码。
(3)用当前的面纹编码与数据库中的面纹编码进行比对。
由于面纹编码不受抗光线、皮肤色调、面部毛发、发型、眼镜、表情和姿态变化的影响,具有可靠性强,从而使其可以精确地辨认出某个人。
在iOS 5之后提供人脸识别的API,通过提供的CIDetector类可以进行人脸特征识别,CIDetector是Core Image框架中的一个特征识别滤镜,CIDetector主要用于人脸特征识别,通过它还可以获得眼睛和嘴的特征信息。但是CIDetector并不包括面纹编码提取,面纹编码提取还需要更为复杂的算法处理。也就是说使用CIDetector类可以找到一张图片中的人脸,但是这张脸是谁,CIDetector无法判断,这需要有一个面纹数据库,把当前人脸提取面纹编码然后与数据库进行比对,这些内容超出了本书的范围,我们不再介绍了。
在此之前iOS开发这方面的应用可以采用OpenCV和Face.com。其中,OpenCV(http://opencv.org/)是开源的C编写的图像处理和识别库,它提供了图像处理和计算机视觉方面的很多通用算法。Face.com提供了在线方式人脸识别服务,开发人员需要在Face.com网站注册key,才可以使用REST Web Service风格的API,提交人脸图片,Face.com返回识别结果。
下面通过一个具体的实例介绍使用CIDetector识别人脸过程,如图3-9所示。屏幕的上半部分是要识别的图片,为了进行比较图片中一个小女孩和一只猩猩,正常情况下应该只能识别出小女孩的脸。单击识别按钮可以将识别出来的脸图片放置在屏幕的下半部分显示出来。
图3-9 人脸识别实例
首先使用Xcode选择Single View Application工程模板,创建一个FaceDetect工程。具体的UI设计过程不再赘述,重点看看代码部分。其中视图控制器类ViewController.h代码如下所示。
@interface ViewController: UIViewController @property (retain, nonatomic) IBOutlet UIImageView *inputImageView; @property (retain, nonatomic) IBOutlet UIImageView *outputImageView; @property (retain, nonatomic) IBOutlet UIButton *button; - (IBAction)detect:(id)sender; @end
视图控制器ViewController.m中,单击识别按钮调用方法detect:,代码如下所示。
- (IBAction)detect:(id)sender { CIContext *context = [CIContext contextWithOptions:nil]; UIImage *imageInput = [_inputImageView image]; CIImage *image = [CIImage imageWithCGImage:imageInput.CGImage]; //设置识别参数 NSDictionary *param = [NSDictionary dictionaryWithObject:CIDetectorAccuracyHigh forKey:CIDetectorAccuracy]; ① //声明一个CIDetector,并设定识别类型 CIDetector* faceDetector = [CIDetector detectorOfType:CIDetectorTypeFace context:context options:param]; ② //取得识别结果 NSArray *detectResult = [faceDetector featuresInImage:image]; ③ UIView *resultView = [[UIView alloc] initWithFrame:_inputImageView.frame]; ④ [self.view addSubview:resultView]; for(CIFaceFeature* faceFeature in detectResult) { ⑤ //脸部 UIView* faceView = [[UIView alloc] initWithFrame:faceFeature.bounds]; faceView.layer.borderWidth = 1; faceView.layer.borderColor = [UIColor orangeColor].CGColor; [resultView addSubview:faceView]; [faceView release]; //左眼 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]; [leftEyeView release]; } //右眼 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]; [rightEyeView release]; } //嘴巴 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]; [mouthView release]; } } [resultView setTransform:CGAffineTransformMakeScale(1, -1)]; ⑧ [resultView release]; if ([detectResult count]> 0) ⑨ { CIImage *faceImage = [image imageByCroppingToRect: [[detectResult objectAtIndex:0] bounds]]; ⑩ UIImage *face = [UIImage imageWithCGImage: [context createCGImage:faceImage fromRect:faceImage.extent]]; self.outputImageView.image = face; [self.button setTitle:[NSString stringWithFormat:@"识别 人脸数 %i", [detectResult count]] forState:UIControlStateNormal]; } }
其中,第①行代码是准备识别参数,参数是放在NSDictionary中的,本例中的CIDetectorAccuracy代表识别精度,CIDetectorAccuracyHigh代表识别精度为“高”。
第②行代码是创建CIDetector对象,需要指定识别类型,目前只有CIDetectorTypeFace类型(人脸类型)。
第③行代码NSArray *detectResult=[faceDetector featuresInImage:image]是进行识别,识别的结果放到NSArray集合中,集合中的每一个元素是CIFaceFeature类型。
第④行代码创建一个UIView对象,将在上面标识出脸、眼睛和嘴巴的位置。
第⑤行代码是从NSArray集合中取出CIFaceFeature元素,CIFaceFeature元素代表一个识别出来的对象。
第⑥行代码faceFeature.hasLeftEyePosition是判断是否识别左眼,类似还有faceFeature.hasRightEyePosition判断是否识别右眼,faceFeature.hasMouthPosition判断是否识别嘴巴。
第⑦行代码faceFeature.leftEyePosition是获得左眼的位置,类似还有faceFeature.rightEyePosition获得右眼的位置,faceFeature.mouthPosition获得嘴巴的位置。
第⑧行代码[resultView setTransform:CGAffineTransformMakeScale(1,-1)]是沿 y 轴进行镜像变换,因为Core Image坐标是在左下角,UIKit的坐标在左上角,需要进行坐标变换。
第⑨行之后的处理是将识别出来的脸部图像,显示在屏幕的下半部分。
第⑩行代码是CIImage * faceImage=[image imageByCroppingToRect:[[detectResult objectAtIndex:0] bounds]],是从识别出人脸位置中裁剪出CIImage图像,其中,[detectResult objectAtIndex:0]是取出第一个识别出来的CIFaceFeature对象,CIFaceFeature对象的bounds方法可以获得其位置信息。imageByCroppingToRect:方法可以按照指定的矩形裁剪CIImage图像。