[SWIFT] [Core ML] Convertissez Cycle GAN en Core ML et exécutez-le sur iOS

J'écrirai comment convertir Cycle GAN en Core ML.

Le contenu est fondamentalement le même que celui du prochain article, mais à partir du 1er novembre 2020, la conversion de modèle peut être effectuée avec Core ML Tools au lieu de tf-coreml, donc j'écrirai la différence dans cette partie.

Convertir Cycle GAN en modèle mobile (CoreML) https://qiita.com/john-rocky/items/3fbdb0892b639187c234

En conclusion, vous pouvez convertir chaque version de bibliothèque sans aucun problème en procédant comme suit.

tensorflow==2.2.0
keras==2.2.4
coremltools==4.0

procédure

J'écrirai la procédure dans Google Colaboratory.

** 1. Ouvrez le didacticiel TensorFlow **

Ouvrez le tutoriel à partir de cette page https://colab.research.google.com/github/tensorflow/docs/blob/master/site/en/tutorials/generative/cyclegan.ipynb

** 2. Faites correspondre chaque version de bibliothèque avec Core ML Tools 4.0 **

Désinstallez le tensorflow et les keras d'origine de Colab, puis réinstallez la version appropriée. Installez également Core ML Tools 4.0. Vous devrez peut-être redémarrer l'environnement d'exécution de Google Colab.

Notebook


!pip uninstall -y tensorflow
!pip uninstall -y keras
!pip install tensorflow==2.2.0
!pip install keras==2.2.4
!pip install -U coremltools==4.0

** 3. Effectuez l'apprentissage selon le tutoriel **

Vous pouvez apprendre Cycle GAN simplement en exécutant le didacticiel de haut en bas, alors continuez tel quel.

** 4. Enregistrez le modèle et convertissez-le en Core ML **

Enregistrez le modèle TensorFlow.

Notebook


generator_g.save('./savedmodel')

Convertissez en Core ML. Les arguments sont beaucoup plus simples que tf-coreml.

Notebook


import coremltools as ct

input_name = generator_g.inputs[0].name.split(':')[0]
print(input_name) #Check input_name.
keras_output_node_name = generator_g.outputs[0].name.split(':')[0]
graph_output_node_name = keras_output_node_name.split('/')[-1]

mlmodel = ct.converters.convert('./savedmodel/',
                       inputs=[ct.ImageType(bias=[-1,-1,-1], scale=2/255,shape=(1, 256, 256, 3,))],
                       output_names=[graph_output_node_name],
                 )

Enregistrez le modèle Core ML converti.

Notebook


mlmodel.save('./cyclegan.mlmodel')

** 5. Charger et afficher le modèle Core ML dans le projet Xcode **

Créez un projet dans Xcode.

Créez une application qui convertit les images de la caméra avec Cycle GAN.

Créez un écran simple avec un seul UIImageView et UIButton sur le Main.storyboard et connectez-le au contrôleur de vue. UIImage se connecte en tant que référence et UIButton se connecte en tant qu'action.

Cette fois, laissez le Vision Framework déduire, mais le résultat de l'inférence sera renvoyé en tant que type Multi Array. Vous devez le convertir en UIImage, mais c'est facile avec Core ML Helper. Pour cela, copiez le code source de CoreMLHelper.

En particulier https: // github.com / hollance / CoreMLHelpers / tree / master / CoreMLHelpers J'ai copié tout le code source ci-dessous dans mon projet.

Voici une référence pour savoir comment utiliser Core ML Helper.

Conversion de MultiArray vers Image CoreMLHelper https://qiita.com/john-rocky/items/bfa631aba3e7aabc2a66

J'écrirai le processus dans le contrôleur de vue. Je capture une image de caméra, je la transmets à Vision Framework, je la convertis en UIImage et je la colle dans une UIImageView.

Cette fois, j'ai interrompu le processus de transmission de l'image de la caméra à Vision Framework et d'extraction de l'IUImage du résultat de l'inférence dans une classe appelée CycleGanConverter.

ViewController.swift


import UIKit
import Vision

class ViewController: UIViewController, UIImagePickerControllerDelegate & UINavigationControllerDelegate {
    @IBOutlet weak var imageView: UIImageView!
    //Convertisseur Cycle GAN
    let converter = CycleGanConverter()

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func tappedCamera(_ sender: Any) {
        //Démarrez l'appareil photo lorsque vous appuyez sur le bouton de l'appareil photo
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera) {

            let picker = UIImagePickerController()
            picker.modalPresentationStyle = UIModalPresentationStyle.fullScreen
            picker.delegate = self
            picker.sourceType = UIImagePickerController.SourceType.camera

            self.present(picker, animated: true, completion: nil)
        }
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        defer {
            picker.dismiss(animated: true, completion: nil)
        }
        guard let image = info[UIImagePickerController.InfoKey(rawValue: UIImagePickerController.InfoKey.originalImage.rawValue)] as? UIImage else {return}
        //L'image prise par la caméra est entrée dans l'image variable
        //Conversion à la taille d'image à transmettre à Cycle GAN(Utiliser l'extension d'assistance CoreML)
        let resized = image.resized(to: CGSize(width: 256, height: 256))
     //Converti car il doit être passé en tant que type cgImage
        guard let cgImage = resized.cgImage else {return}
        //Passer au convertisseur
        converter.convert(image: cgImage) {
            images in
            //Le convertisseur renvoie le résultat dans le tableau d'images si la conversion réussit
            guard images.count > 0 else {return}
            let image = images.first!
            DispatchQueue.main.async {
                //Coller dans UIImageView
                self.imageView.image = image
            }
        }
    }
}

class CycleGanConverter {

    func convert(image: CGImage, completion: @escaping (_ images: [UIImage]) -> Void) {
        //Configurer le cadre de vision
        let handler = VNImageRequestHandler(cgImage: image,options: [:])

        let model = try! VNCoreMLModel(for: cyclegan().model)
        let request = VNCoreMLRequest(model: model, completionHandler: {
            [weak self](request: VNRequest, error: Error?) in
            //Puisque le résultat de l'inférence est renvoyé à la demande de variable, convertissez-le avec la méthode perseImage.
            guard let images = self?.parseImage(request: request) else {return}
            completion(images)
        })

        try? handler.perform([request])
    }
    
    func parseImage(request: VNRequest) -> [UIImage] {
        guard let results = request.results as? [VNCoreMLFeatureValueObservation] else {return []}
        //featureValue de chaque élément dans le tableau de résultats.Étant donné que l'image convertie est incluse dans multiArrayValue, convertissez-la en UIImage
        return results.compactMap {
            $0.featureValue.multiArrayValue?
                .image(min: -1, max: 1, channel: nil, axes: (3,2,1))? //Une méthode de Core ML Helper qui se convertit en UIImage
                .rotated(by: 90) //Faire pivoter pour afficher l'écran
                .withHorizontallyFlippedOrientation() //Inverser pour l'affichage à l'écran
        }
    }
}

terminer

<Après la conversion>

Cette fois, en raison de contraintes de temps, le nombre de formations a été considérablement réduit par rapport à celui spécifié dans le tutoriel, les résultats de conversion sont donc raisonnables.

Si vous vous entraînez conformément au didacticiel, vous devriez obtenir de meilleurs résultats de conversion.

finalement

Note publie régulièrement sur le développement iOS, alors suivez-nous. https://note.com/tokyoyoshida

Il est également publié sur Twitter. https://twitter.com/jugemjugemjugem

Recommended Posts

[Core ML] Convertissez Cycle GAN en Core ML et exécutez-le sur iOS
[Core ML] Comment convertir YOLO v3 en Core ML
Je ne pouvais pas exécuter le traitement avec jdk-9, donc je suis revenu à jdk-1.8 et cela a fonctionné sur Eclipse OXYGEN
Exécutez Rubocop et RSpec sur CircleCI et déployez-le sur ECS
Comment exécuter React et Rails sur le même serveur
Installez Ubuntu20.04 sur RaspberryPi 4 et compilez Kubernetes pour exécuter le conteneur
Étapes pour installer Maven sur Mac et l'utiliser avec Eclipse
Étapes pour exécuter Docker sur Mac
Pour exécuter JavaFX sur Docker
Comment convertir LocalDate et Timestamp
Étapes pour exécuter le développement local d'ASP.NET Core sur Mac avec docker-compose