ML Kit는 셀카 세분화에 최적화된 SDK를 제공합니다. 셀카 세분화 도구 애셋은 빌드 시 앱에 정적으로 연결됩니다. 이렇게 하면 앱 크기가 최대 24MB까지 늘어나며, iPhone X에서 측정된 바와 같이 API 지연 시간은 입력 이미지 크기에 따라 최대 7ms~12ms가 될 수 있습니다.
사용해 보기
- 샘플 앱을 사용하여 이 API의 사용 예를 참조하세요.
시작하기 전에
Podfile에 다음 ML Kit 라이브러리를 포함합니다.
pod 'GoogleMLKit/SegmentationSelfie', '3.2.0'
프로젝트의 포드를 설치하거나 업데이트한 후 .
xcworkspace
를 사용하여 Xcode 프로젝트를 엽니다. ML Kit는 Xcode 버전 13.2.1 이상에서 지원됩니다.
1. 세그먼터의 인스턴스 만들기
셀카 이미지에서 세분화를 실행하려면 먼저 SelfieSegmenterOptions
로 Segmenter
인스턴스를 만들고 선택적으로 세분화 설정을 지정합니다.
분류 기준 옵션
세그먼터 모드
Segmenter
는 두 가지 모드로 작동합니다. 사용 사례에 맞는 태그를 선택해야 합니다.
STREAM_MODE (default)
이 모드는 동영상 또는 카메라의 프레임을 스트리밍하도록 설계되었습니다. 이 모드에서는 세그먼트 도구가 이전 프레임의 결과를 활용하여 더 원활한 세분화 결과를 반환합니다.
SINGLE_IMAGE_MODE (default)
이 모드는 관련되지 않은 단일 이미지를 위해 설계되었습니다. 이 모드에서는 세그먼트 도구가 각 이미지를 독립적으로 처리하며 프레임에 평활화를 적용하지 않습니다.
원시 크기 마스크 사용 설정
세그먼트 작성자에게 모델 출력 크기와 일치하는 원시 크기 마스크를 반환하도록 요청합니다.
RAW 마스크 크기 (예: 256x256)는 일반적으로 입력 이미지 크기보다 작습니다.
이 옵션을 지정하지 않으면 세그먼트 도구가 입력 이미지 크기와 일치하도록 원시 마스크의 크기를 조정합니다. 맞춤설정된 크기 조정 로직을 적용하거나 사용 사례에 크기 조정이 필요하지 않은 경우 이 옵션을 사용하는 것이 좋습니다.
분류 기준 옵션을 지정합니다.
Swift
let options = SelfieSegmenterOptions() options.segmenterMode = .singleImage options.shouldEnableRawSizeMask = true
Objective-C
MLKSelfieSegmenterOptions *options = [[MLKSelfieSegmenterOptions alloc] init]; options.segmenterMode = MLKSegmenterModeSingleImage; options.shouldEnableRawSizeMask = YES;
마지막으로 Segmenter
의 인스턴스를 가져옵니다. 지정한 옵션을 전달합니다.
Swift
let segmenter = Segmenter.segmenter(options: options)
Objective-C
MLKSegmenter *segmenter = [MLKSegmenter segmenterWithOptions:options];
2. 입력 이미지 준비
셀카를 분류하려면 각 이미지 또는 동영상 프레임에 대해 다음을 수행합니다.
스트림 모드를 사용 설정한 경우 VisionImage
객체를
CMSampleBuffer
VisionImage
객체를 UIImage
또는
CMSampleBuffer
입니다.
UIImage
를 사용하는 경우 다음 단계를 따르세요.
UIImage
로VisionImage
객체를 만듭니다. 올바른.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. 이미지 처리
VisionImage
객체를 Segmenter
의 이미지 처리 메서드 중 하나에 전달합니다. 비동기 process(image:)
메서드 또는 동기 results(in:)
메서드를 사용할 수 있습니다.
셀카 이미지를 동기식으로 세분화하려면 다음 단계를 따르세요.
Swift
var mask: [SegmentationMask] do { mask = try segmenter.results(in: image) } catch let error { print("Failed to perform segmentation with error: \(error.localizedDescription).") return } // Success. Get a segmentation mask here.
Objective-C
NSError *error; MLKSegmentationMask *mask = [segmenter resultsInImage:image error:&error]; if (error != nil) { // Error. return; } // Success. Get a segmentation mask here.
셀카 이미지를 비동기식으로 세분화하려면 다음 단계를 따르세요.
Swift
segmenter.process(image) { mask, error in guard error == nil else { // Error. return } // Success. Get a segmentation mask here.
Objective-C
[segmenter processImage:image completion:^(MLKSegmentationMask * _Nullable mask, NSError * _Nullable error) { if (error != nil) { // Error. return; } // Success. Get a segmentation mask here. }];
4. 세분화 마스크 가져오기
다음과 같이 세분화 결과를 얻을 수 있습니다.
Swift
let maskWidth = CVPixelBufferGetWidth(mask.buffer) let maskHeight = CVPixelBufferGetHeight(mask.buffer) CVPixelBufferLockBaseAddress(mask.buffer, CVPixelBufferLockFlags.readOnly) let maskBytesPerRow = CVPixelBufferGetBytesPerRow(mask.buffer) var maskAddress = CVPixelBufferGetBaseAddress(mask.buffer)!.bindMemory( to: Float32.self, capacity: maskBytesPerRow * maskHeight) for _ in 0...(maskHeight - 1) { for col in 0...(maskWidth - 1) { // Gets the confidence of the pixel in the mask being in the foreground. let foregroundConfidence: Float32 = maskAddress[col] } maskAddress += maskBytesPerRow / MemoryLayout<Float32>.size }
Objective-C
size_t width = CVPixelBufferGetWidth(mask.buffer); size_t height = CVPixelBufferGetHeight(mask.buffer); CVPixelBufferLockBaseAddress(mask.buffer, kCVPixelBufferLock_ReadOnly); size_t maskBytesPerRow = CVPixelBufferGetBytesPerRow(mask.buffer); float *maskAddress = (float *)CVPixelBufferGetBaseAddress(mask.buffer); for (int row = 0; row < height; ++row) { for (int col = 0; col < width; ++col) { // Gets the confidence of the pixel in the mask being in the foreground. float foregroundConfidence = maskAddress[col]; } maskAddress += maskBytesPerRow / sizeof(float); }
세분화 결과를 사용하는 방법에 대한 전체 예는 다음 페이지를 참조하십시오. ML Kit 빠른 시작 샘플
실적 개선을 위한 팁
결과의 품질은 입력 이미지의 품질에 따라 달라집니다.
- ML Kit에서 정확한 세분화 결과를 얻으려면 이미지가 256x256픽셀 이상이어야 합니다.
- 실시간 애플리케이션에서 셀카 세분화를 수행하는 경우 입력 이미지의 전체 크기도 고려해야 합니다. 이미지가 작을수록 빠르게 처리될 수 있으므로 지연 시간을 줄이려면 낮은 해상도에서 이미지를 캡처하세요. 단, 위의 해상도 요구사항에 유의하여 피사체가 최대한 많은 이미지를 차지하도록 해야 합니다.
- 이미지 초점이 잘 맞지 않으면 정확도에 영향을 줄 수도 있습니다. 허용 가능한 수준의 결과를 얻지 못하면 사용자에게 이미지를 다시 캡처하도록 요청합니다.
실시간 애플리케이션에서 세분화를 사용하려는 경우 최상의 프레임 속도를 달성하려면 다음 가이드라인을 따르세요.
stream
분류 기준 모드를 사용합니다.- 낮은 해상도에서 이미지를 캡처하는 것이 좋습니다. 그러나 이 API의 이미지 크기 요구사항도 유의해야 합니다.
- 동영상 프레임을 처리하려면 세그먼트 도구의
results(in:)
동기 API를 사용하세요. 지정된 동영상 프레임에서 동기식으로 결과를 가져오려면 AVCaptureVideoDataOutputSampleBufferDelegate의 captureOutput(_, didOutput:from:) 함수에서 이 메서드를 호출합니다. AVCaptureVideoDataOutput의 alwaysDiscardsLateVideoFrames를 true로 유지하여 분류기에 대한 호출을 제한합니다. 세그먼트 도구가 실행 중일 때 새 동영상 프레임이 제공되는 경우 삭제됩니다. - 세그먼트 도구의 출력을 사용하여 입력 이미지에서 그래픽을 오버레이하는 경우 먼저 ML Kit에서 결과를 가져온 후 이미지를 렌더링하고 단일 단계로 오버레이합니다. 이렇게 하면 처리된 입력 프레임마다 한 번만 디스플레이 표면에 렌더링됩니다. 예는 ML Kit 빠른 시작 샘플의 previewOverlayView 및 CameraViewController 클래스를 참조하세요.