Kristopher Baker iOS · プロダクト開発 · システムとツール
← 制作中へ
active updated today Repository

KiFinder

大勢が写った写真アルバムから一人を探し、写真をアップロードしないMacアプリです。娘の保育園から毎月届くアルバムを整理するために作りました。

SwiftmacOSSwiftUICore MLFace recognitionLocal-firstGPLv3

KiFinderは、大勢が写ったアルバムから一人の写真を探すMacアプリです。娘の保育園から毎月、クラス全員が写った何百枚もの写真が複数のzipファイルで届き、その中から娘を手で探していたので作りました。ほかの家庭の子どもも写っているため、照合はMac上で行い、写真をアップロードしません。

仕組み

まず、複数の参照写真で人物を登録します。KiFinderは顔を検出してArcFaceの埋め込みプロファイルを作り、フォルダ、画像ファイル、届いたままのzipファイルをスキャンします。結果は、確度の高い一致、もう一度確認する写真、その他の三つに分けます。集合写真では検出したすべての顔を表示し、アプリの最初の推測をそのまま使わず、自分が探している人物を選べます。

KiFinderのレビュー画面。確信のある一致と境界付近の結果が分かれ、集合写真では検出した顔に枠が付いています。 境界付近の結果は確認できるよう残しつつ、確信のある一致とは分けています。デモ画像では自分を登録し、ほかの人物には合成した顔を使いました。

類似度のしきい値は、モデルに固定された値ではなく、アプリ側で決めるものです。高くすると横顔やぼけた写真を見落とします。低くすると、ほかの子どもの写真がレビューに増えます。calibrateコマンドは、正解と不正解を付けた例から、既知の正解をすべて拾える範囲で最も高い値を提案しますが、自動では適用しません。本物の写真を取りこぼす可能性は、自分で判断したいからです。

各スキャンでは、スコアと顔の埋め込みをmanifestへ保存します。本物の一致を保存するか、似ているだけの顔を除外すると、KiFinderはその修正を最初の参照画像とは別の追加サンプルへ反映します。その後は画像の読み込みやモデルの再実行をせず、以前のアルバムを再評価できます。

KiFinderの人物登録画面。ローカル処理の説明と参照写真のサムネイルが表示されています。 人物登録ではMac上で参照画像から顔を切り出します。複数の角度を含めるため、5枚から12枚の写真を使います。

検証

レビュー画面では、説明のない最終フォルダだけを出すのではなく、モデルの判断を確認できます。App Sandboxを有効にしたときの重要な不具合も、実際のエンジンを動かして見つけました。Core MLがモデルをコンパイルする場所を/private/tmp以下に固定していましたが、サンドボックスからは書き込めませんでした。エラーをtry?で無視した結果、すべての埋め込みがnilになり、顔が0件のままスキャンが完了していました。一時ディレクトリをアプリのコンテナ内へ移し、保存済みの写真で実際のエンジンを使うテストを行うと、壊れたビルドでは0件だった埋め込みが5件と6件になりました。

KiFinderのライブラリ。保存した写真が人物と月ごとにまとまっています。 保存した写真は、Photosへ書き出す前に人物と月ごとにまとまります。

ソースのみで公開する理由

KiFinderは無料、有料を問わず、アプリとして配布しないことにしました。一番大きな理由は、人々のプライバシーを尊重するためです。KiFinderが扱う写真には、ほかの家庭の子どもが大勢写っています。自分の娘を探すために、自分のMac上で顔照合を行うのと、誰でもどのアルバムにも同じ処理を使える署名済みアプリを渡すのは、同じではありません。

モデルの学習データにも問題があります。使っているArcFaceの重みは、本人の同意なく集めた顔画像から作られ、その後取り下げられたデータセット、MS-Celeb-1Mで学習されています。個人用のツールでは使えますが、このモデルを配布したくはありません。アプリとして公開するなら、同意を得たデータで学習したモデルを探すか、自分で学習する必要があります。アプリに伴うサポートや審査対応も必要です。

その代わり、ソースコードをGPLv3でGitHubに公開しています。誰でも読んだり、自分でビルドしたりでき、派生したコードもオープンなままにする形です。

現在

KiFinderは今も自分で使っているプロジェクトです。次はモデルの準備とサンドボックス権限について、実機で繰り返せるテストを増やします。

アップデート 4

次へ

Sparra 制作ログを見る