はじめまして
皆さん、こんにちは。Qitta2回目の投稿、松井 敏と申します(以前は@moririringという名前で活動してました)。現在僕は、読んだマンガを登録するサイト「マンガ読んだ!!」を作っています。マンガ読んだ!!は、「読んだボタン」を押すだけで簡単に読んだマンガを記録できるサービスで、最近β版にしました。
マンガ読んだ!!
以前に本を登録するサービスを使ったことがありますが、自分で1冊ずつ登録していく必要がありました。それはとても面倒で、1000冊読んでいれば、1000回登録が必要でした。マンガ読んだ!!は ボタンを押すだけで登録できます。しかも作者やシリーズでまとめて登録も簡単です!マンガの数は現在、集英社、講談社、小学館などから8万冊以上。毎日増え続けています。
Azure Computer Vision API
さて、Azure Computer Vision API(以下Vision API)というサービスがあります。ある時、このキーワードを知って、サイトを見てみました。すると以下のような説明がありました。
タグ付け、説明、ドメイン固有モデルを使用してコンテンツを特定し、確実にラベル付けします。成人向け/わいせつな描写に対する設定を適用すれば、アダルト コンテンツの自動制限を有効にできます。画像の種類や写真内の配色を特定します。
これだ!と思いました。実はマンガ読んだ!!でやりたいことありました。それは、表紙画像のチェックです。
マンガの表紙チェック
マンガ読んだ!!ではマンガを表紙で表示しています。表紙は、書店で並べられているぐらいなので、基本全年齢OKです。(適切じゃない表紙で回収騒ぎになった作品もありますけどね!)しかし、これ本当に青少年に見せて良いんだろうか?という表紙は結構あります。そこにVision APIです!サイト上で画像のURLを送信すればチェック出来るのでいくつか試してみました。
Vision APIの表紙チェック
例えばラブコメの王道はもちろん、成人向けコンテンツfalseです。
表紙チェックとしての精度、結構悪くなさげです!
プログラムからVision APIで表紙チェック
とはいえ、手作業で一つずつ確認するのは面倒です。面倒なことはもちろんプログラムです。サイトにAPIの使い方が書いてあります。下記のプログラムを実行すればapiResultに結果が返ってきます。
const string uriBase = "https://westcentralus.api.cognitive.microsoft.com/vision/v1.0/analyze";
const string dataUrl = "http://www.s-manga.net/common/thumb/512/4-08-872571-9.jpg";
const string subscriptionKey = "13hc77781f7e4b19b5fcdd72a8df7156";
using (var httpClient = new HttpClient())
{
var content = (await httpClient.GetAsync(dataUrl, HttpCompletionOption.ResponseHeadersRead)).Content;
httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
var apiResult = await (await httpClient.PostAsync(uriBase, content)).Content.ReadAsStringAsync();
}
APIは5000トランザクションまでは無料で使えます。というわけでマンガ読んだで使っている表紙画像にAPIをかけてみました。(※表紙画像を使うことは集英社などに問題ない旨確認済みです)。
isAdultContent と adultScore
実際にAPIを叩くと、以下のようなJSONが返ってきます、
{"adult":{"isAdultContent":false,"adultScore":0.038640901446342468,"isRacyContent":false,"racyScore":0.0293082557618618},"requestId":"ec898276-690d-42d3-a9f0-dfd14132f66b","metadata":{"height":1000,"width":636,"format":"Png"}}
なので以下のクラスを定義して受けます。
public class Adult
{
public bool isAdultContent { get; set; }
public float adultScore { get; set; }
public bool isRacyContent { get; set; }
public float racyScore { get; set; }
}
isAdultContent でアダルト判定できるだけでなくて、adultScore でアダルトスコア(※以下アダルトは大人と記述)も取得出来ます。集まってきた数千件のデータをみていて、思いついちゃいました。スコアは数値です。数値という事はソートが出来ます!そう、表紙機能の大人スコアソートです。実際に大人ソートしてみて色々面白いことが分かりました。
大人ソート
確かに大人ソートの上位を見てみると、いわゆる大人スコアが高いそれっぽい表紙が並びます。ところが、ノイズが結構あります。
例えば、この表紙はトップレベルで高い大人スコアを誇っていますが、それ程でもありません。
また、この表紙も相当な大人スコアです。やっぱり猫は大人ですよね。
特にインパクトが強かったのはこれでしょうか。やっぱり裸の表紙は大人スコア高めですね。
成人向け判定はfalseだけど、大人スコアが高かったのが例えばこれです。確かにすれすれな感じですよね!
まあ、ぶっちゃけ、大人スコアが高いのはイコール肌色率が大きな要因のようです。
Vision API時間制限
Vision APIで躓いたポイントも少し書きます。プログラムで大量のチェックを走らせる時、ローカルでテストしていた時は問題なかったのですが、Azure WebJobsから叩いたら必ず一定数やるとエラーが返ってきました。ログを見ると時間制限があるようで、短期間に連続で呼ぶと駄目なようです。1秒程度間隔を空ければ大体問題ないと思います。数が多いので非同期使いたかったんですけどね。。
Vision APIトランザクションの扱い
もう一つドはまりしました。Vision APIは¥112/1,000トランザクションです。8万件やろうとすると大体1万円ぐらいです。無料枠は当然使い切って、有料枠で使い始めたのですが、トランザクションの扱いを完全に勘違いしていました。URLで1回問い合わせることを1トランザクションかと思ったら1パラメータ1トランザクションでした。2パラメータ指定して取得していたので単純に倍使ってました。これは課金的に本当に痛かった。。
Vision APIのエラー処理
あとは、APIの基本だと思いますが、やっぱりちょくちょくエラーも返ってきます。最初はエラーがあったら止める、安定運用になったらスルーが良いと思います。最初の頃はエラーなら止めていたので、Bad Request、Rate limit is exceeded、InvalidImageFormatなどが来ました。日々更新はadultScoreがなかったらスルーにしています。
#まとめ
そんなこんなでマンガ読んだ!!の8万件を超す表紙データにすべてに大人スコアがつけました。これで一覧での大人ソートは勿論、出版社や作者でも大人ソートできます。手塚治虫のマンガを大人順で並べたり、キン肉マンを大人順で並べたりするのも面白いと思います!ちなみにこの機能は登録ユーザー限定です。是非登録して、大人順でマンガ一覧を見てください!