coremltoolを使った画像認識でsvm形式のモデルを利用する3


<img src="https://qiita-image-store.s3.amazonaws.com/0/40693/eba4306f-8460-bdcd-a706-c98b6072497e.png" width="50%"><img src="https://qiita-image-store.s3.amazonaws.com/0/40693/c6432864-974d-e4a8-0a92-f85dec43c035.png" width="50%"><img src="https://qiita-image-store.s3.amazonaws.com/0/40693/cc7b3a18-c106-d983-b860-b8879876d2a6.png" width="50%"><img src="https://qiita-image-store.s3.amazonaws.com/0/40693/628657da-7680-ec0d-fc12-84e65c2e9d22.png" width="50%">


前回まで
[coremltoolを使った画像認識でsvm形式のモデルを利用する1](https://qiita.com/rnsm504/items/fde1b8347ff82b965e00)

[coremltoolを使った画像認識でsvm形式のモデルを利用する2](https://qiita.com/rnsm504/items/b7ab5a8cfb4d66c6f515)


### 開発環境

+ macOS 10.13
+ Swift4
+ XCode9
+ Python2.7


最後に前回で作ったmlmodelを評価する簡易なペイントアプリのプロジェクトを用意してmlmodelをドラッグする


![スクリーンショット 2017-12-02 15.20.23.png](https://qiita-image-store.s3.amazonaws.com/0/40693/ca42e755-a68f-a9ea-a29d-6fff33b5ccee.png "スクリーンショット 2017-12-02 15.20.23.png")


inputには784のDouble型の要素を持つ１次元配列。outputはInt64の数値が返ってくることになっているので、imageを784の配列に変換する必要がある。配列の中身は28x28のイメージを1pixelの色の濃淡を0〜１の間に表したものになる。
UIImageからCGImageを呼び出し、そこから各pixelのアドレスを呼び出し、色情報を取得する。

````
    func getPixelBuffer() -> [Double]
    {
        guard let cgImage = self.cgImage else {
            return []
        }
        let bytesPerRow = cgImage.bytesPerRow
        let width = cgImage.width
        let height = cgImage.height
        let bytesPerPixel = 4
        let pixelData = cgImage.dataProvider!.data! as Data
        var buf : [Double] = []
        
        for j in 0..<height {
            for i in 0..<width {
                let pixelInfo = bytesPerRow * j + i * bytesPerPixel
                let r = CGFloat(pixelData[pixelInfo])
                let g = CGFloat(pixelData[pixelInfo+1])
                let b = CGFloat(pixelData[pixelInfo+2])
//                let a = CGFloat(pixelData[pixelInfo+3]) / CGFloat(255.0)
                
                let v = floor(Double(r + g + b)/3.0)/255.0
                buf.append(v)
            }
        }
        
        return buf
    }

````

後は算出した配列をMLMultiArrayにセットしたものを、mlmodelの引数にセットすれば結果がかえってきます。

````
        // 画像を配列で返す
        let imageData = reIma.getPixelBuffer()
        let count = imageData.count
        
        let ncount = count as NSNumber
        let mlarray = try! MLMultiArray(shape: [ncount], dataType: MLMultiArrayDataType.double )
        for i in 0 ..< count {
            mlarray[i] = imageData[i] as NSNumber
        }
        
        let model = my_model()
        guard let output = try? model.prediction(input: mlarray) else {
            fatalError("error")
        }
        print("label = \(output.target)")
        
        let target = Int64(output.target)

````

・・・まあ体感的にはあまり精度良く無いのですが、手書きだとそんなものかなあという感じです。


### 参考

参考というかそのまま使わせてもらってます。

[Swift3でUIImageの色情報を抜き出す](https://ja.stackoverflow.com/questions/34519/swift3%E3%81%A7uiimage%E3%81%AE%E8%89%B2%E6%83%85%E5%A0%B1%E3%82%92%E6%8A%9C%E3%81%8D%E5%87%BA%E3%81%99)

[『iOS11』新搭載の「Core ML」を駆使してMNISTの手書き数字認識を試してみた](http://bitwave.showcase-tv.com/%E3%80%8Eios11%E3%80%8F%E6%96%B0%E6%90%AD%E8%BC%89%E3%81%AE%E3%80%8Ccore-ml%E3%80%8D%E3%82%92%E9%A7%86%E4%BD%BF%E3%81%97%E3%81%A6mnist%E3%81%AE%E6%89%8B%E6%9B%B8%E3%81%8D%E6%95%B0%E5%AD%97%E8%AA%8D/2/)