//#-hidden-code
//
//  See LICENSE folder for this template’s licensing information.
//
//  Abstract:
//  The Swift file containing the source code edited by the user of this playground book.
//


import PlaygroundSupport
import AudioToolbox
import Foundation
import UIKit
import CoreML
import Vision

let page = PlaygroundPage.current

page.needsIndefiniteExecution = true

func vprint(_ str: String) {
   if let proxy1 = page.liveView as? PlaygroundRemoteLiveViewProxy {
       let message: PlaygroundValue = .string(str)
       proxy1.send(message)
   }
}



//ビューのイメージを受信した場合の処理
let proxy2 = page.liveView as? PlaygroundRemoteLiveViewProxy
class pgListener: PlaygroundRemoteLiveViewProxyDelegate {
    func remoteLiveViewProxy(_ remoteLiveViewProxy: PlaygroundRemoteLiveViewProxy,received message: PlaygroundValue) {
        if case let .data(imageData) = message {
            myImage = UIImage(data: imageData)!
            receiveImage()
            //vprint("写真を受け取りました。")
        } else {
            //イメージ失敗
            let soundIdRing:SystemSoundID = 1006
            AudioServicesPlaySystemSound(soundIdRing)
        }
    }
    func remoteLiveViewProxyConnectionClosed(_ remoteLiveViewProxy: PlaygroundRemoteLiveViewProxy) {
    //コネクション切断時の処理
    }
}
let pglistener = pgListener()
proxy2?.delegate = pglistener
//#-end-hidden-code
/*: some text
 ##  2️⃣手書きの数字を認識する
このページでは、数字を認識するための機械学習モデル（学習済み）として公開されている\
 MNISTClassifier\
を使用して、数字を特定します。
 * Note:
 　このブックでは、機械学習用APIのCoreML、画像処理用APIのVisionフレームワークを使用しています。
 ---
 */

//描画イメージデータ保持用
var myImage = UIImage()
// 使用するCore MLモデルのインスタンスを生成
let model = try MLModel(contentsOf: try MLModel.compileModel(at:#fileLiteral(resourceName: "MNISTClassifier.mlmodel")))
//Core MLモデルをVNCoreMLModelに変換
let coreMLModel = try VNCoreMLModel(for: model)
//解析リクエストを定義する。
let request = VNCoreMLRequest(model: coreMLModel, completionHandler: { (request, error) in
     // 解析結果を分類情報として保存
     guard let results = request.results as? [VNClassificationObservation] else {
         return
     }
    // 画像内の一番解析割合が大きいオブジェクトを文字列で表示する。
    if let firstResult = results.first {
                vprint("この画像の認識結果は : " + firstResult.identifier + " でした")
    }
})

//描画イメージを受け取った際に呼び出される。
//※受け取った描画イメージはmyImageに保存されてから呼び出されます。
func receiveImage() {
    // Visionへリクエストを送るためにUIImage→CIImageへ変換する
    let ciImage = CIImage(image: myImage)
    let handler = VNImageRequestHandler(ciImage: ciImage!)
    // 画像解析リクエストを実行
    do {
        try handler.perform([request])
    }
    catch {
        print(error)
    }
}

