Gdy przekazujesz obraz do ML Kit, wykrywa on maksymalnie 5 obiektów. wraz z położeniem każdego obiektu na obrazie. Podczas wykrywania obiektów w strumieni wideo, każdy obiekt ma unikalny identyfikator, którego możesz użyć do śledzenia od klatki do klatki.
Możesz użyć niestandardowego modelu klasyfikacji obrazów, aby sklasyfikować obiekty, które są – wykryto. Informacje o modelach niestandardowych z pakietem ML Kit wskazówki dotyczące wymagań zgodności, gdzie znaleźć już 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ą pliku .ipa aplikacji, który
powiększa się. |
Model nie jest częścią pliku .ipa aplikacji. Jest
z serwera 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.
- Zobacz prezentację stylu Material Design , by kompleksowo wdrożyć ten interfejs API.
Zanim zaczniesz
Umieść biblioteki ML Kit w pliku Podfile:
Aby dołączyć model do aplikacji:
pod 'GoogleMLKit/ObjectDetectionCustom', '15.5.0'
Aby dynamicznie pobierać model z Firebase, dodaj
LinkFirebase
zależność:pod 'GoogleMLKit/ObjectDetectionCustom', '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 CustomRemoteModel
,
określając nazwę przypisaną do modelu 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.
2. Konfigurowanie detektora obiektów
Po skonfigurowaniu źródeł modelu skonfiguruj detektor obiektów dla
z obiektem CustomObjectDetectorOptions
. Możesz zmienić
następujące ustawienia:
Ustawienia wykrywania obiektów | |
---|---|
Tryb wykrywania |
STREAM_MODE (domyślna) | SINGLE_IMAGE_MODE
W W |
Wykrywanie i śledzenie wielu obiektów |
false (domyślna) | true
Określa, czy należy wykryć i śledzić do pięciu obiektów, czy tylko najbardziej. widoczny obiekt (domyślnie). |
Klasyfikowanie obiektów |
false (domyślna) | true
Określa, czy należy klasyfikować wykryte obiekty przy użyciu podanego
niestandardowy model klasyfikatora. Aby użyć własnej klasyfikacji
modelu, należy ustawić wartość |
Próg ufności klasyfikacji |
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 . |
Maksymalna liczba etykiet na obiekt |
Maksymalna liczba etykiet na obiekt, które detektor . Jeśli zasada nie jest skonfigurowana, używana jest wartość domyślna, czyli 10. |
Jeśli masz tylko model połączony lokalnie, utwórz detektor obiektów w
Twój obiekt LocalModel
:
Swift
let options = CustomObjectDetectorOptions(localModel: localModel) options.detectorMode = .singleImage options.shouldEnableClassification = true options.shouldEnableMultipleObjects = true options.classificationConfidenceThreshold = NSNumber(value: 0.5) options.maxPerObjectLabelCount = 3
Objective-C
MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableClassification = YES; options.shouldEnableMultipleObjects = YES; options.classificationConfidenceThreshold = @(0.5); options.maxPerObjectLabelCount = 3;
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.
Mimo że musisz to potwierdzić tylko przed uruchomieniem wykrywania obiektów, jeśli
masz zarówno model hostowany, jak i dostępny lokalnie, może to sprawić,
warto przeprowadzić tę kontrolę przy tworzeniu wystąpienia ObjectDetector
: utwórz
detektor z modelu zdalnego, jeśli został pobrany, oraz z modelu lokalnego
w przeciwnym razie.
Swift
var options: CustomObjectDetectorOptions! if (ModelManager.modelManager().isModelDownloaded(remoteModel)) { options = CustomObjectDetectorOptions(remoteModel: remoteModel) } else { options = CustomObjectDetectorOptions(localModel: localModel) } options.detectorMode = .singleImage options.shouldEnableClassification = true options.shouldEnableMultipleObjects = true options.classificationConfidenceThreshold = NSNumber(value: 0.5) options.maxPerObjectLabelCount = 3
Objective-C
MLKCustomObjectDetectorOptions *options; if ([[MLKModelManager modelManager] isModelDownloaded:remoteModel]) { options = [[MLKCustomObjectDetectorOptions alloc] initWithRemoteModel:remoteModel]; } else { options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; } options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableClassification = YES; options.shouldEnableMultipleObjects = YES; options.classificationConfidenceThreshold = @(0.5); options.maxPerObjectLabelCount = 3;
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]; }];
Interfejs API wykrywania i śledzenia obiektów jest zoptymalizowany pod kątem tych dwóch podstawowych zastosowań przypadki:
- Wykrywanie na żywo i śledzenie najbardziej widocznego obiektu w kamerze wizjer.
- Wykrywanie wielu obiektów na obrazie statycznym.
Aby skonfigurować interfejs API pod kątem tych przypadków użycia:
Swift
// Live detection and tracking let options = CustomObjectDetectorOptions(localModel: localModel) options.shouldEnableClassification = true options.maxPerObjectLabelCount = 3 // Multiple object detection in static images let options = CustomObjectDetectorOptions(localModel: localModel) options.detectorMode = .singleImage options.shouldEnableMultipleObjects = true options.shouldEnableClassification = true options.maxPerObjectLabelCount = 3
Objective-C
// Live detection and tracking MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.shouldEnableClassification = YES; options.maxPerObjectLabelCount = 3; // Multiple object detection in static images MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableMultipleObjects = YES; options.shouldEnableClassification = YES; options.maxPerObjectLabelCount = 3;
3. 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];
4. Utwórz i uruchom detektor obiektów
Utwórz nowy wzorzec do wykrywania obiektów:
Swift
let objectDetector = ObjectDetector.objectDetector(options: options)
Objective-C
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
Następnie użyj wzorca do wykrywania treści:
Asynchronicznie:
Swift
objectDetector.process(image) { objects, error in guard error == nil, let objects = objects, !objects.isEmpty else { // Handle the error. return } // Show results. }
Objective-C
[objectDetector processImage:image completion:^(NSArray
*_Nullable objects, NSError *_Nullable error) { if (objects.count == 0) { // Handle the error. return; } // Show results. }]; Synchronnie:
Swift
var objects: [Object] do { objects = try objectDetector.results(in: image) } catch let error { // Handle the error. return } // Show results.
Objective-C
NSError *error; NSArray
*objects = [objectDetector resultsInImage:image error:&error]; // Show results or handle the error.
5. Uzyskiwanie informacji o obiektach oznaczonych etykietami
Jeśli wywołanie procesora zdjęć się powiedzie, przekazywana jest lista
Object
s do modułu obsługi uzupełniania lub zwraca listę, w zależności od
niezależnie od tego, czy została użyta metoda asynchroniczna czy synchroniczna.
Każdy element Object
zawiera te właściwości:
frame |
CGRect wskazujący położenie obiektu w
. |
||||||
trackingID |
Liczba całkowita, która identyfikuje obiekt na obrazach, lub „nil” w SINGLE_IMAGE_MODE. | ||||||
labels |
|
Swift
// objects contains one item if multiple object detection wasn't enabled. for object in objects { let frame = object.frame let trackingID = object.trackingID let description = object.labels.enumerated().map { (index, label) in "Label \(index): \(label.text), \(label.confidence), \(label.index)" }.joined(separator: "\n") }
Objective-C
// The list of detected objects contains one item if multiple object detection // wasn't enabled. for (MLKObject *object in objects) { CGRect frame = object.frame; NSNumber *trackingID = object.trackingID; for (MLKObjectLabel *label in object.labels) { NSString *labelString = [NSString stringWithFormat:@"%@, %f, %lu", label.text, label.confidence, (unsigned long)label.index]; } }
Dbanie o wygodę użytkowników
Aby zadbać o wygodę użytkowników, przestrzegaj tych wytycznych:
- Pomyślne wykrycie obiektu zależy od jego złożoności wizualnej. W są wykrywane, obiekty z niewielką liczbą funkcji wizualnych mogą wymagać aby zająć większą część obrazu. Należy dostarczyć użytkownikom wskazówki na temat tego, przechwytywanie danych wejściowych, które dobrze działają z rodzajami obiektów, które chcesz wykrywać.
- Gdy używasz klasyfikacji, aby wykrywać obiekty, które nie wypadają do obsługiwanych kategorii, zastosować specjalną obsługę nieznanych obiektów.
Zapoznaj się też z [ML Kit Material Design][showcase-link]{: .external } oraz Material Design Kolekcja Wzorce funkcji opartych na systemach uczących się.
Improving performance
Jeśli chcesz używać wykrywania obiektów w aplikacji działającej w czasie rzeczywistym, postępuj zgodnie z tymi instrukcjami wytycznych dotyczących uzyskiwania najlepszej liczby klatek na sekundę:Gdy używasz trybu strumieniowania w aplikacji działającej w czasie rzeczywistym, nie używaj wielu wykrywanie obiektów, ponieważ większość urządzeń nie jest w stanie wygenerować odpowiedniej 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.