開発中のアプリ「Afterglow Trip」の検証で、面白い失敗をしたので記録しておく。
( Afterglow TripはDaylight Trip との姉妹アプリとなります)

何を作っているか
写真のEXIF(撮影日時とGPS)だけから旅行を自動検出して、一生分の足跡を1枚の地図に育てていくアプリを作っている。旅行中にGPSを記録し続ける必要はなく、帰宅後に写真を読み込むだけでいい「後追い型」。サーバーもAPIキーも使わず、端末内で完結させる設計だ。
旅行を検出するには、まず「拠点」——つまり自宅がどこかをアプリが推定する必要がある。拠点が分かれば、「拠点から離れて、拠点に帰ってくるまで」を1つの旅行として切り出せる。
素直な設計:写真が一番多い場所が自宅
最初の設計はシンプルだった。
全写真の座標を0.1度のグリッドに落として投票し、一番票が集まったセルを拠点とする
人生で一番長くいる場所は自宅なのだから、写真も自宅周辺が一番多いはず。理屈は通っている。
テストデータは、先日のケアンズ旅行の写真175枚と、自宅周辺で撮り足した写真50枚ほど。さっそく実行してみた。
🗳️ セル投票ランキング(0.1度グリッド・上位5)
70票 ケアンズ郊外のセル
51票 自宅のセル
39票 ケアンズ市街のセル
...
🏠 拠点推定: ケアンズ郊外 ← !?
拠点=オーストラリアになってしまった。
なぜ負けたのか
旅行中は写真を撮りまくる。観光地では1日で何十枚も撮る。一方、日常で自宅周辺の写真はそんなに撮らない。つまり「枚数」で投票すると、集中撮影された旅行先が、淡々と積み重なる日常に勝ってしまう。
本番では10年分の写真を読み込むので自宅が圧勝するはずだが、「写真は旅行のときしか撮らない」というユーザーなら、同じ逆転が本番でも起きる。これは設計で潰しておくべき穴だった。
解決:拠点とは「繰り返し戻る場所」
投票ランキングをよく見ると、ヒントが隠れていた。
ケアンズの各セルは、7/30〜8/3という連続した1回の滞在に票が集中している。一方、自宅セルは8/13と8/21という離れた日に繰り返し現れている。
そこで投票のルールを変えた。
写真の枚数ではなく「訪問ブロック数」で投票する。撮影日が2日以上空いたら別の訪問として数える。同数なら写真数で決着。
旅行は何百枚撮っても「1回の訪問」。自宅は数枚ずつでも「何度も帰ってくる場所」。結果はこうなった。
🗳️ セル投票ランキング(訪問数→写真数・上位5)
2回訪問 51票 自宅のセル ← 逆転!
2回訪問 2票 仕事場のセル
1回訪問 70票 ケアンズ郊外のセル
1回訪問 39票 ケアンズ市街のセル
...
🏠 拠点推定: 自宅のセル
70票のケアンズは「1回訪問」止まり。51票の自宅が「2回訪問」で堂々の1位になった。
面白いのは2位に「2回訪問・2票」で仕事場が入ったこと。たった2枚でも、離れた日に2回写っていれば旅行先より上位に来る。「拠点=繰り返し戻る場所」という定義が、そのままアルゴリズムになった。
おまけ:この定義は旅行検出とも噛み合う
旅行の切り出しも「拠点から30km超に離れたら開始、30km以内に戻ったら終了」という帰還ベースにした。時間ギャップを使わないので、帰国後しばらく写真を撮らなくても旅行が途切れない。実際、旅行最終日の8/3から次の写真は8/13まで空いていたが、正しく1つの旅行として検出できた。
🧳 検出された旅行: 1件
2026/07/30 - 2026/08/03 最遠 5862km 写真 173枚(GPSなし 39枚)
「旅行=連続した1回の滞在」「拠点=繰り返し戻る場所」。この対比が、投票にも旅行検出にも効いている。
教訓
- 理屈が通っている設計でも、実データは平気で裏切る
- 失敗した出力(投票ランキング)をよく眺めると、次の設計が書いてある
- 定義を言葉にできたとき(拠点とは繰り返し戻る場所)、実装は一気に素直になる
検証フェーズはこれで完了。次は本番プロジェクトの立ち上げに進む。
SINQWELL — 写真から旅を残すアプリ「Afterglow Trip」開発中
