Apple公式のセグメンテーション用Core MLモデル「DeeplabV3」
Appleが公式に配布するCore MLモデル[1]に「DeeplabV3」と呼ばれるセグメンテーション用モデルが追加されました。
iOSにおける他のセグメンテーション手段との違い
「DeeplabV3」モデルによるセグメンテーションは、iOSにおける他のセグメンテーション手段とどう違うのでしょうか。この比較により本モデルの利点や使いどころがより明確にわかるようになります。
「iOSで「髪」「肌」「歯」「空」をセグメンテーションする」で解説した "Portrait Effect Matte" や "Semantic Segmentation Matte" は高精細なセグメンテーションマスクを提供します。しかし、以下のような制約があります。
- 静止画からしか取得できない
- デプスを撮影可能なカメラ(デュアルカメラまたはTrueDepthカメラ)で撮影する必要がある
- 特定のオブジェクト(髪、肌、歯、空)だけが対象
またiOS 13 / ARKit 3で登場した「People Occlusion」はリアルタイムでセグメンテーションを行うものですが、以下のような制約があります。
- ARKitでしか使えない。つまり、既存の動画や静止画には使えない。
- 人間だけが対象
- iOS 13以上でしか使えない
- A12 Bionicチップが必要
一方、Core MLの「DeeplabV3」モデルは、
-
人間以外のオブジェクト(人間、犬、猫、etc...)もセグメンテーション可能
- 具体的なラベルのリストを本記事の末尾に掲載しています。
- 動画でも静止画でも、リアルタイムでもオフラインでも使用可能
- デプスを含まない静止画や動画フレームにも適用可能
- iOS 12以上で使用可能
- デバイスを問わない(iOS 12が動くデバイスすべてで利用可能)
と、非常に幅広い場面・条件下で利用可能です。
DeeplabV3を利用したリアルタイムセグメンテーションの実装
DeeplabV3.mlmodel
を使用して、カメラから得られる画像からリアルタイムにセグメンテーションを行ってみましょう。
推論処理実行までの基本実装は「Apple公式のデプス推定Core MLモデル「FCRN-DepthPrediction」」の「基本実装(推論処理実行まで)」と同等ですので、こちらではコードのみ載せておきます。
-
VNCoreMLModel
の初期化
private let depthModel = try! VNCoreMLModel(for: DeepLabV3().model)
-
VNCoreMLRequest
の初期化、設定
let request = VNCoreMLRequest(
model: depthModel, completionHandler: { request, error in
// 推論完了後の処理
...
})
request.preferBackgroundProcessing = true
request.imageCropAndScaleOption = .centerCrop
-
VNImageRequestHandler
を初期化し、処理を開始する
let handler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer)
try! handler.perform([request])
推論結果(MLMultiArray)の処理
上述の手順で推論処理は実行されますが、完了後の処理をまだ実装していません。モデルの入出力仕様を確認して、推論結果(セグメンテーション結果)の処理を実装していきましょう。
1. モデルの入出力仕様を確認する
DeeplabV3.mlmodel
をプロジェクトに追加し、Xcodeで見てみると、次のように入出力仕様を確認できます。
入力として513 x 513
のカラー画像(RGB画像)を受け取り、シェイプが(513 x 513)
で値がInt32
のMLMultiArray
オブジェクトを出力することがわかります。
入力と出力でサイズが同じですが、出力画像の各ピクセル値が示すものは色やデプスではなく、当該ピクセルが分類されたクラスを示します[2]。
2. 推論結果のMLMultiArrayオブジェクトを取得する
本モデルもデプス推定モデルと同様に出力の型がMLMultiArray
なので、次のようにVNRequest
オブジェクトからMLMultiArray
オブジェクトを取り出せます。[3]
guard let result =
request.results?.first as? VNCoreMLFeatureValueObservation
else { return }
guard result.featureValue.type == .multiArray else { fatalError() }
let multiArray = result.featureValue.multiArrayValue!
3. MLMultiArrayをCGImageに変換する
ここでもMLMultiArray
の処理のため「CoreMLHelpers」[4]を利用します。このヘルパーライブラリのextensionを利用して、次のようにMLMultiArray
をCGImage
に変換します。
let cgImage = multiArray.cgImage(min: min, max: max)!
あとはこのピクセル値に応じて入力画像をセグメンテーションクラスごとに塗り分けたり、マスクとして使用して背景合成を行ったりといったことが可能になります。
セグメンテーション結果を用いて入力画像を塗り分け
DeeplabV3 のラベル一覧
DeeplabV3モデルでは以下のものをセグメンテーションできます。
- background
- aeroplane
- bicycle
- bird
- boat
- bottle
- bus
- car
- cat
- chair
- cow
- diningTable
- dog
- horse
- motorbike
- person
- pottedPlant
- sheep
- sofa
- train
- tvOrMonitor
こちらにソースコードがあり、どのようなデータセットで学習されたかが確認できます。
モデルの情報・更新履歴
DeeplabV3のApple公式のCore MLモデルは2019年が初出ですが、以降もたびたび(ひっそりと)更新されています [5]。
モデルの種類
種類・ファイルサイズはバージョンに関わらず共通。
- DeepLabV3.mlmodel
- 8.6 MB
- DeepLabV3FP16
- 4.3MB
- DeepLabV3Int8LUT
- 2.3MB
モデルのバージョン
- モデルバージョン: 1.3
- coremltoolsバージョン: 3.4
- モデルバージョン: 1.1
- coremltoolsバージョン: 4.0a6
- モデルバージョン: ---(初出時はバージョン情報なし)
1.3のcoremltools(coremltoolsVersion
)は間違ってるような...?
-
ここでの「クラス」は、プログラミング言語におけるクラスの話ではなく、分類タスクにおけるクラスのことです。 ↩︎
-
本手順の解説は、「Apple公式のデプス推定Core MLモデル「FCRN-DepthPrediction」」の「2. 推論結果のMLMultiArrayオブジェクトを取得する」にあります。 ↩︎
-
AppleのCore MLモデル配布サイトを見ても更新情報はまったく書かれていないので、毎年WWDC期間中やcoremltoolsのメジャーアップデートがリリースされるタイミングでダウンロードして確認しています。 ↩︎
Discussion