写真に写っている人・動物をヒエログリフにする iOS アプリを作ってみた

機械学習フレームワークを使ったアプリを作ってみたくなり、試しに作ってみた。ついでに最近、エジプトのヒエログリフが面白いなあ、と思っていたのでそれをアプリのテーマにした。

Egyptian Hieroglyphs Photo

Egyptian Hieroglyphs Photo

  • Daisuke Tonosaki
  • 写真/ビデオ
  • 無料

Apple の review に提出する際に、かなり機能が単純なアプリだからリジェクトされるかと思ったが、大丈夫だった。
(審査にデモビデオは添付した)

アプリを使って変換すると、こんな感じで写真 → エジプトのヒエログリフの壁画風の画像になる。

f:id:daisuke-t-jp:20210303213230p:plain:w500

f:id:daisuke-t-jp:20210303213422p:plain:h400 f:id:daisuke-t-jp:20210303213440p:plain:h400

アプリの動作はこんな感じ。

www.youtube.com

精度はそんなに良くなく、たとえば写真全体に人や動物が大きく写っていると、残念ながらうまくいかない。。


ざっくりとした処理の流れは↓の感じ。

  1. あらかじめ、使用するヒエログリフの画像を作成して用意しておく
  2. 写真から人や動物を認識する
  3. 認識した領域にもっとも特徴が近いヒエログリフを探し、該当するヒエログリフで写真を置き換える

やってみて悩ましかった点は

多数の画像(ヒエログリフ)から VNFeaturePrintObservation を作ると時間がかかりすぎる。アプリの利用上の障害がある、という問題があった。

解決策としては

  • 実行時に特徴検出を逐次作成するのではなく
  • あらかじめ、各画像の VNFeaturePrintObservation を作成しておいてそれを CoreData で DB に保存しておく
    • そしてそれをアプリにバンドルしておく
  • アプリの実行時には作っておいた DB からVNFeaturePrintObservation を fetch する

という形にした。

VNFeaturePrintObservation の継承元の VNObservationNSSecureCoding を採用しているので、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 はほとんど触ったことがなく難しい印象だったが、やってみると楽しかった。