Po wytrenowaniu własnego modelu za pomocą AutoML Vision Edge możesz użyć go w swojej aplikacji do oznaczania obrazów.
Zanim zaczniesz
- Jeśli nie dodałeś jeszcze Firebase do swojej aplikacji, zrób to, wykonując czynności opisane w przewodniku wprowadzającym .
- Dołącz biblioteki ML Kit do swojego Podfile:
pod 'Firebase/MLVision', '6.25.0' pod 'Firebase/MLVisionAutoML', '6.25.0'
Po zainstalowaniu lub zaktualizowaniu Podów swojego projektu pamiętaj o otwarciu projektu Xcode przy użyciu jego.xcworkspace
. - W swojej aplikacji zaimportuj Firebase:
Szybki
import Firebase
Cel C
@import Firebase;
1. Załaduj model
ML Kit uruchamia modele wygenerowane przez AutoML na urządzeniu. Możesz jednak skonfigurować ML Kit tak, aby ładował Twój model zdalnie z Firebase, z magazynu lokalnego lub z obu.
Hostując model w Firebase, możesz aktualizować model bez wydawania nowej wersji aplikacji, a także możesz używać zdalnej konfiguracji i testów A/B do dynamicznego udostępniania różnych modeli różnym grupom użytkowników.
Jeśli zdecydujesz się udostępnić model tylko poprzez hostowanie go w Firebase, a nie łączyć go z aplikacją, możesz zmniejszyć początkowy rozmiar pobieranej aplikacji. Pamiętaj jednak, że jeśli model nie jest dołączony do Twojej aplikacji, wszelkie funkcje związane z modelem nie będą dostępne, dopóki aplikacja nie pobierze modelu po raz pierwszy.
Łącząc model z aplikacją, możesz mieć pewność, że funkcje uczenia maszynowego w aplikacji będą nadal działać, gdy model hostowany przez Firebase nie będzie dostępny.
Skonfiguruj źródło modelu hostowane w Firebase
Aby użyć modelu hostowanego zdalnie, utwórz obiekt AutoMLRemoteModel
, podając nazwę, którą przypisałeś modelowi podczas jego publikacji:
Szybki
let remoteModel = AutoMLRemoteModel(
name: "your_remote_model" // The name you assigned in the Firebase console.
)
Cel C
FIRAutoMLRemoteModel *remoteModel = [[FIRAutoMLRemoteModel alloc]
initWithName:@"your_remote_model"]; // The name you assigned in the Firebase console.
Następnie rozpocznij zadanie pobierania modelu, określając warunki, na jakich chcesz zezwolić na pobieranie. Jeśli modelu nie ma na urządzeniu lub jeśli dostępna jest nowsza wersja modelu, zadanie asynchronicznie pobierze model z Firebase:
Szybki
let downloadConditions = ModelDownloadConditions(
allowsCellularAccess: true,
allowsBackgroundDownloading: true
)
let downloadProgress = ModelManager.modelManager().download(
remoteModel,
conditions: downloadConditions
)
Cel C
FIRModelDownloadConditions *downloadConditions =
[[FIRModelDownloadConditions alloc] initWithAllowsCellularAccess:YES
allowsBackgroundDownloading:YES];
NSProgress *downloadProgress =
[[FIRModelManager modelManager] downloadRemoteModel:remoteModel
conditions:downloadConditions];
Wiele aplikacji rozpoczyna zadanie pobierania w kodzie inicjującym, ale można to zrobić w dowolnym momencie, zanim będzie konieczne użycie modelu.
Skonfiguruj lokalne źródło modelu
Aby połączyć model z aplikacją:
- Wyodrębnij model i jego metadane z archiwum zip pobranego z konsoli Firebase do folderu:
your_model_directory |____dict.txt |____manifest.json |____model.tflite
Wszystkie trzy pliki muszą znajdować się w tym samym folderze. Zalecamy używanie plików w takiej postaci, w jakiej je pobrałeś, bez modyfikacji (w tym nazw plików). - Skopiuj folder do projektu Xcode, pamiętając o zaznaczeniu opcji Utwórz odniesienia do folderu, gdy to zrobisz. Plik modelu i metadane zostaną uwzględnione w pakiecie aplikacji i dostępne dla ML Kit.
- Utwórz obiekt
AutoMLLocalModel
, podając ścieżkę do pliku manifestu modelu:Szybki
guard let manifestPath = Bundle.main.path( forResource: "manifest", ofType: "json", inDirectory: "your_model_directory" ) else { return true } let localModel = AutoMLLocalModel(manifestPath: manifestPath)
Cel C
NSString *manifestPath = [NSBundle.mainBundle pathForResource:@"manifest" ofType:@"json" inDirectory:@"your_model_directory"]; FIRAutoMLLocalModel *localModel = [[FIRAutoMLLocalModel alloc] initWithManifestPath:manifestPath];
Utwórz etykietę obrazu ze swojego modelu
Po skonfigurowaniu źródeł modelu utwórz obiekt VisionImageLabeler
z jednego z nich.
Jeśli masz tylko model powiązany lokalnie, po prostu utwórz etykietę na podstawie obiektu AutoMLLocalModel
i skonfiguruj wymagany próg wyniku zaufania (zobacz Oceń swój model ):
Szybki
let options = VisionOnDeviceAutoMLImageLabelerOptions(localModel: localModel)
options.confidenceThreshold = 0 // Evaluate your model in the Firebase console
// to determine an appropriate value.
let labeler = Vision.vision().onDeviceAutoMLImageLabeler(options: options)
Cel C
FIRVisionOnDeviceAutoMLImageLabelerOptions *options =
[[FIRVisionOnDeviceAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel];
options.confidenceThreshold = 0; // Evaluate your model in the Firebase console
// to determine an appropriate value.
FIRVisionImageLabeler *labeler =
[[FIRVision vision] onDeviceAutoMLImageLabelerWithOptions:options];
Jeśli masz model hostowany zdalnie, przed uruchomieniem musisz sprawdzić, czy został pobrany. Możesz sprawdzić status zadania pobierania modelu, korzystając z metody isModelDownloaded(remoteModel:)
menedżera modeli.
Chociaż musisz to potwierdzić jedynie przed uruchomieniem modułu etykietowania, jeśli masz zarówno model hostowany zdalnie, jak i model powiązany lokalnie, sensowne może być wykonanie tej kontroli podczas tworzenia instancji VisionImageLabeler
: utwórz etykietę z modelu zdalnego, jeśli jest został pobrany, a w przeciwnym razie z modelu lokalnego.
Szybki
var options: VisionOnDeviceAutoMLImageLabelerOptions?
if (ModelManager.modelManager().isModelDownloaded(remoteModel)) {
options = VisionOnDeviceAutoMLImageLabelerOptions(remoteModel: remoteModel)
} else {
options = VisionOnDeviceAutoMLImageLabelerOptions(localModel: localModel)
}
options.confidenceThreshold = 0 // Evaluate your model in the Firebase console
// to determine an appropriate value.
let labeler = Vision.vision().onDeviceAutoMLImageLabeler(options: options)
Cel C
VisionOnDeviceAutoMLImageLabelerOptions *options;
if ([[FIRModelManager modelManager] isModelDownloaded:remoteModel]) {
options = [[FIRVisionOnDeviceAutoMLImageLabelerOptions alloc] initWithRemoteModel:remoteModel];
} else {
options = [[FIRVisionOnDeviceAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel];
}
options.confidenceThreshold = 0.0f; // Evaluate your model in the Firebase console
// to determine an appropriate value.
FIRVisionImageLabeler *labeler = [[FIRVision vision] onDeviceAutoMLImageLabelerWithOptions:options];
Jeśli masz tylko model hostowany zdalnie, wyłącz funkcje związane z modelem — na przykład wyszarz lub ukryj część interfejsu użytkownika — do czasu potwierdzenia, że model został pobrany.
Stan pobierania modelu możesz uzyskać podłączając obserwatorów do domyślnego Centrum powiadomień. Pamiętaj, aby użyć słabego odniesienia do self
w bloku obserwatora, ponieważ pobieranie może zająć trochę czasu, a obiekt źródłowy może zostać zwolniony do czasu zakończenia pobierania. Na przykład:
Szybki
NotificationCenter.default.addObserver( forName: .firebaseMLModelDownloadDidSucceed, 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: .firebaseMLModelDownloadDidFail, 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] // ... }
Cel C
__weak typeof(self) weakSelf = self; [NSNotificationCenter.defaultCenter addObserverForName:FIRModelDownloadDidSucceedNotification object:nil queue:nil usingBlock:^(NSNotification *_Nonnull note) { if (weakSelf == nil | note.userInfo == nil) { return; } __strong typeof(self) strongSelf = weakSelf; FIRRemoteModel *model = note.userInfo[FIRModelDownloadUserInfoKeyRemoteModel]; if ([model.name isEqualToString:@"your_remote_model"]) { // The model was downloaded and is available on the device } }]; [NSNotificationCenter.defaultCenter addObserverForName:FIRModelDownloadDidFailNotification object:nil queue:nil usingBlock:^(NSNotification *_Nonnull note) { if (weakSelf == nil | note.userInfo == nil) { return; } __strong typeof(self) strongSelf = weakSelf; NSError *error = note.userInfo[FIRModelDownloadUserInfoKeyError]; }];
2. Przygotuj obraz wejściowy
Następnie dla każdego obrazu, który chcesz oznaczyć etykietą, utwórz obiekt VisionImage
, korzystając z jednej z opcji opisanych w tej sekcji i przekaż go do instancji VisionImageLabeler
(opisanej w następnej sekcji).
Utwórz obiekt VisionImage
przy użyciu UIImage
lub CMSampleBufferRef
.
Aby użyć UIImage
:
- W razie potrzeby obróć obraz tak, aby jego właściwość
imageOrientation
miała.up
. - Utwórz obiekt
VisionImage
przy użyciu poprawnie obróconegoUIImage
. Nie określaj żadnych metadanych rotacji — należy użyć wartości domyślnej.topLeft
.Szybki
let image = VisionImage(image: uiImage)
Cel C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
Aby użyć CMSampleBufferRef
:
Utwórz obiekt
VisionImageMetadata
, który określa orientację danych obrazu zawartych w buforzeCMSampleBufferRef
.Aby uzyskać orientację obrazu:
Szybki
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> VisionDetectorImageOrientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftTop : .rightTop case .landscapeLeft: return cameraPosition == .front ? .bottomLeft : .topLeft case .portraitUpsideDown: return cameraPosition == .front ? .rightBottom : .leftBottom case .landscapeRight: return cameraPosition == .front ? .topRight : .bottomRight case .faceDown, .faceUp, .unknown: return .leftTop } }
Cel C
- (FIRVisionDetectorImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationLeftTop; } else { return FIRVisionDetectorImageOrientationRightTop; } case UIDeviceOrientationLandscapeLeft: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationBottomLeft; } else { return FIRVisionDetectorImageOrientationTopLeft; } case UIDeviceOrientationPortraitUpsideDown: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationRightBottom; } else { return FIRVisionDetectorImageOrientationLeftBottom; } case UIDeviceOrientationLandscapeRight: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationTopRight; } else { return FIRVisionDetectorImageOrientationBottomRight; } default: return FIRVisionDetectorImageOrientationTopLeft; } }
Następnie utwórz obiekt metadanych:
Szybki
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Cel C
FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init]; AVCaptureDevicePosition cameraPosition = AVCaptureDevicePositionBack; // Set to the capture device you used. metadata.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
- Utwórz obiekt
VisionImage
przy użyciu obiektuCMSampleBufferRef
i metadanych rotacji:Szybki
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Cel C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
3. Uruchom etykietę obrazu
Aby oznaczyć obiekty na obrazie, przekaż obiekt VisionImage
do metody process()
klasy VisionImageLabeler
:
Szybki
labeler.process(image) { labels, error in
guard error == nil, let labels = labels else { return }
// Task succeeded.
// ...
}
Cel C
[labeler
processImage:image
completion:^(NSArray<FIRVisionImageLabel *> *_Nullable labels, NSError *_Nullable error) {
if (error != nil || labels == nil) {
return;
}
// Task succeeded.
// ...
}];
Jeśli etykietowanie obrazu powiedzie się, tablica obiektów VisionImageLabel
zostanie przekazana do procedury obsługi uzupełniania. Z każdego obiektu można uzyskać informację o cesze rozpoznanej na obrazie.
Na przykład:
Szybki
for label in labels {
let labelText = label.text
let confidence = label.confidence
}
Cel C
for (FIRVisionImageLabel *label in labels) {
NSString *labelText = label.text;
NSNumber *confidence = label.confidence;
}
Wskazówki, jak poprawić wydajność w czasie rzeczywistym
- Przepustnica wzywa do detektora. Jeżeli w trakcie działania detektora pojawi się nowa klatka wideo, usuń ją.
- Jeśli używasz wyjścia detektora do nakładania grafiki na obraz wejściowy, najpierw uzyskaj wynik z ML Kit, a następnie wyrenderuj obraz i nakładkę w jednym kroku. W ten sposób renderujesz na powierzchnię wyświetlacza tylko raz dla każdej klatki wejściowej. Zobacz przykładowe klasy PreviewOverlayView i FIRDetectionOverlayView w przykładowej aplikacji prezentacyjnej.