写真に写っている人・動物をヒエログリフにする iOS アプリを作ってみた
機械学習のフレームワークを使ったアプリを作ってみたくなり、試しに作ってみた。ついでに最近、エジプトのヒエログリフが面白いなあ、と思っていたのでそれをアプリのテーマにした。
Apple の review に提出する際に、かなり機能が単純なアプリだからリジェクトされるかと思ったが、大丈夫だった。
(審査にデモビデオは添付した)
アプリを使って変換すると、こんな感じで写真 → エジプトのヒエログリフの壁画風の画像になる。
アプリの動作はこんな感じ。
精度はそんなに良くなく、たとえば写真全体に人や動物が大きく写っていると、残念ながらうまくいかない。。
ざっくりとした処理の流れは↓の感じ。
- あらかじめ、使用するヒエログリフの画像を作成して用意しておく
- 写真から人や動物を認識する
- 認識した領域にもっとも特徴が近いヒエログリフを探し、該当するヒエログリフで写真を置き換える
- Vision(CoreML) VNFeaturePrintObservation で画像間の特徴の近さが分かる
やってみて悩ましかった点は
多数の画像(ヒエログリフ)から VNFeaturePrintObservation
を作ると時間がかかりすぎる。アプリの利用上の障害がある、という問題があった。
解決策としては
- 実行時に特徴検出を逐次作成するのではなく
- あらかじめ、各画像の
VNFeaturePrintObservation
を作成しておいてそれを CoreData で DB に保存しておく- そしてそれをアプリにバンドルしておく
- アプリの実行時には作っておいた DB から
VNFeaturePrintObservation
を fetch する
という形にした。
VNFeaturePrintObservation
の継承元の VNObservation
は NSSecureCoding
を採用しているので、CoreData の Attribute の型を Transformable
にして、下のようなカスタムの Transformer クラスを使用することで CoreData に保存できる。
@objc(VNFeaturePrintObservationTransformer) class VNFeaturePrintObservationTransformer: NSSecureUnarchiveFromDataTransformer { static let name = NSValueTransformerName(rawValue: String(describing: VNFeaturePrintObservationTransformer.self)) override class var allowedTopLevelClasses: [AnyClass] { return super.allowedTopLevelClasses + [VNFeaturePrintObservation.self] } public static func register() { let transformer = VNFeaturePrintObservationTransformer() ValueTransformer.setValueTransformer(transformer, forName: name) } }
Google ML Kit や Core ML はほとんど触ったことがなく難しい印象だったが、やってみると楽しかった。