Introdução ao CoreML no Xamarin.iOS
O CoreML traz o aprendizado de máquina para o iOS – os aplicativos podem aproveitar os modelos de aprendizado de máquina treinados para executar todos os tipos de tarefas, desde a resolução de problemas até o reconhecimento de imagens.
Esta introdução abrange o seguinte:
Introdução ao CoreML
Estas etapas descrevem como adicionar CoreML a um projeto iOS.
1. Adicionar o modelo CoreML ao projeto
Adicione um modelo CoreML (um arquivo com a extensão .mlmodel ) ao diretório Resources do projeto.
Nas propriedades do arquivo de modelo, sua ação Build é definida como CoreMLModel. Isso significa que ele será compilado em um arquivo .mlmodelc quando o aplicativo for criado.
2. Carregue o modelo
Carregue o modelo usando o MLModel.Create
método estático:
var assetPath = NSBundle.MainBundle.GetUrlForResource("NameOfModel", "mlmodelc");
model = MLModel.Create(assetPath, out NSError error1);
3. Defina os parâmetros
Os parâmetros do modelo são passados para dentro e para fora usando uma classe de contêiner que implementa IMLFeatureProvider
.
As classes de provedor de recursos se comportam como um dicionário de cadeia de caracteres e MLFeatureValue
s, em que cada valor de recurso pode ser uma cadeia de caracteres ou um número simples, uma matriz ou dados ou um buffer de pixels contendo uma imagem.
O código para um provedor de recursos de valor único é mostrado abaixo:
public class MyInput : NSObject, IMLFeatureProvider
{
public double MyParam { get; set; }
public NSSet<NSString> FeatureNames => new NSSet<NSString>(new NSString("myParam"));
public MLFeatureValue GetFeatureValue(string featureName)
{
if (featureName == "myParam")
return MLFeatureValue.FromDouble(MyParam);
return MLFeatureValue.FromDouble(0); // default value
}
Usando classes como essa, os parâmetros de entrada podem ser fornecidos de uma maneira que seja compreendida pelo CoreML. Os nomes dos recursos (como myParam
no exemplo de código) devem corresponder ao que o modelo espera.
4. Execute o modelo
O uso do modelo requer que o provedor de recursos seja instanciado e os parâmetros definidos e, em seguida, que o GetPrediction
método seja chamado:
var input = new MyInput {MyParam = 13};
var outFeatures = model.GetPrediction(inputFeatures, out NSError error2);
5. Extraia os resultados
O resultado outFeatures
da previsão também é uma instância de ; os valores de IMLFeatureProvider
saída podem ser acessados usando GetFeatureValue
com o nome de cada parâmetro de saída (como theResult
), como neste exemplo:
var result = outFeatures.GetFeatureValue("theResult").DoubleValue; // eg. 6227020800
Usando o CoreML com o Vision Framework
O CoreML também pode ser usado em conjunto com a estrutura de visão para executar operações na imagem, como reconhecimento de forma, identificação de objetos e outras tarefas.
As etapas abaixo descrevem como o CoreML e o Vision podem ser usados juntos. O exemplo combina o reconhecimento de retângulos da estrutura Vision com o modelo MNINSTClassifier CoreML para identificar um dígito manuscrito em uma fotografia.
1. Criar um modelo CoreML de visão
O modelo CoreML MNISTClassifier é carregado e, em seguida, encapsulado em um VNCoreMLModel
que disponibiliza o modelo para tarefas de visão. Esse código também cria duas solicitações de visão: primeiro para localizar retângulos em uma imagem e, em seguida, para processar um retângulo com o modelo CoreML:
// Load the ML model
var bundle = NSBundle.MainBundle;
var assetPath = bundle.GetUrlForResource("MNISTClassifier", "mlmodelc");
NSError mlErr, vnErr;
var mlModel = MLModel.Create(assetPath, out mlErr);
var model = VNCoreMLModel.FromMLModel(mlModel, out vnErr);
// Initialize Vision requests
RectangleRequest = new VNDetectRectanglesRequest(HandleRectangles);
ClassificationRequest = new VNCoreMLRequest(model, HandleClassification);
A classe ainda precisa implementar os HandleRectangles
métodos and HandleClassification
para as solicitações Vision, mostradas nas etapas 3 e 4 abaixo.
2. Inicie o processamento da visão
O código a seguir inicia o processamento da solicitação. No exemplo CoreMLVision, esse código é executado depois que o usuário seleciona uma imagem:
// Run the rectangle detector, which upon completion runs the ML classifier.
var handler = new VNImageRequestHandler(ciImage, uiImage.Orientation.ToCGImagePropertyOrientation(), new VNImageOptions());
DispatchQueue.DefaultGlobalQueue.DispatchAsync(()=>{
handler.Perform(new VNRequest[] {RectangleRequest}, out NSError error);
});
Esse manipulador passa o ciImage
para a estrutura VNDetectRectanglesRequest
Vision que foi criada na etapa 1.
3. Lidar com os resultados do processamento da visão
Depois que a detecção do retângulo é concluída, ele executa o HandleRectangles
método, que corta a imagem para extrair o primeiro retângulo, converte a imagem do retângulo em escala de cinza e a passa para o modelo CoreML para classificação.
O request
parâmetro passado para esse método contém os detalhes da solicitação Vision e, usando o GetResults<VNRectangleObservation>()
método, ele retorna uma lista de retângulos encontrados na imagem. O primeiro retângulo observations[0]
é extraído e passado para o modelo CoreML:
void HandleRectangles(VNRequest request, NSError error) {
var observations = request.GetResults<VNRectangleObservation>();
// ... omitted error handling ...
var detectedRectangle = observations[0]; // first rectangle
// ... omitted cropping and greyscale conversion ...
// Run the Core ML MNIST classifier -- results in handleClassification method
var handler = new VNImageRequestHandler(correctedImage, new VNImageOptions());
DispatchQueue.DefaultGlobalQueue.DispatchAsync(() => {
handler.Perform(new VNRequest[] {ClassificationRequest}, out NSError err);
});
}
O ClassificationRequest
foi inicializado na etapa 1 para usar o HandleClassification
método definido na próxima etapa.
4. Manipular o CoreML
O request
parâmetro passado para esse método contém os detalhes da solicitação CoreML e, usando o GetResults<VNClassificationObservation>()
método, ele retorna uma lista de resultados possíveis ordenados por confiança (confiança mais alta primeiro):
void HandleClassification(VNRequest request, NSError error){
var observations = request.GetResults<VNClassificationObservation>();
// ... omitted error handling ...
var best = observations[0]; // first/best classification result
// render in UI
DispatchQueue.MainQueue.DispatchAsync(()=>{
ClassificationLabel.Text = $"Classification: {best.Identifier} Confidence: {best.Confidence * 100f:#.00}%";
});
}