É possível usar o Kit de ML para reconhecer entidades em uma imagem e rotulá-las. Essa API oferece suporte a uma ampla variedade de modelos de classificação de imagem personalizados. Não se esqueça consulte Modelos personalizados com o Kit de ML para receber orientações sobre requisitos de compatibilidade de modelos, onde encontrar modelos pré-treinados, e como treinar seus próprios modelos.
Há duas maneiras de integrar um modelo personalizado. É possível agrupar o modelo colocá-lo na pasta de recursos do app ou fazer o download dele dinamicamente do Firebase. A tabela a seguir compara as duas opções.
Modelo em pacote | Modelo hospedado |
---|---|
O modelo faz parte do APK do app, o que aumenta o tamanho dele. | O modelo não faz parte do seu APK. Ele é hospedado por meio do upload para Machine Learning do Firebase. |
O modelo estará disponível imediatamente, mesmo quando o dispositivo Android estiver off-line | O download do modelo é feito sob demanda |
Não é necessário ter um projeto do Firebase | Requer um projeto do Firebase |
É necessário republicar o app para atualizar o modelo | Enviar atualizações do modelo sem republicar o app |
Sem testes A/B integrados | Teste A/B fácil com a Configuração remota do Firebase |
Faça um teste
- Consulte o app de início rápido do Vision. um exemplo de uso do modelo empacotado e do app de início rápido do AutoML para uma exemplo de uso do modelo hospedado.
Antes de começar
Inclua as bibliotecas do Kit de ML no seu Podfile:
Para agrupar um modelo e seu app:
pod 'GoogleMLKit/ImageLabelingCustom', '15.5.0'
Para fazer o download dinâmico de um modelo do Firebase, adicione
LinkFirebase
dependência:pod 'GoogleMLKit/ImageLabelingCustom', '15.5.0' pod 'GoogleMLKit/LinkFirebase', '15.5.0'
Depois de instalar ou atualizar os pods do seu projeto, abra o projeto Xcode usando a
.xcworkspace
dele. O Kit de ML é compatível com a versão 13.2.1 do Xcode ou superior.Se você quiser fazer o download de um modelo, verifique se adicione o Firebase ao seu projeto do iOS, caso ainda não tenha feito isso. Isso não é necessário quando você agrupa o um modelo de machine learning.
1. Carregar o modelo
Configurar uma fonte de modelo local
Para agrupar o modelo e o app, faça o seguinte:
Copie o arquivo do modelo (geralmente terminando em
.tflite
ou.lite
) para seu Xcode projeto. Lembre-se de selecionarCopy bundle resources
ao fazer isso. A do modelo será incluído no pacote de apps e estará disponível para o Kit de ML.Crie o objeto
LocalModel
, especificando o caminho para o arquivo de modelo:Swift
let localModel = LocalModel(path: localModelFilePath)
Objective-C
MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithPath:localModelFilePath];
Configurar uma fonte de modelo hospedada no Firebase
Para usar o modelo hospedado remotamente, crie um objeto RemoteModel
, especificando o
nome que você atribuiu ao modelo quando o publicou:
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];
Em seguida, inicie a tarefa de download do modelo, especificando as condições sob as quais do qual você quer permitir o download. Se o modelo não estiver no dispositivo ou se um modelo mais recente versão do modelo estiver disponível, a tarefa fará o download do arquivo do 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];
Muitos apps iniciam a tarefa de download no código de inicialização, mas você pode fazer isso a qualquer momento antes de precisar usar o modelo.
Configurar o rotulador de imagens
Depois de configurar as origens do modelo, crie um objeto ImageLabeler
usando uma
um deles.
As seguintes opções estão disponíveis:
Opções | |
---|---|
confidenceThreshold
|
Pontuação de confiança mínima dos rótulos detectados. Se não for definido, qualquer um o limite do classificador especificado pelos metadados do modelo será usado. Se o modelo não tiver metadados ou se os metadados não tiverem especificar um limite de classificador, um limite padrão de 0,0 será usados. |
maxResultCount
|
Número máximo de rótulos a serem retornados. Se não for definido, o valor padrão de 10 serão usados. |
Se você tiver apenas um modelo agrupado localmente, basta criar um rotulador
Objeto LocalModel
:
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];
Se você tiver um modelo hospedado remotamente, será necessário verificar se ele foi
antes de executá-lo. É possível verificar o status do download do modelo
tarefa usando o método isModelDownloaded(remoteModel:)
do gerenciador de modelos.
Embora isso só precise ser confirmado antes de executar o rotulador, se você
mas tem um modelo hospedado remotamente e um modelo agrupado localmente, isso pode tornar
para fazer essa verificação ao instanciar o ImageLabeler
: crie um
rotulador a partir do modelo remoto, caso ele tenha sido transferido por download, e do modelo local
caso contrário.
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];
Se você tiver apenas um modelo hospedado remotamente, desative o recurso da interface, por exemplo, esmaecer ou ocultar parte da interface, até confirme se o download do modelo foi concluído.
É possível receber o status de download do modelo anexando observadores ao arquivo
Central de Notificações. Use uma referência fraca a self
no observador.
já que os downloads podem levar algum tempo e o objeto de origem pode ser
liberado no momento em que o download é concluído. Exemplo:
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. Preparar a imagem de entrada
Crie um objeto VisionImage
usando um UIImage
ou um
CMSampleBuffer
.
Se você usa um UIImage
, siga estas etapas:
- Crie um objeto
VisionImage
com oUIImage
. Especifique o.orientation
correto.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Se você usa um CMSampleBuffer
, siga estas etapas:
-
Especifique a orientação dos dados da imagem contidos no
CMSampleBuffer
:Para saber qual é a orientação da imagem:
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; } }
- Crie um objeto
VisionImage
usando o Objeto e orientaçãoCMSampleBuffer
: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. Executar o rotulador de imagens
Para rotular objetos em uma imagem, transmita o objeto image
para o objeto ImageLabeler
.
process()
.
De forma assíncrona:
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. }];
De forma síncrona:
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. Receber informações sobre entidades rotuladas
Se a operação de rotulagem de imagem for bem-sucedida, ela retornará uma matriz deImageLabel
Cada ImageLabel
representa algo que foi
rotuladas na imagem. Você pode obter a descrição de texto de cada rótulo (se disponível no
metadados do arquivo de modelo do TensorFlow Lite), pontuação de confiança e índice.
Exemplo:
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; }
Dicas para melhorar o desempenho em tempo real
Se você quiser rotular imagens em um aplicativo em tempo real, siga estas instruções diretrizes para obter as melhores taxas de quadros:
- Para processar frames de vídeo, use a API síncrona
results(in:)
do detector. Ligação esse método daAVCaptureVideoDataOutputSampleBufferDelegate
captureOutput(_, didOutput:from:)
para receber resultados do vídeo fornecido de forma síncrona frame. Manter deAVCaptureVideoDataOutput
alwaysDiscardsLateVideoFrames
comotrue
para limitar as chamadas ao detector. Se um novo frame de vídeo ficar disponível enquanto o detector estiver em execução, ele será descartado. - Se você usar a saída do detector para sobrepor elementos gráficos a imagem de entrada, primeiro acesse o resultado do Kit de ML e, em seguida, renderize a imagem e sobreposição em uma única etapa. Ao fazer isso, você renderiza a superfície de exibição apenas uma vez para cada frame de entrada processado. Veja a classe updatePreviewOverlayViewWithLastFrame na amostra do guia de início rápido do Kit de ML.