[iOS] 안면 인식 (CIDetector)
코어 이미지는 이미지나 비디오에서
얼굴이나 얼굴의 특징을 탐지할 수 있는 기능을 제공한다.
안면 인식기 설정
코어 이미지에서 안면 인식기를 사용하려면 CIImage 객체가 필요하다.
UIImage *detectUIImage = [self.sourceImageView image];
CGImageRef detectCGImageRef = [detectUIImage CGImage];
CIImage *detectImage = [CIImage imageWithCGImage:detectCGImageRef];
NSDictionary *options = @{CIDetectorAccuracy : CIDetectorAccuracyHigh};
CIDetector *faceDetector = [CIDetector detectorOfType:CIDetectorTypeFace
context:nil
options:options];
NSArray *features = [faceDetector featuresInImage:detectImage];
안면 인식 기능은 CIDetector 가 제공하는데, 현재는 Face 이외에 아래 4가지가 있다.
CORE_IMAGE_EXPORT NSString* const CIDetectorTypeFace NS_AVAILABLE(10_7, 5_0);
CORE_IMAGE_EXPORT NSString* const CIDetectorTypeRectangle NS_AVAILABLE(10_10, 8_0);
CORE_IMAGE_EXPORT NSString* const CIDetectorTypeQRCode NS_AVAILABLE(10_10, 8_0);
CORE_IMAGE_EXPORT NSString* const CIDetectorTypeText NS_AVAILABLE(10_11, 9_0);
options 으로는 Accuracy 를 줄 수 있는데, 높을수록 시간이 오래 걸린다.
안면 특징 처리
NSArray *features = [faceDetector featuresInImage:detectImage];
에서 나온 features 들은 측정된 안면 개수만큼 나온다.
for (CIFaceFeature *face in features) {
CGRect faceRect = [self adjustCoordinateSpaceForMarker:face.bounds
andHeight:detectImage.extent.size.height];
UIView *faceMarker = [[UIView alloc] initWithFrame:faceRect];
faceMarker.layer.borderWidth = 2;
faceMarker.layer.borderColor = [[UIColor redColor] CGColor];
[self.sourceImageView addSubview:faceMarker];
if (face.hasLeftEyePosition) {
CGFloat leftEyeXPos = face.leftEyePosition.x - kEyeMarkerWidth/2;
CGFloat leftEyeYPos = face.leftEyePosition.y - kEyeMarkerWidth/2;
CGRect leftEyeRect =
CGRectMake(leftEyeXPos, leftEyeYPos, kEyeMarkerWidth, kEyeMarkerWidth);
CGRect flippedLeftEyeRect = [self adjustCoordinateSpaceForMarker:leftEyeRect
andHeight:self.sourceImageView.bounds.size.height];
UIView *leftEyeMarker = [[UIView alloc] initWithFrame:flippedLeftEyeRect];
leftEyeMarker.layer.borderWidth = 2;
leftEyeMarker.layer.borderColor = [[UIColor yellowColor] CGColor];
[self.sourceImageView addSubview:leftEyeMarker];
}
//hasRightEyePosition, hasMouthPosition 도 마찬가지..
face 의 크기는 측정해주지만, 눈의 크기는 측정해주지 않기 때문에 임의의 수로 rect 를 그리고 있다.
코어 이미지는 UIKit 과는 다른 좌표 시스템을 사용한다.
코어 이미지의 좌표 시스템에서는 수직 방향 (Y축) 이 뒤집혀 있다.
따라서 좌표값이 0인 위치는 이미지의 상단이 아니고 하단이다.
이를 보정해 주는 코드는 아래에 있다.
- (CGRect)adjustCoordinateSpaceForMarker:(CGRect)marker andHeight:(CGFloat)height {
CGAffineTransform scale = CGAffineTransformMakeScale(1, -1);
CGAffineTransform flip =
CGAffineTransformTranslate(scale, 0, -height);
CGRect flippedRect = CGRectApplyAffineTransform(marker, flip);
return flippedRect;
}
iOS 7 이상에서는 탐지한 얼굴이 미소짓고 있는지 (hasSmile),
눈을 깜박이고 있는지 (leftEyeClosed, rightEyeClosed) 도 가지고 있다.