Za pomocą pakietu ML Kit możesz rozpoznawać encje na obrazie i oznaczać je etykietami. Ten interfejs API obsługuje szeroką gamę niestandardowych modeli klasyfikacji obrazów. Proszę wskazówki znajdziesz w sekcji Modele niestandardowe z ML Kit wymagania dotyczące zgodności, gdzie znaleźć wytrenowane modele, oraz jak trenować własne modele.
Model niestandardowy można zintegrować na 2 sposoby. Możesz połączyć model według poprzez umieszczenie go w folderze z zasobami aplikacji lub pobranie dynamicznego z Firebase. W poniższej tabeli porównano 2 opcje.
Model w pakiecie | Hostowany model |
---|---|
Model jest częścią pakietu APK aplikacji, co zwiększa jego rozmiar. | Model nie jest częścią pakietu APK. Jest hostowany przez przesłanie do Systemów uczących się Firebase. |
Model jest dostępny od razu, nawet gdy urządzenie z Androidem jest offline | Model jest pobierany na żądanie |
Nie potrzeba projektu Firebase | Wymaga projektu Firebase |
Aby zaktualizować model, musisz ponownie opublikować aplikację | Przekazywanie aktualizacji modelu bez ponownego publikowania aplikacji |
Brak wbudowanych testów A/B | Łatwe testy A/B dzięki Zdalnej konfiguracji Firebase |
Wypróbuj
- Zobacz aplikację z krótkim wprowadzeniem do Vision na przykład użycia modelu zawartego w pakiecie Krótkie wprowadzenie do AutoML przykład użycia hostowanego modelu.
Zanim zaczniesz
Umieść biblioteki ML Kit w pliku Podfile:
Aby dołączyć model do aplikacji:
pod 'GoogleMLKit/ImageLabelingCustom', '15.5.0'
Aby dynamicznie pobierać model z Firebase, dodaj
LinkFirebase
zależność:pod 'GoogleMLKit/ImageLabelingCustom', '15.5.0' pod 'GoogleMLKit/LinkFirebase', '15.5.0'
Po zainstalowaniu lub zaktualizowaniu podów swojego projektu otwórz projekt Xcode za pomocą:
.xcworkspace
. ML Kit jest obsługiwany w Xcode w wersji 13.2.1 lub wyższą.Jeśli chcesz pobrać model, dodaj Firebase do swojego projektu na iOS, jeśli jeszcze nie zostało to zrobione. Nie jest to wymagane, gdy łączysz model atrybucji.
1. Wczytaj model
Skonfiguruj źródło modelu lokalnego
Aby połączyć model z aplikacją:
Skopiuj plik modelu (zwykle kończący się na
.tflite
lub.lite
) do Xcode projektu, pamiętając przy tym, by wybraćCopy bundle resources
. zostanie uwzględniony w pakiecie aplikacji i będzie dostępny dla ML Kit.Utwórz obiekt
LocalModel
, podając ścieżkę do pliku modelu:Swift
let localModel = LocalModel(path: localModelFilePath)
Objective-C
MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithPath:localModelFilePath];
Skonfiguruj źródło modelu hostowanego w Firebase
Aby używać modelu hostowanego zdalnie, utwórz obiekt RemoteModel
, określając
nazwa nadana modelowi podczas jego publikowania:
Swift
let firebaseModelSource = FirebaseModelSource( name: "your_remote_model") // The name you assigned in // the Firebase console. let remoteModel = CustomRemoteModel(remoteModelSource: firebaseModelSource)
Objective-C
MLKFirebaseModelSource *firebaseModelSource = [[MLKFirebaseModelSource alloc] initWithName:@"your_remote_model"]; // The name you assigned in // the Firebase console. MLKCustomRemoteModel *remoteModel = [[MLKCustomRemoteModel alloc] initWithRemoteModelSource:firebaseModelSource];
Następnie uruchom zadanie pobierania modelu, określając warunki, które którym chcesz zezwolić na pobieranie. Jeśli nie ma modelu na urządzeniu lub jest on nowszy gdy dostępna będzie wersja modelu, zadanie asynchronicznie pobierze model z 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];
Wiele aplikacji rozpoczyna zadanie pobierania w kodzie inicjowania, możesz to zrobić w dowolnym momencie, zanim trzeba będzie skorzystać z modelu.
Konfigurowanie osoby oznaczającej obrazy
Po skonfigurowaniu źródeł modelu utwórz obiekt ImageLabeler
na podstawie jednego
z nich.
Dostępne są te ustawienia:
Opcje | |
---|---|
confidenceThreshold
|
Minimalny wskaźnik ufności wykrytych etykiet. Jeśli zasada nie jest skonfigurowana, zostanie użyty próg klasyfikatora określony przez metadane modelu. Jeśli model nie zawiera żadnych metadanych lub określ próg klasyfikatora, domyślny próg równy 0,0 zostanie . |
maxResultCount
|
Maksymalna liczba etykiet do zwrócenia. Jeśli zasada nie jest skonfigurowana, domyślną wartością jest Użyjemy wartości 10. |
Jeśli masz tylko model scalony lokalnie, po prostu utwórz osobę oznaczającą etykietami na podstawie
LocalModel
obiekt:
Swift
let options = CustomImageLabelerOptions(localModel: localModel) options.confidenceThreshold = NSNumber(value: 0.0) let imageLabeler = ImageLabeler.imageLabeler(options: options)
Objective-C
MLKCustomImageLabelerOptions *options = [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:localModel]; options.confidenceThreshold = @(0.0); MLKImageLabeler *imageLabeler = [MLKImageLabeler imageLabelerWithOptions:options];
Jeśli masz model hostowany zdalnie, musisz sprawdzić, czy został
pobrane przed uruchomieniem. Stan pobierania modelu możesz sprawdzić
za pomocą metody isModelDownloaded(remoteModel:)
menedżera modeli.
Chociaż trzeba to potwierdzić tylko przed uruchomieniem osoby oznaczającej etykietami,
korzystają zarówno z modelu hostowanego zdalnie, jak i z pakietu lokalnego, może to sprawić,
warto przeprowadzić tę kontrolę przy tworzeniu wystąpienia ImageLabeler
: utwórz
z modelu zdalnego, jeśli został on pobrany, oraz z modelu lokalnego
w przeciwnym razie.
Swift
var options: CustomImageLabelerOptions! if (ModelManager.modelManager().isModelDownloaded(remoteModel)) { options = CustomImageLabelerOptions(remoteModel: remoteModel) } else { options = CustomImageLabelerOptions(localModel: localModel) } options.confidenceThreshold = NSNumber(value: 0.0) let imageLabeler = ImageLabeler.imageLabeler(options: options)
Objective-C
MLKCustomImageLabelerOptions *options; if ([[MLKModelManager modelManager] isModelDownloaded:remoteModel]) { options = [[MLKCustomImageLabelerOptions alloc] initWithRemoteModel:remoteModel]; } else { options = [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:localModel]; } options.confidenceThreshold = @(0.0); MLKImageLabeler *imageLabeler = [MLKImageLabeler imageLabelerWithOptions:options];
Jeśli masz tylko model hostowany zdalnie, wyłącz powiązany z nim model funkcji – na przykład wyszarzenia lub ukrycia części interfejsu – do potwierdzasz, że model został pobrany.
Stan pobierania modelu możesz sprawdzić, dołączając obserwatorów do wartości domyślnej.
Centrum powiadomień. Pamiętaj, aby w obserwatorium używać słabego odniesienia do self
bo pobieranie może trochę potrwać, a źródłowy obiekt
zwolniony do momentu zakończenia pobierania. Na przykład:
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. Przygotowywanie obrazu wejściowego
Utwórz obiekt VisionImage
za pomocą UIImage
lub
CMSampleBuffer
.
Jeśli używasz UIImage
, wykonaj te czynności:
- Utwórz obiekt
VisionImage
za pomocąUIImage
. Pamiętaj, by określić prawidłowy.orientation
.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Jeśli używasz CMSampleBuffer
, wykonaj te czynności:
-
Określ orientację danych zdjęć zawartych w pliku
CMSampleBuffer
Aby sprawdzić orientację obrazu:
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; } }
- Utwórz obiekt
VisionImage
za pomocąCMSampleBuffer
obiekt i orientacja: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. Uruchamianie oznaczania obrazów
Aby oznaczyć etykietami obiekty na obrazie, przekaż obiekt image
do funkcji ImageLabeler
Metoda process()
.
Asynchronicznie:
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 (label.count == 0) { // Handle the error. return; } // Show results. }];
Synchronnie:
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. Uzyskiwanie informacji o elementach oznaczonych etykietami
Jeśli operacja oznaczania obrazów etykietami zakończy się powodzeniem, funkcja zwróci tablicęImageLabel
Każdy element ImageLabel
reprezentuje coś,
oznaczone etykietą na zdjęciu. Opis każdej etykiety (jeśli jest dostępny w
metadane pliku modelu TensorFlow Lite), wskaźnik ufności i indeks.
Na przykład:
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; }
Wskazówki dotyczące poprawy skuteczności w czasie rzeczywistym
Jeśli chcesz oznaczać obrazy w aplikacji działającej w czasie rzeczywistym, postępuj zgodnie z tymi instrukcjami wytycznych dotyczących uzyskiwania najlepszej liczby klatek na sekundę:
- Do przetwarzania klatek wideo używaj synchronicznego interfejsu API
results(in:)
detektora. Zadzwoń do nas tę metodę zAVCaptureVideoDataOutputSampleBufferDelegate
.captureOutput(_, didOutput:from:)
, aby synchronicznie pobierać wyniki dotyczące danego filmu ramki. ZachowajAVCaptureVideoDataOutput
:alwaysDiscardsLateVideoFrames
jakotrue
, aby ograniczyć wywołania detektora. Jeśli nowy gdy klatka wideo jest dostępna, gdy jest uruchomiony detektor, zostanie usunięta. - Jeśli użyjesz danych wyjściowych detektora do nakładania grafiki na obrazu wejściowego, najpierw pobierz wynik z ML Kit, a następnie wyrenderuj obraz i nakładanie nakładek w jednym kroku. W ten sposób renderowanie na powierzchni tylko raz na każdą przetworzoną ramkę wejściową. Zobacz updatePreviewOverlayViewWithLastFrame. znajdziesz na przykład w krótkim wprowadzeniu do korzystania z ML Kit.