[SWIFT] [Core ML] Konvertieren Sie Cycle GAN in Core ML und führen Sie es unter iOS aus

Ich werde schreiben, wie man Cycle GAN in Core ML konvertiert.

Grundsätzlich der gleiche Inhalt wie im nächsten Artikel, aber ab dem 1. November 2020 kann die Modellkonvertierung mit Core ML Tools anstelle von tf-coreml durchgeführt werden, daher werde ich den Unterschied dieses Teils schreiben.

Konvertieren Sie Cycle GAN in ein mobiles Modell (CoreML). https://qiita.com/john-rocky/items/3fbdb0892b639187c234

Zusammenfassend können Sie jede Bibliotheksversion problemlos konvertieren, indem Sie die folgenden Schritte ausführen.

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

Verfahren

Ich werde das Verfahren in Google Colaboratory schreiben.

** 1. Öffnen Sie das TensorFlow-Tutorial **

Öffnen Sie das Tutorial von dieser Seite https://colab.research.google.com/github/tensorflow/docs/blob/master/site/en/tutorials/generative/cyclegan.ipynb

** 2. Ordnen Sie jede Bibliotheksversion Core ML Tools 4.0 zu **

Deinstallieren Sie den ursprünglichen Tensorflow und die Keras von Colab und installieren Sie die entsprechende Version neu. Installieren Sie außerdem Core ML Tools 4.0. Möglicherweise müssen Sie die Google Colab-Laufzeit neu starten.

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. Führen Sie das Lernen gemäß dem Tutorial durch **

Sie können Cycle GAN lernen, indem Sie das Lernprogramm von oben nach unten ausführen. Fahren Sie also so fort, wie es ist.

** 4. Speichern Sie das Modell und konvertieren Sie es in Core ML **

Speichern Sie das TensorFlow-Modell.

Notebook


generator_g.save('./savedmodel')

In Core ML konvertieren. Die Argumente sind viel einfacher als 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],
                 )

Speichern Sie das konvertierte Core ML-Modell.

Notebook


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

** 5. Laden und Anzeigen des Core ML-Modells im Xcode-Projekt **

Erstellen Sie ein Projekt in Xcode.

Erstellen Sie eine App, die Kamerabilder mit Cycle GAN konvertiert.

Erstellen Sie einen einfachen Bildschirm mit nur einem UIImageView und UIButton auf dem Main.storyboard und verbinden Sie ihn mit dem View Controller. UIImage stellt eine Verbindung als Referenz und UIButton eine Verbindung als Aktion her.

Lassen Sie diesmal das Vision Framework schließen, aber das Inferenzergebnis wird als Multi-Array-Typ zurückgegeben. Sie müssen dies in ein UIImage konvertieren, aber mit Core ML Helper ist das ganz einfach. Kopieren Sie dazu den Quellcode von CoreMLHelper.

Speziell https: // github.com / hollance / CoreMLHelpers / tree / master / CoreMLHelpers Ich habe den gesamten folgenden Quellcode in mein Projekt kopiert.

Hier finden Sie eine Referenz zur Verwendung von Core ML Helper.

Konvertierung von MultiArray zu Image CoreMLHelper https://qiita.com/john-rocky/items/bfa631aba3e7aabc2a66

Ich werde den Prozess in den View Controller schreiben. Ich nehme ein Kamerabild auf, übergebe es an das Vision Framework, konvertiere es in ein UIImage und füge es in ein UIImageView ein.

Dieses Mal habe ich den Prozess des Übergebens des Kamerabilds an das Vision Framework und des Extrahierens des UIImage des Inferenzergebnisses in eine Klasse namens "CycleGanConverter" abgeschnitten.

ViewController.swift


import UIKit
import Vision

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

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func tappedCamera(_ sender: Any) {
        //Starten Sie die Kamera, wenn die Kamerataste gedrückt wird
        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}
        //Das von der Kamera aufgenommene Bild wird in das variable Bild eingegeben
        //Konvertieren in die Bildgröße, die an Cycle GAN übergeben werden soll(CoreML Helper Extension verwenden)
        let resized = image.resized(to: CGSize(width: 256, height: 256))
     //Konvertiert, da es als cgImage-Typ übergeben werden muss
        guard let cgImage = resized.cgImage else {return}
        //Zum Konverter übergeben
        converter.convert(image: cgImage) {
            images in
            //Der Konverter gibt das Ergebnis im Bildarray zurück, wenn die Konvertierung erfolgreich ist
            guard images.count > 0 else {return}
            let image = images.first!
            DispatchQueue.main.async {
                //In UIImageView einfügen
                self.imageView.image = image
            }
        }
    }
}

class CycleGanConverter {

    func convert(image: CGImage, completion: @escaping (_ images: [UIImage]) -> Void) {
        //Richten Sie Vision Framework ein
        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
            //Da das Inferenzergebnis an die Variablenanforderung zurückgegeben wird, konvertieren Sie es mit der perseImage-Methode.
            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 jedes Elements im Ergebnisarray.Da das konvertierte Bild in multiArrayValue enthalten ist, konvertieren Sie es in UIImage
        return results.compactMap {
            $0.featureValue.multiArrayValue?
                .image(min: -1, max: 1, channel: nil, axes: (3,2,1))? //Eine Methode von Core ML Helper, die in UIImage konvertiert wird
                .rotated(by: 90) //Zur Bildschirmanzeige drehen
                .withHorizontallyFlippedOrientation() //Invertieren für Bildschirmanzeige
        }
    }
}

Fertig

Dieses Mal wurde aus zeitlichen Gründen die Anzahl der Schulungen im Vergleich zu der im Lernprogramm angegebenen erheblich reduziert, sodass die Konvertierungsergebnisse angemessen sind.

Wenn Sie gemäß dem Tutorial trainieren, sollten Sie bessere Conversion-Ergebnisse erzielen.

Schließlich

Hinweis veröffentlicht regelmäßig Informationen zur iOS-Entwicklung. Folgen Sie uns daher. https://note.com/tokyoyoshida

Es ist auch auf Twitter gepostet. https://twitter.com/jugemjugemjugem

Recommended Posts