iOS에서 AutoML 학습 모델을 사용하여 이미지 라벨 지정
AutoML Vision Edge를 사용하여 자체 모델을 학습시킨 후 앱에서 모델을 사용하여 이미지에 라벨을 지정할 수 있습니다.
AutoML Vision Edge에서 학습된 모델을 통합하는 방법에는 두 가지가 있습니다. 모델의 파일을 Xcode 프로젝트로 복사하여 모델을 번들로 묶거나 Firebase에서 동적으로 다운로드할 수 있습니다.
모델 번들 옵션 | |
---|---|
앱에 번들로 제공 |
|
Firebase로 호스팅 |
|
사용해 보기
- 샘플 앱을 살펴보고 이 API의 사용 예를 확인합니다.
시작하기 전에
1. Podfile에 ML Kit 라이브러리를 포함합니다.모델을 앱에 번들로 묶는 방법은 다음과 같습니다.
pod 'GoogleMLKit/ImageLabelingAutoML'Firebase에서 모델을 동적으로 다운로드하려면
LinkFirebase
종속 항목을 추가합니다.
pod 'GoogleMLKit/ImageLabelingAutoML' pod 'GoogleMLKit/LinkFirebase'2. 프로젝트의 포드를 설치하거나 업데이트한 후
.xcworkspace
코드>를 사용하여 Xcode 프로젝트를 엽니다. ML Kit는 Xcode 버전 13.2.1 이상에서 지원됩니다.
3. 모델을 다운로드하려면 iOS 프로젝트에 Firebase를 추가해야 합니다(아직 추가하지 않은 경우). 모델을 번들로 묶을 때는 이 작업이 필요하지 않습니다.
1. 모델 로드
로컬 모델 소스 구성
모델을 앱과 번들로 묶는 방법은 다음과 같습니다.1. Firebase Console에서 다운로드한 zip 보관 파일에서 모델과 모델의 메타데이터를 폴더로 추출합니다.
your_model_directory |____dict.txt |____manifest.json |____model.tflite세 파일이 모두 같은 폴더에 있어야 합니다. 다운로드한 파일을 수정하지 않고 (파일 이름 등) 그대로 사용하는 것이 좋습니다.
2. 폴더를 Xcode 프로젝트에 복사합니다. 이때 폴더 참조 만들기를 선택해야 합니다. 모델 파일과 메타데이터가 App Bundle에 포함되며 ML Kit에서 사용할 수 있습니다.
3. 모델 매니페스트 파일의 경로를 지정하여
AutoMLImageLabelerLocalModel
객체를 만듭니다.
Swift
guard let manifestPath = Bundle.main.path( forResource: "manifest", ofType: "json", inDirectory: "your_model_directory" ) else { return } let localModel = AutoMLImageLabelerLocalModel(manifestPath: manifestPath)
Objective-C
NSString *manifestPath = [NSBundle.mainBundle pathForResource:@"manifest" ofType:@"json" inDirectory:@"your_model_directory"]; MLKAutoMLImageLabelerLocalModel *localModel = [[MLKAutoMLImageLabelerLocalModel alloc] initWithManifestPath:manifestPath];
Firebase 호스팅 모델 소스 구성
원격 호스팅 모델을 사용하려면 모델을 게시할 때 할당한 이름을 지정하여 AutoMLImageLabelerRemoteModel
객체를 만듭니다.
Swift
let remoteModel = AutoMLImageLabelerRemoteModel( name: "your_remote_model" // The name you assigned in // the Firebase console. )
Objective-C
MLKAutoMLImageLabelerRemoteModel *remoteModel = [[MLKAutoMLImageLabelerRemoteModel alloc] initWithName:@"your_remote_model"]; // The name you assigned in // the Firebase console.
이제 다운로드를 허용할 조건을 지정하여 모델 다운로드 작업을 시작합니다. 모델이 기기에 없거나 최신 버전의 모델을 사용할 수 있는 경우 모델이 Firebase에서 비동기식으로 다운로드됩니다.
Swift
let downloadConditions = ModelDownloadConditions( allowsCellularAccess: true, allowsBackgroundDownloading: true ) let downloadProgress = ModelManager.modelManager().download( remoteModel, conditions: downloadConditions )
Objective-C
MLKModelDownloadConditions *downloadConditions = [[MLKModelDownloadConditions alloc] initWithAllowsCellularAccess:YES allowsBackgroundDownloading:YES]; NSProgress *downloadProgress = [[MLKModelManager modelManager] downloadModel:remoteModel conditions:downloadConditions];
대부분의 앱은 초기화 코드에서 다운로드 작업을 시작하지만 모델 사용이 필요한 시점 이전에 언제든지 다운로드할 수 있습니다.
모델에서 이미지 라벨러 만들기
모델 소스를 구성한 후 모델 소스 중 하나에서 ImageLabeler
객체를 만듭니다.
로컬로 번들된 모델만 있다면 AutoMLImageLabelerLocalModel
객체에서 라벨러를 만들고 필요한 신뢰도 점수 임곗값을 구성합니다 (모드 평가 참조).
Swift
let options = AutoMLImageLabelerOptions(localModel: localModel) options.confidenceThreshold = NSNumber(value: 0.0) // Evaluate your model in the Firebase console // to determine an appropriate value. let imageLabeler = ImageLabeler.imageLabeler(options: options)
Objective-C
MLKAutoMLImageLabelerOptions *options = [[MLKAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel]; options.confidenceThreshold = @(0.0); // Evaluate your model in the Firebase console // to determine an appropriate value. MLKImageLabeler *imageLabeler = [MLKImageLabeler imageLabelerWithOptions:options];
원격 호스팅 모델이 있는 경우 모델을 실행하기 전에 다운로드되었는지 확인해야 합니다. 모델 관리자의 isModelDownloaded
(remoteModel:) 메서드를 사용하여 모델 다운로드 작업의 상태를 확인할 수 있습니다.
이 상태는 라벨러 실행 전에만 확인하면 되지만, 원격 호스팅 모델과 로컬로 번들된 모델이 모두 있는 경우에는 ImageLabeler
를 인스턴스화할 때 이 확인 작업을 수행하는 것이 합리적일 수 있습니다. 원격 모델이 다운로드되었으면 원격 모델에서, 그렇지 않으면 로컬 모델에서 라벨러를 만듭니다.
Swift
var options: AutoMLImageLabelerOptions! if (ModelManager.modelManager().isModelDownloaded(remoteModel)) { options = AutoMLImageLabelerOptions(remoteModel: remoteModel) } else { options = AutoMLImageLabelerOptions(localModel: localModel) } options.confidenceThreshold = NSNumber(value: 0.0) // Evaluate your model in the Firebase console // to determine an appropriate value. let imageLabeler = ImageLabeler.imageLabeler(options: options)
Objective-C
MLKAutoMLImageLabelerOptions *options; if ([[MLKModelManager modelManager] isModelDownloaded:remoteModel]) { options = [[MLKAutoMLImageLabelerOptions alloc] initWithRemoteModel:remoteModel]; } else { options = [[MLKAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel]; } options.confidenceThreshold = @(0.0); // Evaluate your model in the Firebase console // to determine an appropriate value. MLKImageLabeler *imageLabeler = [MLKImageLabeler imageLabelerWithOptions:options];
원격 호스팅 모델만 있다면 모델 다운로드 여부가 확인될 때까지 모델 관련 기능을 중지해야 합니다(예: UI 비활성화 또는 숨김).
기본 알림 센터에 관찰자를 연결하여 모델 다운로드 상태를 가져올 수 있습니다. 다운로드하는 데 시간이 걸릴 수 있고 다운로드가 완료되면 원래 객체가 해제될 수 있으므로 관찰자 블록의 self
에 약한 참조를 사용하세요. 예를 들면 다음과 같습니다.
Swift
NotificationCenter.default.addObserver( forName: .mlkitModelDownloadDidSucceed, object: nil, queue: nil ) { [weak self] notification in guard let strongSelf = self, let userInfo = notification.userInfo, let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue] as? RemoteModel, model.name == "your_remote_model" else { return } // The model was downloaded and is available on the device } NotificationCenter.default.addObserver( forName: .mlkitModelDownloadDidFail, object: nil, queue: nil ) { [weak self] notification in guard let strongSelf = self, let userInfo = notification.userInfo, let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue] as? RemoteModel else { return } let error = userInfo[ModelDownloadUserInfoKey.error.rawValue] // ... }
Objective-C
__weak typeof(self) weakSelf = self; [NSNotificationCenter.defaultCenter addObserverForName:MLKModelDownloadDidSucceedNotification object:nil queue:nil usingBlock:^(NSNotification *_Nonnull note) { if (weakSelf == nil | note.userInfo == nil) { return; } __strong typeof(self) strongSelf = weakSelf; MLKRemoteModel *model = note.userInfo[MLKModelDownloadUserInfoKeyRemoteModel]; if ([model.name isEqualToString:@"your_remote_model"]) { // The model was downloaded and is available on the device } }]; [NSNotificationCenter.defaultCenter addObserverForName:MLKModelDownloadDidFailNotification object:nil queue:nil usingBlock:^(NSNotification *_Nonnull note) { if (weakSelf == nil | note.userInfo == nil) { return; } __strong typeof(self) strongSelf = weakSelf; NSError *error = note.userInfo[MLKModelDownloadUserInfoKeyError]; }];
2. 입력 이미지 준비
UIImage
또는 CMSampleBuffer
를 사용하여 VisionImage
객체를 만듭니다.
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; } }
CMSampleBuffer
객체와 방향을 사용하여VisionImage
객체를 만듭니다.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. 이미지 라벨러 실행
비동기식으로:
Swift
imageLabeler.process(image) { labels, error in guard error == nil, let labels = labels, !labels.isEmpty else { // Handle the error. return } // Show results. }
Objective-C
[imageLabeler processImage:image completion:^(NSArray*_Nullable labels, NSError *_Nullable error) { if (labels.count == 0) { // Handle the error. return; } // Show results. }];
동기식으로:
Swift
var labels: [ImageLabel] do { labels = try imageLabeler.results(in: image) } catch let error { // Handle the error. return } // Show results.
Objective-C
NSError *error; NSArray*labels = [imageLabeler resultsInImage:image error:&error]; // Show results or handle the error.
4. 라벨이 지정된 객체에 대한 정보 가져오기
이미지 라벨 지정 작업이 성공하면ImageLabel
의 배열이 반환됩니다. 각 ImageLabel
는 이미지에서 라벨이 지정된 항목을 나타냅니다. 각 라벨의 텍스트 설명 (TensorFlow Lite 모델 파일의 메타데이터에서 제공되는 경우), 신뢰도 점수, 색인을 가져올 수 있습니다.
예를 들면 다음과 같습니다.
Swift
for label in labels { let labelText = label.text let confidence = label.confidence let index = label.index }
Objective-C
for (MLKImageLabel *label in labels) { NSString *labelText = label.text; float confidence = label.confidence; NSInteger index = label.index; }
실시간 성능 개선을 위한 팁
실시간 애플리케이션에서 이미지에 라벨을 지정하려는 경우 최상의 프레임 속도를 얻으려면 다음 가이드라인을 따르세요.
- 동영상 프레임을 처리하려면 감지기의
results(in:)
동기 API를 사용합니다.AVCaptureVideoDataOutputSampleBufferDelegate
의captureOutput(_, didOutput:from:)
함수에서 이 메서드를 호출하여 주어진 동영상 프레임에서 결과를 동기식으로 가져옵니다.AVCaptureVideoDataOutput
의alwaysDiscardsLateVideoFrames
를true
로 유지하여 감지기 호출을 제한합니다. 인식기가 실행 중일 때 새 동영상 프레임이 제공되면 삭제됩니다. - 인식기 출력을 사용하여 입력 이미지에서 그래픽을 오버레이하는 경우 먼저 ML Kit에서 결과를 가져온 후 이미지를 렌더링하고 단일 단계로 오버레이합니다. 이렇게 하면 처리된 입력 프레임마다 한 번만 디스플레이 표면에 렌더링됩니다. 관련 예는 ML Kit 빠른 시작 샘플에서 updatePreviewOverlayViewWithLastFrame을 참조하세요.