その後のその後

iOSエンジニア 堤 修一のブログ github.com/shu223

Core ML Tools実践入門に「mlmodelファイルフォーマット」の章を加筆しました #技術書典

拙著「Core ML Tools実践入門」に加筆した新版を公開しました。

shu223.hatenablog.com

BOOTH、技術書典 応援祭コンカで電子版をご購入の方は新版を無料でダウンロードしていただけます。

mlmodelファイルフォーマットについて知ると何が嬉しいのか?

知ると嬉しいというより、知らないと損している、といっても過言ではないと思っています。

iOS開発にたとえるのであれば、APIリファレンスの読み方がわからず開発をしているようなものかと。たとえばこの章に書いてあることを理解していないと、たとえば画像分類(Image Classification)を行う.mlmodelモデルでクラスラベルの一覧を出力したいと思ってもどのように出力するのか、そもそも可能なのかといったことがわからないわけです。

クラスラベル一覧はほんの一例で、mlmodelのファイルフォーマットについて理解しておくと、mlmodelの持つあらゆる情報にアクセスできるようになります。coremltoolsを用いてモデルを自作する際、デバッグや最適化に大いに役立つことでしょう。

「Core ML Tools実践入門」という本を書きました #技術書典

iOS×機械学習といえばCore ML。既製のCore MLモデルを扱うのは非常に簡単なのですが、

  • TensorFlowやKeras等の機械学習ツールで作成した独自モデルをCore MLモデルに変換したい
  • モデルサイズを小さくしたい
  • 複数サイズの入力をサポートしたい
  • オンデバイスで更新できるようにしたい

等々、つまり 自分でCore MLモデルをつくりたい・カスタマイズしたい場合にはCore ML Tools(coremltools)を使いこなすことが不可欠 です。

が、こんなに重要なツールなのに意外にも情報が少なく、日本語情報どころか英語の公式ドキュメントすら全然網羅的ではありません

というわけで自分で勉強しつつ書いた本がこちらです1

f:id:shu223:20200309090337j:plain

Core ML Toolsの利用方法を実践形式でさまざまなモデルをつくりながら学んでいきます。最初はわずか2行のコードで変換することからはじめてCore ML Toolsに入門しつつ、もっと高度な変換方法や、モデルのサイズを縮小する方法、パイプラインを構築する歩法、オンデバイスで学習できるようにする方法等も解説していきます。

また巻末には「逆引きリファレンス」も収録しています。開発の現場で「どう書くんだっけ?」となったときに大いに役立つことでしょう。

A5版、150ページ。サンプルコードはGitHubよりダウンロード可能です。普段は電子版だけで2300円のところ、3月いっぱい開催される「技術書典 応援祭」期間中のみ紙+電子セット2000円で販売しています。40部しかないのでお早めに!

techbookfest.org

目次

第1章 準備

  • 1.1 Core ML Toolsとは
  • 1.2 Kerasとは
    • 1.2.1 KerasとCore ML Tools
    • 1.2.2 tf.kerasとスタンドアロン版Keras
  • 1.3 Keras/TensorFlow/Core ML Toolsの環境構築

第2章 Core ML Toolsはじめの一歩

  • 2.1 2行のコードで学習済みモデルをロードする
  • 2.2 2行のコードでCore MLモデルに変換する
  • 2.3 変換したモデルを.mlmodelファイルとして保存

第3章 Core MLモデル作成の基礎

  • 3.1 HDF5ファイルを読み込む
  • 3.2 Core MLモデルに変換する
  • 3.3 Core MLモデルの入力の型を変更する
  • Core MLモデルから自動生成されるSwiftコード
  • Visionはどのように画像分類モデルを判定するか?

第5章 オンデバイス学習 - UpdatableなCore MLモデルの作成

  • 5.1 モデルのパーソナライゼーション
  • 5.2 ベースとなるモデルの作成
  • 5.3 Updatableなモデルに変換する
  • 5.4 損失関数をセットする
  • 5.5 最適化アルゴリズムをセットする
  • 5.6 エポック数をセットする
  • 5.7 モデルを保存する

第6章 オンデバイス学習 - iOSで学習

  • 6.1 MLUpdateTask
    • 6.1.1 mlmodelc
    • 6.1.2 MLBatchProvider, MLArrayBatchProvider
    • 6.1.3 MLTask
    • 6.1.4 オンデバイスモデル更新タスクの全体感
  • 6.2 学習データの準備
  • 6.3 学習タスクの実行
  • 6.4 オンデバイスで学習したモデルを保存する / MLUpdateContext, MLWritable
  • 6.5 推論処理の実行

f:id:shu223:20200309090819g:plain

第7章 TensorFlowモデルの変換 - 基礎編

  • 7.1 tfcoreml
  • 7.2 tfcoremlを用いたCore MLモデルへの変換(最小実装)
    • 7.2.1 学習済みモデル(.pbファイル)を読み込む
    • 7.2.2 出力テンソルの名前を取得する
    • 7.2.3 tfcoremlを用いて変換する
  • 7.3 より扱いやすいCoreMLモデルに変換する
    • 7.3.1 クラスラベルを指定する
    • 7.3.2 入力の型を画像に変更する
  • 7.4 iOSで推論を実行
  • 7.5 入力画像の前処理を指定する

第8章 TensorFlowモデルの変換 - 画風変換モデル

  • 8.1 学習済みモデルからグラフ定義を読み込む
  • 8.2 変換に必要なグラフの情報を取得する
    • 8.2.1 入力テンソルの名前を取得する
    • 8.2.2 出力テンソルの名前を取得する
  • 8.3 tfcoremlを用いて変換する
    • 8.3.1 入力テンソルのshapeを指定する
  • 8.4 Core MLモデルの出力の型を変更する
  • 8.5 iOSで画風変換を実行
    • 8.5.1 複数の入力を持つCore MLモデルをVisionで使う
    • 8.5.2 出力画像を取得する

f:id:shu223:20200309090946g:plain

第9章 Flexible Shape - 超解像モデル

  • 9.1 Flexible Shapeとは/使いどころ
  • 9.2 超解像モデルをCore MLモデルに変換する
  • 9.3 Flexible Shapeを適用する
  • 9.4 iOS側での推論処理の実行

第9章 Core MLモデルのサイズを小さくする

  • 9.1 本章で利用する感情認識モデルについて
  • 9.2 重みを16ビット化する
    • 9.2.1 16ビット化が推論結果の精度に与える影響
    • 9.2.2 Core MLモデルを16ビット化する手順
  • 9.3 クォンタイズ
  • 9.4 iOSでの推論結果の比較
  • 9.5 さらなるモデルサイズ削減
    • 9.5.1 ルックアップテーブルを利用した量子化
    • 9.5.2 モデルの一部を共通化

第10章 パイプラインモデルとリンクモデル(Linked Model)

  • 10.1 パイプラインの構築
    • 10.1.1 coremltools.models.pipelineモジュール
    • 10.1.2 PipelineClassifierオブジェクトの生成
    • 10.1.3 パイプラインにモデルを追加
    • 10.1.4 MLModel オブジェクト生成
  • 10.2 リンクモデル(LinkedModel)
    • 10.2.1 リンクモデルとは/リンクモデルを使用するメリット
    • 10.2.2 パイプラインとリンクモデル
    • 10.2.3 リンクモデルの作成方法
  • CreateMLのモデルはなぜ小さいのか
    • CreateMLとパイプライン
    • Vision FeaturePrint

第11章 モデルの可視化

  • 11.1 Netron
  • 11.2 coremltoolsのvisualize_spec
  • 11.3 TensorBoard
    • 11.3.1 TensorFlowモデルのグラフを可視化
    • 11.3.2 Kerasでの学習状況を可視化
  • 11.4 Kerasのplot_model

付録A coremltools逆引きリファレンス

  • A.1 MLModelオブジェクトを生成する
    • A.1.2 .mlmodelファイルから生成する
    • A.1.1 Specから生成する
  • A.2 モデルのSpecを取得する
    • A.2.1 .mlmodelファイルから取得する
    • A.2.2 MLModelオブジェクトから取得する
  • A.3 .mlmodelファイルの保存・読み込み
    • A.3.1 .mlmodelファイルを読み込む
    • A.3.2 .mlmodelファイルとして保存する
  • A.4 NeuralNetworkBuilderを生成する
  • A.5 モデルの中身を調べる
    • A.5.1 モデルを可視化(ビジュアライズ)する
    • A.5.2 モデルのバージョン(Specification Version)を確認する
    • A.5.3 Specをログに出力する
    • A.5.4 ネットワークの情報をログに出力する
    • A.5.5 NeuralNetworkBuilderでモデルの入力・出力形式を確認する
    • A.5.6 モデルのレイヤー一覧を出力する
    • A.5.7 モデルの中間層の入出力形式を調べる
  • A.6 Core MLモデルにクラスラベルを与える
    • A.6.1 ラベル文字列の配列を渡す
    • A.6.2 クラスラベルファイルのパスを渡す
  • A.7 モデルの入力・出力をカスタマイズする
    • A.7.1 入力・出力名を指定する
    • A.7.2 変換時に入力の型を画像型にする
    • A.7.3 変換済みモデルの入力・出力の型を画像型にする
    • A.7.4 入力テンソルのshapeを指定する
    • A.7.5 入力画像の前処理を指定する
  • A.8 モデルサイズを圧縮する
    • A.8.1 重みを16ビット(半精度)化する
    • A.8.2 重みをクォンタイズする
  • A.9 オンデバイス学習関連
    • A.9.1 モデルがUpdatableかどうかを調べる
    • A.9.2 Updatableなレイヤー一覧を出力
    • A.9.3 Updatableなモデルに変換する
    • A.9.4 学習で使用する損失関数をセットする
    • A.9.5 損失関数のサマリを確認する
    • A.9.6 学習で使用する最適化アルゴリズム(オプティマイザ)をセットする
    • A.9.7 最適化アルゴリズムを確認する
    • A.9.8 エポック数をセットする
  • A.10 FlexibleShape関連
    • A.10.1 FlexibleShapeの適用可否を確認する
    • A.10.2 入力・出力の画像サイズを範囲で指定する
    • A.10.3 入力・出力に複数の画像サイズを指定する
  • A.11 misc.
    • 利用中のcoremltoolsのバージョンを確認する

付録B Kerasでカスタムモデル作成

  • B.1 モデルのネットワークを定義する
    • B.1.1 Sequential モデル(とKeras functinal API)
    • B.1.2 Conv2D
    • B.1.3 MaxPooling2D
    • B.1.4 Dropout
    • B.1.5 Flatten
    • B.1.6 Dense
    • B.1.7 モデルのサマリを確認
  • B.2 モデルのコンパイル
    • B.2.1 損失関数
    • B.2.2 最適化アルゴリズム
    • B.2.3 評価関数
  • B.3 モデルの学習
  • B.4 評価
  • B.5 モデルの保存

  1. 日本語でのCore ML Tools専門書は初ですし、今後も出てこないと思います。

フリーランスのお仕事まとめ2019

2020年に入って既に10分の1ほど過ぎてしまいましたが、2019年にやったお仕事のまとめです。

機械学習×iOS

  • とある有名アプリへの機械学習モデル組み込み実装
    • 実稼働中
    • 実績公開OKか未確認なので控えておく
  • 「まごチャンネル」の子供写真検出

  • とある広告案件向けのプロトタイプ
    • 個人的には関われてめちゃくちゃ嬉しいし内容もおもしろいのだけどまだまだ公開できない

ARKit, Metal, デプス, カメラ, 画像処理関連

  • とある海外のアプリの動画向けエフェクト
    • 渡航費や滞在費は先方持ちで1週間海外に滞在
    • MetalやARKit 3を用いた動画エフェクトの実装
  • とあるカメラアプリへのデプス関連機能実装
    • watchOSも使用
  • アプリで3Dスキャン -> 3Dプリントデータ作成(プロトタイプ)
  • とある雑誌×AR案件(プロト)
    • ARKitも他のARライブラリも使わないAR
  • とある海外案件でのデプス機能実装(その機能だけを実装したサンプルが成果物)

BLE関連

  • とあるIoTプロダクトを利用した実証実験用プロト開発
    • とある業界向けソリューションで、別の業界の現場に行けるのは楽しかった
  • とあるスマートロック
    • BLEのパフォーマンス改善・・・起動〜利用開始までの所要時間が数分の1に短縮された(結局要因はBLEだけではなかったが)

展示系

  • ニューヨークのポスター美術館「Poster House」のサイネージ向けmacOSアプリ(BASSDRUM)

(9月には義母が手伝いに来てくれて、念願かなってNYに実際に見に行くことができた)

  • 「不思議な宿」のiPadアプリ(ブルーパドル)

www.youtube.com

技術書の執筆

2019年のひとつのテーマは「技術発信のマネタイズ」だったが少しずつ結実してきた。

新刊

  • Keras & Core ML Tools
    • 今一番力をいれて更新しています
    • 「詳解Core ML Tools - coremltools, Keras, TensorFlow」に改題予定

既刊の更新

その他発信活動

  • 「三重県立桑名工業高校」での講演

note.com

  • noteの有料マガジン
    • 有料バリアにより心理的安全に守られつつ日々の勉強メモを気軽に投稿するための場
    • 合計143本書いた(←マガジン外の記事も含む)

  • 単価公開note
    • めちゃくちゃ売れた...技術書は3ヶ月フルコミットで書いて印税の合計50万いかないぐらいだったが、これは書くのに1時間もかかってなくてたぶん100万ぐらい売れた
    • しかしこれは自分の文章力とかじゃなく10年間ひたすらものをつくり行動し発信してきた結果なので再現性はまったくないと思っている

note.com

「エンジニアと人生」というYouTubeチャンネルを始めました

「エンジニアと人生」というYouTubeチャンネルを始めました。

www.youtube.com

技術の小難しい話はおいておいて、「生き様」に焦点をあてていろんなエンジニアにお話を伺う、というコンセプトの雑談チャンネルです

ソフトウェアエンジニアという職業は今や売り手市場で、パソコンとネットがあればどこでも仕事ができ、国や言語を超えて通用し、ブログやオープンソースで発信することでプレゼンスも向上しやすく、「生き方の選択肢が多い」職業のひとつです。エンジニアにもそうでないみなさまにも、人生の可能性を感じてワクワクしていただけるような内容にしたいと思います。

  • Vol. 1

www.youtube.com

  • Vol. 2

www.youtube.com

  • Vol. 3

www.youtube.com

チャンネル登録していただけると嬉しいです。

ちなみに今のところはいずれも音声コンテンツです。 Voicyという音声プラットフォームで配信している内容を再編集して動画を作成しています。

voicy.jp

  • このチャンネルを始めた動機

(2020.2 追記)動画も始めました。

最初は音声コンテンツに静止画を貼り付けたものだけで運営してましたが、最近は動画も撮り始めました。

www.youtube.com

www.youtube.com

www.youtube.com

[2019年度版]ドラッグ&ドロップで機械学習のモデルがつくれる「Create ML」の使い方(macOS 10.15 Catalina) #WWDC19

ドラッグ&ドロップで超簡単にオリジナルの機械学習モデルがつくれてしまうCreate MLが大幅パワーアップしました。

新機能が増えたのと、使い方が若干変わった(より簡単になった)部分があるので、最新版として本記事をお送りします。

なお、NDAに配慮してスクリーンショットはAppleの公開資料および現行バージョンのもので代用することにします。

developer.apple.com

developer.apple.com

Create MLの起動方法

これまではCreate MLはまだ独立したアプリとして提供されておらず、Playgroundにコードを書いて実行してアプリケーションのUIにアクセスしていました。

しかしmacOS 10.15 Catalina / Xcode 11で提供される最新バージョンでは、独立したアプリ(Create ML.app)として提供されるようになりました。

Xcode 11のメニューから、

[Xcode] > [Open Developer Tool] > [Create ML]

を選択することで起動します。

使用方法:画像分類器(Image Classifier)

プロジェクトの作成

[File] > [New Project] を選択するとテンプレート選択画面が立ち上がるので、"Image Classifier"を選択します。

f:id:shu223:20190608104742j:plain
テンプレート選択画面。これはWWDCセッションスライド内にあったスクショだが、実際に試すとテンプレートはImage ClassifierとSound Classifierの2つしかなかった(2019.6.7現在)

データセットを用意する

どういうデータを用意するかですが、チュートリアルによると、

  • ラベルごとに最低でも10枚の画像
  • ラベルごとに枚数のバランスをとること(チーターは10枚、ゾウは1000枚、みたいなことをしない)

Use at least 10 images per label for the training set, but more is always better. Also, balance the number of images for each label. For example, don’t use 10 images for Cheetah and 1000 images for Elephant.

  • JPEGやPNG等、画像フォーマットはなんでもいい(UTIがpublic.imageに適合していれば)
  • サイズは揃ってなくてもOK
  • サイズもなんでもいいが、最低でも299x299ピクセルはあった方が良い

The images can be in any format whose uniform type identifer conforms to public.image. This includes common formats like JPEG and PNG. The images don’t have to be the same size as each other, nor do they have to be any particular size, although it’s best to use images that are at least 299x299 pixels.

あとは実際に推論を行うのと同じ状況で学習データも収集した方がいいとか、いろんな角度、ライティングの状況のデータがあった方がいい、ということが書かれています。

If possible, train with images collected in a way that’s similar to how images will be collected for prediction.

Provide images with variety. For example, use images that show animals from many different angles and in different lighting conditions. A classifier trained on nearly identical images for a given label tends to have poorer performance than one trained on a more diverse image set.

ラベルをフォルダ名にし、その配下にトレーニングデータ、テストデータを配置します。

f:id:shu223:20180606071547p:plain

学習&モデルの評価

データフォルダをドラッグ&ドロップします。

f:id:shu223:20190608110725p:plain

テスト(モデルの評価)もドラッグ&ドロップ。

f:id:shu223:20190608110811p:plain

オプショナルで、最大イテレーション回数を指定したり、トレーニングデータにノイズやブラーを付加したり、回転を加えたりといったパラメータを指定することもできます。

f:id:shu223:20190608110855p:plain

Playボタンをクリックすると、学習が開始されます。

f:id:shu223:20190608111115p:plain

学習が完了すると、スコアが表示されます。

f:id:shu223:20190608111212p:plain

f:id:shu223:20190608111423p:plain

モデルを保存する

学習したモデルを .mlmodel ファイルとして保存します。

f:id:shu223:20190608111515p:plain

アプリに組み込む

作成した .mlmodel ファイルをiOSアプリに組み込んで使用します。

実装方法はこちらの記事を参考にしてください。

qiita.com

また画像分類の .mlmodel ファイルをドラッグ&ドロップで試せるアプリをGitHubで公開しているので、こちらもぜひ活用してください。

github.com

使用方法:音声分類器(Sound Classifier)

(続く)

関連(SoundAnalysisについてちょっと書いてます):

qiita.com

API Diffsから見るiOS 13の新機能 - その他諸々 #WWDC19

Vision編CoreML公式配布モデル編Core Image編と、巨大な新API群の端っこの方から記事を書き始めたわけですが、その後どのフレームワークについて書こうとしても調査内容が膨大になってしまってうまくまとまらず、もう眠くなってしまったのでざっくり箇条書きで書いておいて明日以降にまたじっくり調査することにします。

f:id:shu223:20190603103013j:plain

SoundAnalysis

developer.apple.com

Analyze streamed and file-based audio to classify it as a particular type.

機械学習ベースで音を分類したりするらしい。何の音を分類してくれるのかAPIリファレンスからはわからなかったのだけど、次のドキュメントで、

The SoundAnalysis framework operates on a model that you’ve trained using a Create ML MLSoundClassifier

と書いてあって、Create MLでつくったCore MLモデルを使って音を判別するようだ。

ってことで、レイヤーとしてはVisionの音声処理版(Visionは画像処理版)と解釈しとくとよさそう。

セマンティック・セグメンテーション / AVSemanticSegmentationMatte

前からしてPortrait Matteの汎用版。Portrait Matteは人間の全身専用マスクだが、もうちょっと汎用的に領域分割するマスクが取れるようになると。

関連メソッドは前回記事にも書いた:

CoreML公式配布モデルの「DeeplabV3」がMatte抽出にあたって内部で使われているのか、別の仕組みなのかは気になる。

AVSemanticSegmentationMatte.MatteTypeという構造体があり、今のところ次のような種類があるようだ。

static let hair: AVSemanticSegmentationMatte.MatteType

A matting image that segments the hair from all people in the visible field of view of an image.

static let skin: AVSemanticSegmentationMatte.MatteType

A matting image that segments the skin from all people in the visible field of view of an image.

static let teeth: AVSemanticSegmentationMatte.MatteType

A matting image that segments the teeth from all people in the visible field of view of an image.

このへんの髪・肌・歯のセグメンテーションについては前回記事にも書いた。

AVCapturePhotoOutputに関連APIがいくつか追加されている。

developer.apple.com

var availableSemanticSegmentationMatteTypes: [AVSemanticSegmentationMatte.MatteType]

An array of semantic segmentation matte types that may be captured and delivered along with the primary photo.

var enabledSemanticSegmentationMatteTypes: [AVSemanticSegmentationMatte.MatteType]

The semantic segmentation matte types that the photo render pipeline delivers.

AVCapturePhotoにも。

func semanticSegmentationMatte(for: AVSemanticSegmentationMatte.MatteType) -> AVSemanticSegmentationMatte?

Retrieves the semantic segmentation matte associated with this photo.

AVCaptureMultiCamSession

developer.apple.com

A subclass of AVCaptureSession that supports simultaneous capture from multiple inputs of the same media type.

"AVMultiCamPiP: Capturing from Multiple Cameras"というサンプルがあるので、あとで実行してみる。

Core Haptics

developer.apple.com

Compose and play haptic patterns to customize your iOS app's haptic feedback.

サンプルもある。

このドキュメントも興味深い。"Apple Haptic and Audio Pattern (AHAP)"なるファイルフォーマットがあるらしい。

Audio Effects

そんなに新機能を期待してなかったAudioToolboxのリファレンスを見ていたら、iOS 13+なサンプルが2つもあった。

どちらも"Audio Effects"関連。どのへんがiOS 13なのかまだちゃんと読んでないが、あとで見てみる。

AVSpeechSynthesisVoiceGender

以前からある音声合成機能の、合成音声に男女の区別がついた。

case female
case male
case unspecified

これに伴い、AVSpeechSynthesisVoiceにはgenderプロパティが追加された。

var gender: AVSpeechSynthesisVoiceGender { get }

AVSpeechSynthesizer

なんかちょこちょこと新APIがある。

var mixToTelephonyUplink: Bool
var synthesizerAudioSession: AVAudioSession
func write(AVSpeechUtterance, toBufferCallback: AVSpeechSynthesizer.BufferCallback)

MKPointOfInterestCategory

MKMapViewに次のようなプロパティが追加されていて、

var pointOfInterestFilter: MKPointOfInterestFilter?

地図上の"Point of Interest"をフィルタできる。めちゃくちゃ多くの種類が定義されているので、ここでは触りだけ。

static let airport: MKPointOfInterestCategory

The point of interest category for airports.

static let amusementPark: MKPointOfInterestCategory

The point of interest category for amusement parks.

MKMultiPolygon

MapKitの新クラス。WWDCキーノートを聞きながら

こんな妄想をしてたのもあって、「ポリゴン」という字面からSceneKitと連携するなにかかと一瞬期待したが、よく考えたらMKPolygonというクラスは昔からあって、3Dメッシュ表現手法としてのポリゴンではなくて普通に本来の意味での「多角形」だった。(で、どういうものなのかはまだわかってない)

Create ML

いずれ別記事で書きたいので省略するが、つくれるモデルの種類が増えている。

Create MLって何だっけ?という方はこちらをどうぞ:

shu223.hatenablog.com

VisionKit

Visionとはまた別の新フレームワーク。ドキュメントスキャナ的なものをつくる機能を提供してくれている?

developer.apple.com

VisionKit is a small framework that lets your app use the system's document scanner. Present the document camera as a view controller, which covers the entire screen like the camera function in Notes. Implement the VNDocumentCameraViewControllerDelegate in your own view controller to receive callbacks from the document camera, such as completed scans.

watchOSのIndependent App

これめっちゃいいじゃないですか。今まで2つのApp Extensionで構成されてたのがどうなるのか気になる。プロジェクト生成してみる。

On-device speech recognition

オンデバイスで音声認識。SFSpeechRecognitionRequestに、以下のプロパティが追加されている。

var requiresOnDeviceRecognition: Bool { get set }

その他もちろん気になるフレームワーク群

(SwiftUIとかCombineとかはもちろんキャッチアップするとして)

  • ARKit 3
  • RealityKit
  • Reality
  • Core ML 3
  • Metal
  • MetalKit
  • Metal Performance Shaders
  • Natural Language

etc...

API Diffsから見るiOS 13の新機能 - Core Image #WWDC19

iOS 13の新API発掘シリーズその3です。今回はCore Image。

髪・肌・歯のマスク

iOS 12の"Portrait Matte"は全身セグメンテーション用のマスクだったわけですが、それの「髪・肌・歯」版が取れるようになったようです。

developer.apple.com

static let auxiliarySemanticSegmentationHairMatte: CIImageOption
static let auxiliarySemanticSegmentationSkinMatte: CIImageOption
static let auxiliarySemanticSegmentationTeethMatte: CIImageOption

関連: "Portrait Matte"とは?

shu223.hatenablog.com

デプスブラー

CIContextにデプスブラーフィルタを生成するメソッドが追加。disparityImage(視差画像)、portraitEffectsMatte(全身セグメンテーション用マスク画像)、hairSemanticSegmentation(髪のセグメンテーション画像)を渡せて、出力としてCIFilterオブジェクトが返ってきます。

developer.apple.com

func depthBlurEffectFilter(for image: CIImage, 
            disparityImage: CIImage, 
      portraitEffectsMatte: CIImage?, 
  hairSemanticSegmentation: CIImage?, 
               orientation: CGImagePropertyOrientation, 
                   options: [AnyHashable : Any]? = nil) -> CIFilter?

allowLowPower

また、CIContextOptionに以下の型プロパティが追加されていました。

static let allowLowPower: CIContextOption

ドキュメントには解説がありませんが、ヘッダになにか書いてあるかも知れません。パフォーマンスかなにかを犠牲にして消費電力を抑えるオプションでしょうか?

CIFilterの各フィルタの初期化メソッド

今までは次のように文字列でフィルタ名を指定して初期化しないといけなかったのですが、

let filter = CIFilter(name: "CISepiaTone")!

iOS 13ではドーンと(たぶん)全フィルタの初期化メソッドが追加されました。

一覧は長いので本記事の末尾に載せますが、たとえば上に示したsepia toneフィルタは次のメソッドで初期化できます。

class func sepiaTone() -> CIFilter & CISepiaTone

CIImageのAVSemanticSegmentationMatteからの初期化メソッド

AVSemanticSegmentationMatteはまだ紹介してませんが、名前からしてPortraitMatteの汎用版(Portrait Matteは人間の全身専用マスクだが、もうちょっと汎用的に領域分割するマスク)で、そこからCIImageを生成するメソッドが追加されています。

init?(semanticSegmentationMatte: AVSemanticSegmentationMatte)
init?(semanticSegmentationMatte: AVSemanticSegmentationMatte, options: [CIImageOption : Any]?)

パパッと既存の(≠オリジナルの)画像処理を適用するにはやっぱりCore Imageが簡単なので、これは必須ですね。

CGImageSourceを渡すイニシャライザも追加されています(今までなかったんだっけ。。?)

init(cgImageSource: CGImageSource, index: Int, options: [CIImageOption : Any]?)

AVSemanticSegmentationMatteオブジェクトにはプロパティからアクセスできる(持っていれば)ようです。

var semanticSegmentationMatte: AVSemanticSegmentationMatte?

一色のCIImageを生成する?

ドキュメントには解説がなかったのですが、CIImageに以下のような型プロパティが追加されています。一色塗りのCIImageオブジェクトを生成するのでしょうか?

class var black: CIImage
class var blue: CIImage
class var clear: CIImage
class var cyan: CIImage
class var gray: CIImage
class var green: CIImage
class var magenta: CIImage
class var red: CIImage
class var white: CIImage
class var yellow: CIImage

CIFilterに追加された初期化メソッド一覧

上で解説した、CIFilterを生成するメソッド一覧です。しれっと新たに追加されたフィルタもあるかもしれません。

class func accordionFoldTransition() -> CIFilter & CIAccordionFoldTransition
class func additionCompositing() -> CIFilter & CICompositeOperation
class func affineClamp() -> CIFilter & CIAffineClamp
class func affineTile() -> CIFilter & CIAffineTile
class func attributedTextImageGenerator() -> CIFilter & CIAttributedTextImageGenerator
class func aztecCodeGenerator() -> CIFilter & CIAztecCodeGenerator
class func barcodeGenerator() -> CIFilter & CIBarcodeGenerator
class func barsSwipeTransition() -> CIFilter & CIBarsSwipeTransition
class func bicubicScaleTransform() -> CIFilter & CIBicubicScaleTransform
class func blendWithAlphaMask() -> CIFilter & CIBlendWithMask
class func blendWithBlueMask() -> CIFilter & CIBlendWithMask
class func blendWithMask() -> CIFilter & CIBlendWithMask
class func blendWithRedMask() -> CIFilter & CIBlendWithMask
class func bloom() -> CIFilter & CIBloom
class func bokehBlur() -> CIFilter & CIBokehBlur
class func boxBlur() -> CIFilter & CIBoxBlur
class func checkerboardGenerator() -> CIFilter & CICheckerboardGenerator
class func circularScreen() -> CIFilter & CICircularScreen
class func cmykHalftone() -> CIFilter & CICMYKHalftone
class func code128BarcodeGenerator() -> CIFilter & CICode128BarcodeGenerator
class func colorBlendMode() -> CIFilter & CICompositeOperation
class func colorBurnBlendMode() -> CIFilter & CICompositeOperation
class func colorClamp() -> CIFilter & CIColorClamp
class func colorControls() -> CIFilter & CIColorControls
class func colorCrossPolynomial() -> CIFilter & CIColorCrossPolynomial
class func colorCube() -> CIFilter & CIColorCube
class func colorCubeWithColorSpace() -> CIFilter & CIColorCubeWithColorSpace
class func colorCubesMixedWithMask() -> CIFilter & CIColorCubesMixedWithMask
class func colorCurves() -> CIFilter & CIColorCurves
class func colorDodgeBlendMode() -> CIFilter & CICompositeOperation
class func colorInvert() -> CIFilter & CIColorInvert
class func colorMap() -> CIFilter & CIColorMap
class func colorMatrix() -> CIFilter & CIColorMatrix
class func colorMonochrome() -> CIFilter & CIColorMonochrome
class func colorPolynomial() -> CIFilter & CIColorPolynomial
class func colorPosterize() -> CIFilter & CIColorPosterize
class func comicEffect() -> CIFilter & CIComicEffect
class func convolution3X3() -> CIFilter & CIConvolution
class func convolution5X5() -> CIFilter & CIConvolution
class func convolution7X7() -> CIFilter & CIConvolution
class func convolution9Horizontal() -> CIFilter & CIConvolution
class func convolution9Vertical() -> CIFilter & CIConvolution
class func copyMachineTransition() -> CIFilter & CICopyMachineTransition
class func coreMLModel() -> CIFilter & CICoreMLModel
class func crystallize() -> CIFilter & CICrystallize
class func darkenBlendMode() -> CIFilter & CICompositeOperation
class func depthOfField() -> CIFilter & CIDepthOfField
class func depthToDisparity() -> CIFilter & CIDepthToDisparity
class func differenceBlendMode() -> CIFilter & CICompositeOperation
class func discBlur() -> CIFilter & CIDiscBlur
class func disintegrateWithMaskTransition() -> CIFilter & CIDisintegrateWithMaskTransition
class func disparityToDepth() -> CIFilter & CIDisparityToDepth
class func dissolveTransition() -> CIFilter & CIDissolveTransition
class func dither() -> CIFilter & CIDither
class func divideBlendMode() -> CIFilter & CICompositeOperation
class func documentEnhancer() -> CIFilter & CIDocumentEnhancer
class func dotScreen() -> CIFilter & CIDotScreen
class func edgePreserveUpsample() -> CIFilter & CIEdgePreserveUpsample
class func edgeWork() -> CIFilter & CIEdgeWork
class func edges() -> CIFilter & CIEdges
class func eightfoldReflectedTile() -> CIFilter & CIEightfoldReflectedTile
class func exclusionBlendMode() -> CIFilter & CICompositeOperation
class func exposureAdjust() -> CIFilter & CIExposureAdjust
class func falseColor() -> CIFilter & CIFalseColor
class func flashTransition() -> CIFilter & CIFlashTransition
class func fourfoldReflectedTile() -> CIFilter & CIFourfoldReflectedTile
class func fourfoldRotatedTile() -> CIFilter & CIFourfoldRotatedTile
class func fourfoldTranslatedTile() -> CIFilter & CIFourfoldTranslatedTile
class func gammaAdjust() -> CIFilter & CIGammaAdjust
class func gaussianBlur() -> CIFilter & CIGaussianBlur
class func gaussianGradient() -> CIFilter & CIGaussianGradient
class func glideReflectedTile() -> CIFilter & CIGlideReflectedTile
class func gloom() -> CIFilter & CIGloom
class func hardLightBlendMode() -> CIFilter & CICompositeOperation
class func hatchedScreen() -> CIFilter & CIHatchedScreen
class func heightFieldFromMask() -> CIFilter & CIHeightFieldFromMask
class func hexagonalPixellate() -> CIFilter & CIHexagonalPixellate
class func highlightShadowAdjust() -> CIFilter & CIHighlightShadowAdjust
class func hueAdjust() -> CIFilter & CIHueAdjust
class func hueBlendMode() -> CIFilter & CICompositeOperation
class func hueSaturationValueGradient() -> CIFilter & CIHueSaturationValueGradient
class func kaleidoscope() -> CIFilter & CIKaleidoscope
class func labDeltaE() -> CIFilter & CILabDeltaE
class func lanczosScaleTransform() -> CIFilter & CILanczosScaleTransform
class func lenticularHaloGenerator() -> CIFilter & CILenticularHaloGenerator
class func lightenBlendMode() -> CIFilter & CICompositeOperation
class func lineOverlay() -> CIFilter & CILineOverlay
class func lineScreen() -> CIFilter & CILineScreen
class func linearBurnBlendMode() -> CIFilter & CICompositeOperation
class func linearDodgeBlendMode() -> CIFilter & CICompositeOperation
class func linearGradient() -> CIFilter & CILinearGradient
class func linearToSRGBToneCurve() -> CIFilter & CILinearToSRGBToneCurve
class func luminosityBlendMode() -> CIFilter & CICompositeOperation
class func maskToAlpha() -> CIFilter & CIMaskToAlpha
class func maskedVariableBlur() -> CIFilter & CIMaskedVariableBlur
class func maximumComponent() -> CIFilter & CIMaximumComponent
class func maximumCompositing() -> CIFilter & CICompositeOperation
class func median() -> CIFilter & CIMedian
class func meshGenerator() -> CIFilter & CIMeshGenerator
class func minimumComponent() -> CIFilter & CIMinimumComponent
class func minimumCompositing() -> CIFilter & CICompositeOperation
class func mix() -> CIFilter & CIMix
class func modTransition() -> CIFilter & CIModTransition
class func morphologyGradient() -> CIFilter & CIMorphologyGradient
class func morphologyMaximum() -> CIFilter & CIMorphologyMaximum
class func morphologyMinimum() -> CIFilter & CIMorphologyMinimum
class func morphologyRectangleMaximum() -> CIFilter & CIMorphologyRectangleMaximum
class func morphologyRectangleMinimum() -> CIFilter & CIMorphologyRectangleMinimum
class func motionBlur() -> CIFilter & CIMotionBlur
class func multiplyBlendMode() -> CIFilter & CICompositeOperation
class func multiplyCompositing() -> CIFilter & CICompositeOperation
class func noiseReduction() -> CIFilter & CINoiseReduction
class func opTile() -> CIFilter & CIOpTile
class func overlayBlendMode() -> CIFilter & CICompositeOperation
class func pageCurlTransition() -> CIFilter & CIPageCurlTransition
class func pageCurlWithShadowTransition() -> CIFilter & CIPageCurlWithShadowTransition
class func paletteCentroid() -> CIFilter & CIPaletteCentroid
class func palettize() -> CIFilter & CIPalettize
class func parallelogramTile() -> CIFilter & CIParallelogramTile
class func pdf417BarcodeGenerator() -> CIFilter & CIPDF417BarcodeGenerator
class func perspectiveCorrection() -> CIFilter & CIPerspectiveCorrection
class func perspectiveTile() -> CIFilter & CIPerspectiveTile
class func perspectiveTransform() -> CIFilter & CIPerspectiveTransform
class func perspectiveTransformWithExtent() -> CIFilter & CIPerspectiveTransformWithExtent
class func photoEffectChrome() -> CIFilter & CIPhotoEffect
class func photoEffectFade() -> CIFilter & CIPhotoEffect
class func photoEffectInstant() -> CIFilter & CIPhotoEffect
class func photoEffectMono() -> CIFilter & CIPhotoEffect
class func photoEffectNoir() -> CIFilter & CIPhotoEffect
class func photoEffectProcess() -> CIFilter & CIPhotoEffect
class func photoEffectTonal() -> CIFilter & CIPhotoEffect
class func photoEffectTransfer() -> CIFilter & CIPhotoEffect
class func pinLightBlendMode() -> CIFilter & CICompositeOperation
class func pixellate() -> CIFilter & CIPixellate
class func pointillize() -> CIFilter & CIPointillize
class func qrCodeGenerator() -> CIFilter & CIQRCodeGenerator
class func radialGradient() -> CIFilter & CIRadialGradient
class func randomGenerator() -> CIFilter & CIRandomGenerator
class func rippleTransition() -> CIFilter & CIRippleTransition
class func sRGBToneCurveToLinear() -> CIFilter & CISRGBToneCurveToLinear
class func saliencyMap() -> CIFilter & CISaliencyMap
class func saturationBlendMode() -> CIFilter & CICompositeOperation
class func screenBlendMode() -> CIFilter & CICompositeOperation
class func sepiaTone() -> CIFilter & CISepiaTone
class func shadedMaterial() -> CIFilter & CIShadedMaterial
class func sharpenLuminance() -> CIFilter & CISharpenLuminance
class func sixfoldReflectedTile() -> CIFilter & CISixfoldReflectedTile
class func sixfoldRotatedTile() -> CIFilter & CISixfoldRotatedTile
class func smoothLinearGradient() -> CIFilter & CISmoothLinearGradient
class func softLightBlendMode() -> CIFilter & CICompositeOperation
class func sourceAtopCompositing() -> CIFilter & CICompositeOperation
class func sourceInCompositing() -> CIFilter & CICompositeOperation
class func sourceOutCompositing() -> CIFilter & CICompositeOperation
class func sourceOverCompositing() -> CIFilter & CICompositeOperation
class func spotColor() -> CIFilter & CISpotColor
class func spotLight() -> CIFilter & CISpotLight
class func starShineGenerator() -> CIFilter & CIStarShineGenerator
class func straighten() -> CIFilter & CIStraighten
class func stripesGenerator() -> CIFilter & CIStripesGenerator
class func subtractBlendMode() -> CIFilter & CICompositeOperation
class func sunbeamsGenerator() -> CIFilter & CISunbeamsGenerator
class func supportedRawCameraModels() -> [String]!
class func swipeTransition() -> CIFilter & CISwipeTransition
class func temperatureAndTint() -> CIFilter & CITemperatureAndTint
class func textImageGenerator() -> CIFilter & CITextImageGenerator
class func thermal() -> CIFilter & CIThermal
class func toneCurve() -> CIFilter & CIToneCurve
class func triangleKaleidoscope() -> CIFilter & CITriangleKaleidoscope
class func triangleTile() -> CIFilter & CITriangleTile
class func twelvefoldReflectedTile() -> CIFilter & CITwelvefoldReflectedTile
class func unsharpMask() -> CIFilter & CIUnsharpMask
class func vibrance() -> CIFilter & CIVibrance
class func vignette() -> CIFilter & CIVignette
class func vignetteEffect() -> CIFilter & CIVignetteEffect
class func whitePointAdjust() -> CIFilter & CIWhitePointAdjust
class func xRay() -> CIFilter & CIXRay
class func zoomBlur() -> CIFilter & CIZoomBlur