読者です 読者をやめる 読者になる 読者になる

Brace, Paren, Semicolon.

受験勉強中

乃木坂って、どこ?Google Cloud Vision APIの画像認識で乃木坂の位置を探してみた #乃木坂46

こんにちは。突然ですが皆さんは乃木坂46をご存じでしょうか。

乃木坂46秋元康プロデュースのアイドルグループ。AKB48とは公式ライバルにあたるらしいです。

YouTubeにて公式公開されているPVがあったりします。知らない方はとりあえず見てみましょう。

とてもフレッシュですね。

ところで、乃木坂46ファンが最初にぶつかる壁が「乃木坂って、どこ?」という疑問だそうです(自分調べ)

AKB48はアキバ、SKE48は名古屋、NGT48は新潟、乃木坂は...どこ?

「乃木坂の詩」という曲にもこんなフレーズがあります。

乃木坂がどこにあるかなんて 僕らは何も知らずに来たんだ

自分らでも知らんのかい!

あまりにもよくある疑問なので、「乃木坂って、どこ?」というテレビ番組がやってるくらいです。ぜひ見てみましょう。

www.nogizaka46.com

というわけで、乃木坂が一体どこにあるのか調べてみることにしました。

どうやって調べるか

それにしても、乃木坂が一体どこにあるのかなんてどうやって調べたら良いのでしょうか。

Googleで「乃木坂 場所」で検索してみる?いやいや、そんなに簡単に見つかるわけがない...これは却下。

まわりの人に聞いてみる?いやいや、ファンでも分からないのに一般人が知ってるわけがない...これも却下。

他にもいろいろな手段で乃木坂がどこにあるのか調べられないか考えましたが、八方塞がりになってしまいました。

疲れ果ててしまったので「ハルジオンが咲く頃に」のPVを見て頭を休めることにします...

はあ。まいまい(深川麻衣)かわいい。

ちなみに、残念ながらまいまいは6月には卒業してしまうのです。その前には乃木坂がどこにあるのか見つけておきたい...

それにしても手元に残されたのはこのPVだけ...

どうやって乃木坂を見つけたらいいんだ...

PVだけ...

PVだけ...?

はっ!

人工知能でPVが撮影された位置を推定すれば、乃木坂の場所が分かるんじゃないか?!

こんなニュースもあるくらいだし。

Google、写真から撮影された場所を特定するAI「PlaNet」を開発 - エキサイトニュース

この方法なら乃木坂の位置が分かりそう!

テンション上がってきました。早速実装してみましょう。

PVからフレームを抽出する

f:id:oimou:20160409184759j:plain

まず、公式公開されているPVのURLを元に、mp4ファイルをダウンロードしてきます。

# download.py
from pytube import YouTube as YT

urls = [
  ...
]

for url in urls:
    yt = YT(url)

    try:
        video = yt.get("mp4", "720p")

    except:
        video = yt.get("mp4")

    video.download("./video")

    print("Download finished: " + url)

ダウンロードが完了したら、FFmpegを利用してフレームを抽出します。

それほど頻繁に景色が移り変わるシーンはないので、フレームレートは0.2Hzに設定し、5秒毎に1枚のフレームを抽出するようにしました。

# extract-frames.sh

for f in video/*.mp4; do
        DNAME=$(basename ${f%.*} | tr '.' '_')

        mkdir -p frame/${DNAME}
        ffmpeg -i ${f} -r 0.2 frame/${DNAME}/thumbnail-%04d.jpg
done

これで約1900枚のフレームを抽出することができました。

さて、この画像を元に位置情報を推定していきます。

画像認識を行う

抽出したフレームにはメタデータが付いていないので、フレームから位置情報を推定するには画像認識が必要です。

どうやって画像認識をするか。

Google Street ViewやTwitterから位置情報付き画像を集めてくればディープラーニングで位置検出器を作れるなーと妄想しましたが、ちょっと大変そう。

そういえばGoogle Cloud Vision APIが先日公開ベータとなり、一般ユーザが利用できるようになりましたね。

このCloud Vision APILANDMARK_DETECTION と呼ばれるランドマーク検出機能を備えており、画像から位置情報を推定できるようになっています。

ちょうどいい機会なので、Cloud Vision APIを使って実装することにしました。

jp.techcrunch.com

Cloud Vision APIとのやりとりは、下記ブログ記事を参考にNode.jsで書いてみました。

Node.jsとGoogle Cloud Vision API使って色々な画像認識試してみた。 | Indie Engineer Blog

使い捨ての実装なのでソースコードは恥ずかしいですが、1リクエストにつき16枚のフレームを一括で送るようになっています。

# vision.js

"use strict";

const fs = require("fs");
const vision = require("node-cloud-vision-api");

vision.init({
        auth: "API_KEY"
})

let dirs = fs.readdirSync("./frame")
let count = 0;
let nEmit = 0;
let paths = [];

for (let dir of dirs) {
        if (!fs.statSync("./frame/" + dir).isDirectory()) continue;

        let files = fs.readdirSync("./frame/" + dir);

        for (let file of files) {
                let path = "./frame/" + dir + "/" + file;

                paths.push(path);

                count++;

                if (count >= 16) {
                        emitPaths();

                        nEmit++;

                        count = 0;
                }
        }
}

function emitPaths() {
        let _paths = paths.concat();
        let reqs = _paths.map((path) => {
                let req = new vision.Request({
                        image: new vision.Image({
                                path: path
                        }),
                        features: [
                                new vision.Feature("LANDMARK_DETECTION", 1)
                        ]
                });

                return req;
        });

        setTimeout(() => {
                vision.annotate(reqs).then((res) => {
                        let results = res.responses;

                        _paths.forEach((path, i) => {
                                console.log(JSON.stringify({
                                        path: path,
                                        result: results[i]
                                }) + ",");
                        });
                }, (err) => {
                        console.error("Error: " + err);
                });
        }, nEmit * 2000);

        paths = [];
}

Cloud Vision APIのリクエスト制限については、1-1000 units/monthが無料枠の範囲内に入る模様。

Cloud Vision API Pricing - Google Cloud Vision API — Google Cloud Platform

unitというのがどの単位を指すのか気になりますが、ページにはこう書いてあるので、リクエスト単位ではないような気がしますね。

Charges are incurred for each feature applied to an image. For example, if you apply Face Detection and Label Detection to the same image, each feature would be billed individually.

とすると今回は約1900枚の画像認識タスクをリクエストしたので、$2.50/monthといったところでしょうか。この価格でGoogleが学習させたモデルを使えるなら安いかもしれませんね。

画像認識結果

1900枚のフレームを全てCloud Vision APIに投げるには5分ほどかかりました。そして画像認識の結果がこちら。

レスポンスJSONだけ眺めていても気分が乗らないので、簡単なHTMLに整形してあります。

f:id:oimou:20160409195554p:plain

位置情報なしだらけ

f:id:oimou:20160409195601p:plain

これも位置情報なし

f:id:oimou:20160409195608p:plain

まいまいがかわいい

f:id:oimou:20160409195614p:plain

街のフレームもだめか

f:id:oimou:20160409195622p:plain

あ、見つけた!

f:id:oimou:20160409195629p:plain

こっちにも!

ついに乃木坂の位置が判明!!

最終的に見つけたのはこの2箇所でした。

緯度: 32.732667 軽度: 129.869892 Googleマップを開く

緯度: 32.74683050793882 軽度: 129.87938404083252 Googleマップを開く

Googleマップを開いてみると...

f:id:oimou:20160409201022p:plain

こっ、ここは、長崎県長崎市じゃないか!

乃木坂は長崎にあったんだ!

 ナ ナンダッテー!!
 Ω ΩΩ

まとめ

Cloud Vision APIによって、乃木坂が長崎県にあることがわかりました*1

これでまいまいの卒業を安心して迎えることができますね。本当にありがとうございました。

*1:本当は東京都港区にあります