iOS에서 ML Kit를 사용하여 얼굴 인식

ML Kit를 사용하면 이미지 및 동영상에서 얼굴을 감지할 수 있습니다.

사용해 보기

  • 샘플 앱을 사용하여 이 API의 사용 예를 참조하세요.
  • Codelab을 참고하세요.

시작하기 전에

  1. Podfile에 다음 ML Kit 포드를 포함합니다.
    pod 'GoogleMLKit/FaceDetection', '3.2.0'
    
  2. 프로젝트의 포드를 설치하거나 업데이트한 후 포드를 사용하여 Xcode 프로젝트를 엽니다. .xcworkspace ML Kit는 Xcode 버전 12.4 이상에서 지원됩니다.

입력 이미지 가이드라인

얼굴 인식에는 크기가 480x360픽셀 이상인 이미지를 사용해야 합니다. ML Kit가 얼굴을 정확하게 인식하려면 입력 이미지에 얼굴이 있어야 합니다. 표시할 수 있습니다. 일반적으로 원하는 모든 얼굴 최소 100x100픽셀이어야 합니다. 감지하려는 경우 ML Kit에는 더 높은 해상도의 입력이 필요합니다. 최소 200x200픽셀이어야 합니다.

실시간 애플리케이션에서 얼굴을 인식하는 경우 입력 이미지의 전체 크기를 고려하세요 더 작은 이미지는 지연 시간을 줄이기 위해 낮은 해상도에서 이미지를 캡처하지만 위의 정확성 요건을 염두에 두고 피사체의 얼굴이 이미지의 가장 많은 부분을 차지합니다 참고 항목 실시간 성능 향상을 위한 팁을 참고하세요.

이미지 초점이 잘 맞지 않으면 정확도에 영향을 줄 수도 있습니다. 용인되지 않는 경우 사용자에게 이미지를 다시 캡처하도록 요청합니다.

카메라를 기준으로 한 얼굴의 방향은 ML Kit가 감지하는 특성을 파악할 수 있습니다 자세한 내용은 얼굴 인식 개념.

1. 얼굴 감지기 구성

이미지에 얼굴 인식 기능을 적용하기 전에 얼굴 인식기의 기본 설정에서 FaceDetectorOptions 객체 변경할 수 있습니다. 다음 설정을 변경합니다.

설정
performanceMode fast (기본값) | accurate

얼굴을 감지할 때 속도 또는 정확성을 우선시합니다.

landmarkMode none (기본값) | all

얼굴의 '특징'(눈, 얼굴 표정을 통해 감지됩니다.

contourMode none (기본값) | all

얼굴 특징의 윤곽을 감지할지 여부입니다. 윤곽선은 자동으로 감지됩니다.

classificationMode none (기본값) | all

얼굴을 '웃고 있음'과 같은 카테고리로 분류할 것인지 여부 '눈을 뜨고 있는 것'이 있습니다.

minFaceSize CGFloat(기본값: 0.1)

원하는 가장 작은 얼굴 크기를 이미지의 너비입니다.

isTrackingEnabled false (기본값) | true

얼굴에 ID를 할당할지 여부(추적에 사용할 수 있음) 여러 개의 이미지를 만들어 냅니다.

윤곽 인식이 사용 설정되면 얼굴 한 개만 유용한 결과가 나오지 않습니다. 이 작업 감지 속도를 높이기 위해 두 윤곽을 모두 사용 설정하지 마세요. 인식과 얼굴 추적을 지원합니다

예를 들어 FaceDetectorOptions를 빌드합니다. 객체를 사용할 수 있습니다.

Swift

// High-accuracy landmark detection and face classification
let options = FaceDetectorOptions()
options.performanceMode = .accurate
options.landmarkMode = .all
options.classificationMode = .all

// Real-time contour detection of multiple faces
// options.contourMode = .all

Objective-C

// High-accuracy landmark detection and face classification
MLKFaceDetectorOptions *options = [[MLKFaceDetectorOptions alloc] init];
options.performanceMode = MLKFaceDetectorPerformanceModeAccurate;
options.landmarkMode = MLKFaceDetectorLandmarkModeAll;
options.classificationMode = MLKFaceDetectorClassificationModeAll;

// Real-time contour detection of multiple faces
// options.contourMode = MLKFaceDetectorContourModeAll;

2. 입력 이미지 준비

이미지 속 얼굴을 인식하려면 이미지를 UIImage 또는 다음 중 하나를 사용하여 FaceDetectorCMSampleBufferRef를 추가합니다. process(_:completion:) 또는 results(in:) 메서드:

VisionImage 객체를 UIImage 또는 CMSampleBuffer입니다.

UIImage를 사용하는 경우 다음 단계를 따르세요.

  • UIImageVisionImage 객체를 만듭니다. 올바른 .orientation를 지정해야 합니다.

    Swift

    let image = VisionImage(image: UIImage)
    visionImage.orientation = image.imageOrientation

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

CMSampleBuffer를 사용하는 경우 다음 단계를 따르세요.

  • CMSampleBuffer

    이미지 방향을 가져오는 방법은 다음과 같습니다.

    Swift

    func imageOrientation(
      deviceOrientation: UIDeviceOrientation,
      cameraPosition: AVCaptureDevice.Position
    ) -> UIImage.Orientation {
      switch deviceOrientation {
      case .portrait:
        return cameraPosition == .front ? .leftMirrored : .right
      case .landscapeLeft:
        return cameraPosition == .front ? .downMirrored : .up
      case .portraitUpsideDown:
        return cameraPosition == .front ? .rightMirrored : .left
      case .landscapeRight:
        return cameraPosition == .front ? .upMirrored : .down
      case .faceDown, .faceUp, .unknown:
        return .up
      }
    }
          

    Objective-C

    - (UIImageOrientation)
      imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                             cameraPosition:(AVCaptureDevicePosition)cameraPosition {
      switch (deviceOrientation) {
        case UIDeviceOrientationPortrait:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored
                                                                : UIImageOrientationRight;
    
        case UIDeviceOrientationLandscapeLeft:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored
                                                                : UIImageOrientationUp;
        case UIDeviceOrientationPortraitUpsideDown:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored
                                                                : UIImageOrientationLeft;
        case UIDeviceOrientationLandscapeRight:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored
                                                                : UIImageOrientationDown;
        case UIDeviceOrientationUnknown:
        case UIDeviceOrientationFaceUp:
        case UIDeviceOrientationFaceDown:
          return UIImageOrientationUp;
      }
    }
          
  • 다음을 사용하여 VisionImage 객체를 만듭니다. CMSampleBuffer 객체 및 방향:

    Swift

    let image = VisionImage(buffer: sampleBuffer)
    image.orientation = imageOrientation(
      deviceOrientation: UIDevice.current.orientation,
      cameraPosition: cameraPosition)

    Objective-C

     MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer];
     image.orientation =
       [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                    cameraPosition:cameraPosition];

3. FaceDetector 인스턴스 가져오기

FaceDetector의 인스턴스를 가져옵니다.

Swift

let faceDetector = FaceDetector.faceDetector(options: options)

Objective-C

MLKFaceDetector *faceDetector = [MLKFaceDetector faceDetectorWithOptions:options];
      

4. 이미지 처리

그런 다음 이미지를 process() 메서드에 전달합니다.

Swift

weak var weakSelf = self
faceDetector.process(visionImage) { faces, error in
  guard let strongSelf = weakSelf else {
    print("Self is nil!")
    return
  }
  guard error == nil, let faces = faces, !faces.isEmpty else {
    // ...
    return
  }

  // Faces detected
  // ...
}

Objective-C

[faceDetector processImage:image
                completion:^(NSArray<MLKFace *> *faces,
                             NSError *error) {
  if (error != nil) {
    return;
  }
  if (faces.count > 0) {
    // Recognized faces
  }
}];

5. 감지된 얼굴에 관한 정보 얻기

얼굴 인식 작업이 성공하면 얼굴 인식기는 배열을 전달합니다. Face 객체를 완료 핸들러에 전달합니다. 각 Face 객체는 이미지에서 인식된 얼굴을 나타냅니다. 대상 입력 이미지에서 경계 좌표를 구할 수 있을 뿐만 아니라 얼굴 인식기가 찾도록 구성한 기타 모든 정보 예를 들면 다음과 같습니다.

Swift

for face in faces {
  let frame = face.frame
  if face.hasHeadEulerAngleX {
    let rotX = face.headEulerAngleX  // Head is rotated to the uptoward rotX degrees
  }
  if face.hasHeadEulerAngleY {
    let rotY = face.headEulerAngleY  // Head is rotated to the right rotY degrees
  }
  if face.hasHeadEulerAngleZ {
    let rotZ = face.headEulerAngleZ  // Head is tilted sideways rotZ degrees
  }

  // If landmark detection was enabled (mouth, ears, eyes, cheeks, and
  // nose available):
  if let leftEye = face.landmark(ofType: .leftEye) {
    let leftEyePosition = leftEye.position
  }

  // If contour detection was enabled:
  if let leftEyeContour = face.contour(ofType: .leftEye) {
    let leftEyePoints = leftEyeContour.points
  }
  if let upperLipBottomContour = face.contour(ofType: .upperLipBottom) {
    let upperLipBottomPoints = upperLipBottomContour.points
  }

  // If classification was enabled:
  if face.hasSmilingProbability {
    let smileProb = face.smilingProbability
  }
  if face.hasRightEyeOpenProbability {
    let rightEyeOpenProb = face.rightEyeOpenProbability
  }

  // If face tracking was enabled:
  if face.hasTrackingID {
    let trackingId = face.trackingID
  }
}

Objective-C

for (MLKFace *face in faces) {
  // Boundaries of face in image
  CGRect frame = face.frame;
  if (face.hasHeadEulerAngleX) {
    CGFloat rotX = face.headEulerAngleX;  // Head is rotated to the upward rotX degrees
  }
  if (face.hasHeadEulerAngleY) {
    CGFloat rotY = face.headEulerAngleY;  // Head is rotated to the right rotY degrees
  }
  if (face.hasHeadEulerAngleZ) {
    CGFloat rotZ = face.headEulerAngleZ;  // Head is tilted sideways rotZ degrees
  }

  // If landmark detection was enabled (mouth, ears, eyes, cheeks, and
  // nose available):
  MLKFaceLandmark *leftEar = [face landmarkOfType:FIRFaceLandmarkTypeLeftEar];
  if (leftEar != nil) {
    MLKVisionPoint *leftEarPosition = leftEar.position;
  }

  // If contour detection was enabled:
  MLKFaceContour *upperLipBottomContour = [face contourOfType:FIRFaceContourTypeUpperLipBottom];
  if (upperLipBottomContour != nil) {
    NSArray<MLKVisionPoint *> *upperLipBottomPoints = upperLipBottomContour.points;
    if (upperLipBottomPoints.count > 0) {
      NSLog("Detected the bottom contour of the subject's upper lip.")
    }
  }

  // If classification was enabled:
  if (face.hasSmilingProbability) {
    CGFloat smileProb = face.smilingProbability;
  }
  if (face.hasRightEyeOpenProbability) {
    CGFloat rightEyeOpenProb = face.rightEyeOpenProbability;
  }

  // If face tracking was enabled:
  if (face.hasTrackingID) {
    NSInteger trackingID = face.trackingID;
  }
}

얼굴 윤곽의 예

얼굴 윤곽 인식이 활성화된 경우 얼굴 특징을 각각 감지했습니다. 이 점들은 기능을 사용할 수 있습니다. 얼굴 윤곽에 대한 자세한 내용은 감지 개념을 참조하세요. 나타냅니다.

다음 이미지는 이 점들이 얼굴에 어떻게 매핑되는지 보여 줍니다. 이미지를 확대합니다.

감지된 얼굴 윤곽 메시 예

실시간 얼굴 인식

실시간 애플리케이션에서 얼굴 인식을 사용하려면 다음을 따르세요. 다음 가이드라인을 참조하세요.

  • 다음 중 하나를 사용하도록 얼굴 감지기 구성 얼굴 윤곽 인식 또는 분류와 특징 감지 중 한 가지만 선택할 수 있습니다.

    윤곽 인식
    랜드마크 인식
    분류
    랜드마크 인식 및 분류
    윤곽 인식 및 특징 인식
    윤곽 인식 및 분류
    윤곽 인식, 특징 인식, 분류

  • fast 모드를 사용 설정합니다 (기본적으로 사용 설정됨).

  • 낮은 해상도에서 이미지를 캡처하는 것이 좋습니다. 그러나 명심해야 할 점은 이 API의 이미지 크기 요구사항입니다.

  • 동영상 프레임을 처리하려면 감지기의 results(in:) 동기 API를 사용하세요. 전화걸기 AVCaptureVideoDataOutputSampleBufferDelegate님의 <ph type="x-smartling-placeholder"></ph> captureOutput(_, didOutput:from:) 함수를 사용하여 특정 동영상에서 동기식으로 결과를 가져옵니다. 있습니다. 유지 AVCaptureVideoDataOutput님의 alwaysDiscardsLateVideoFramestrue로 설정하여 감지기 호출을 제한합니다. 새 동영상 프레임은 감지기가 실행되는 동안 사용할 수 있게 되면 삭제됩니다.
  • 감지기 출력을 사용하여 그래픽 이미지를 먼저 ML Kit에서 결과를 가져온 후 이미지를 하나의 단계로 오버레이할 수 있습니다. 이렇게 하면 처리되어야 합니다 자세한 내용은 updatePreviewOverlayViewWithLastFrame을 를 참조하세요.