Create MLの新機能Style Transfer（WWDC2020,iOS14）.

#WWDC2020の新機能を試す
Create MLに初の画像出力モデルStyle Transferが追加されました。
これがなかなか、痒いところに手が届く便利な機能がついています。

<img width="475" alt="スクリーンショット 2020-07-23 8.21.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/2f163320-01d6-a69d-f872-50c124a2ea8d.png">
![Jul-23-2020 08-06-56.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/e79a6bca-cb4f-890a-632c-b10c6b74782a.gif)


**Videoをスタイル変換できる高速モデルも追加されています。**

#手順はシンプル

・スタイル画像１枚
・トレーニング経過チェックのための検証画像１枚
・コンテンツ画像複数枚
を用意します。
Trainボタンで学習が開始、数分で完了します。

#便利なところ
####**計算回数、スタイル適用の強度（Strenth)、密度（Density）が指定できます**
・計算回数…デフォルトの500でだいたいそれらしくスタイル変換されました。
 ただ、多めに計算した方が綺麗な結果が出る（ような気がします）。添付したGIFは１２００iterations。それでも１０分で終わります。
・**強度を高めると、色、エッジともにスタイル画像の影響が大きくなります。**
・**密度を高めると、スタイル画像の細い領域のパターンを適用し、弱めると広い領域のパターンを適用します。**
画像左から、
*（強度５,密度５:デフォルト） ／ （強度１０,密度５） ／（強度５,密度１０）*Videoモデル
<img width="500" alt="スクリーンショット 2020-07-23 10.10.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/4bd43b68-fb32-69bb-1222-c4d45073cc9a.png">


####**中間画像結果を細かく確認できます**
学習中5iterationごとに中間画像を表示してくれます。


####**中間モデルを細かく保存できます**
Snapshotボタンを押すと、学習途中のモデルを保存できます。
途中経過を見比べて選定したいときに便利です。

####**プリセットのコンテンツ画像があります**
Natural Content Datasetsという６００枚の風景画像がダウンロードできます。

####軽量モデルです
Videoモデルが595KB
Imageモデルが6.5MB
でした。

#VideoモデルとImageモデルのちがい。
・Imageモデルはトレーニングの収束も１０倍ぐらいかかります（と言っても数分の違いですが）。
[結果の綺麗さのちがいは僕はわかりませんでした。(Google Drive:左ビデオモデル：右画像モデル)](https://drive.google.com/file/d/1UTU5dq9ww2Qeark3S4fsXTd8xLOo8yTV/view?usp=sharing)
・UIViewでパラパラビデオにしてみると、やはりVideoの方が滑らかでした。
 Capture Outputを食わせた時のCPUUsageは、ビデオが１０〜２０％、イメージが10弱でイメージの方が小さいですが、
メモリ使用がビデオ６０MB、イメージ２５０MBとイメージが４倍大きかったです。
（iPod Touch使用）


#感想
**GUIで結果もすぐ見れるので、オプションを調整したり画像を変えたり、いろんなスタイルを試すのがたのしくなりました。**

#iOSプロジェクトでモデルを使う
モデルは入出力ともに512pixelのColor Imageです。
従来通りVisionのVNCoreMLRequestで処理できます。
AVFoundationのCapture OutputをCMSampleBufferGetImageBufferして入力にしています。
**結果はPixelBufferです。**

```swift:ViewController.swift
    lazy var coreMLRequest:VNCoreMLRequest = {
        let model = try! VNCoreMLModel(for: windStyle().model)
        let request = VNCoreMLRequest(model: model, completionHandler: self.coreMLCompletionHandler0)
        return request
    }()
```

```swift:ViewController.swift
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
            guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
                return
            }
            currentBuffer = pixelBuffer
           
            let exifOrientation = exifOrientationFromDeviceOrientation()
            let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer:currentBuffer!, orientation: exifOrientation, options: [:])
            do {
                try imageRequestHandler.perform([self.coreMLRequest])
            } catch {
                print(error)
            }
    }
```

Videoとして高速でレンダリングするにはMetalとかを使わないといけないと思うので、以下の記事を参考にしてください。

[Qiita:Metalでカメラからの動画入力をリアルタイム処理する](https://qiita.com/shu223/items/2e493645e2d9a1e35a0d)

ぼくはMetalを勉強せず、UIViewでパラパラVideoにしました。
Capture Output全部食わせてもcpu使用率１０％とかだったので、モデル処理は軽量なのだと思います。
[UIViewで描画した動画です（GoogleDrive：最初にカッコつけたGIF貼って容量超えたので貼れなくなりました)。興味ある方はどうぞ。]
(https://drive.google.com/file/d/1GDOS-5dXXMTDl4D5ph3TlhkvSUkltVXy/view?usp=sharing)



・・・

機械学習関連の情報を発信しています。
https://twitter.com/JackdeS11

Core MLやCreate ML、Visionを使ったアプリを作っています。
rockyshikoku@gmail.com

　　　　　　　　　　　　↓