Google Cloud Vision API を試すまで (有害画像検出)

こんにちは。

クローラで画像や動画を集めている時にアダルトなものが紛れてきたら嫌ですよね。(え？嬉しい？)
少し前に話題になった Google Cloud Vision API には、そのような有害な画像を検出する機能があるみたいです。

ここでは、Google Cloud Vison APIの無料トライアルで有害画像検出を試すまでにやったことを、メモとしてまとめておきます。
Cloud Vison APIの他の機能、例えば画像認識、テキスト検出、 顔検出なども、以下に示すのと同様の手順で利用可能です。

# 試す手順
Google Cloud Vison API は一般的なAPIと同様に以下の手順で利用します。
　
1. 個人情報を登録し、APIキーを取得する
2. リクエストを作成し、APIへポストする
3. レスポンスを受け取り、その内容を確認する

上記の内容を、順番に、簡単にまとめます。

## APIキーの取得
以下のサイトを参考にAPIキーを取得します。

[Cloud Vision APIの使い方まとめ (サンプルコード付き)](https://syncer.jp/cloud-vision-api)

特に注意する点は以下の通り。

* 無料トライアルでも課金登録(クレジットorデビッドカードの登録)が必要。__つまり、カードがないと試せない__。
* 電話番号を入力する際は、頭に国際番号(日本なら"+81")を付ける。  (ここで詰まりました。一般常識が無いのがバレてします。)
ex.) +8109012345678
* 絶対にお金を払いたくない！という人はアラートの設定を忘れずに行う。

## リクエストの作成・送信
今回はpythonで試しました。というより自分がpythonしか使えませんでした。
リクエストの送信にはrequestsモジュールを使うので、入ってない場合はpipでインストールしましょう。

```bash:
$ pip install requests
```

リクエストの作成には、Cloud Vision APIの公式チュートリアルで公開されていた[generatejson.py](https://github.com/GoogleCloudPlatform/cloud-vision/blob/master/python/utils/generatejson.py)を利用するのが便利です。
これは、送りたいリクエストの情報をテキストにまとめて入力すると、その情報をまとめたjsonファイルを出力してくれるもの。
入力ファイルの形式は以下のとおりです。

```text:input_file.txt
# 画像のPath 機能番号:結果の取得件数 
filepath_to_image1.jpg 4:10
filepath_to_image2.png 1:10 6:10
```

半角スペース区切りで、最初に画像のPath、以降に使いたい機能の番号とその結果取得件数をコロン区切りで指定します。(上の例にあるコメントは書かないでください。)
機能番号(2016/05/19 現在のもの)は以下の表に対応します。

| 機能名 | 説明 | 番号 |
|-----------|------------|:------------:|
| FACE_DETECTION | 顔部分の検出 | 1 |
| LANDMARK_DETECTION | ランドマークの検出 | 2 |
| LOGO_DETECTION | ロゴの検出 | 3 |
| LABEL_DETECTION | 物体検出・認識 | 4 |
| TEXT_DETECTION | 画像中のテキスト検出 | 5 |
| SAFE_SEARCH_DETECTION | 有害画像の検出 | 6 |

  
例えば、"4:10"と指定すると、物体認識を行い、推定されたラベルの上位10件が返ってきます。
有害画像検出など、"件数"が必要ない場合もとりあえず:Xと数値をつけて試しました。Xを1にしても10にしても結果は変わらなかったです。

generatejson.pyを使ったjsonファイルの作成は以下のようにします。

```bash:
python generatejson.py -i <inputfile> -o <outputfile>
# ex.) python generatejson.py -i input_file.txt -o vision.json
```

-iオプションの後に先ほど作成したテキストファイルを、-oオプションの後に作成するjsonファイルの名前を指定します。
jsonファイルができたら、それを送信します。
送り方はこんな感じ。

```bash
$ python
...
>>> import requests
>>> data = open('/path/to/json', 'rb').read()
>>> response = requests.post(url='https://vision.googleapis.com/v1/images:annotate?key=<API-key>',
    data=data,
    headers={'Content-Type': 'application/json'})
>>> print response.text
>>> ''' 以下、レスポンスの例
{
  "responses": [
    {
      "safeSearchAnnotation": {
        "adult": "VERY_UNLIKELY",
        "spoof": "VERY_UNLIKELY",
        "medical": "VERY_UNLIKELY",
        "violence": "VERY_UNLIKELY"
      }
    }
  ]
}
'''
```

"< API-key >"の部分には、"APIキーの取得"で取得したAPIキーを入力してください。
リクエストを送信して1秒ほどでレスポンスが返ってきます。内容はtextプロパティで確認できます。

## レスポンスの読み方
ここでは有害画像検出の場合のみまとめます。
レスポンスの内容は下記のようにjsonモジュールで取得するのが楽だと思います。

```bash
$ python
...
>>> # 変数responseにレスポンスがあるものとする
>>> import json
>>> response_json = json.loads(response.text)
>>> # 最初の画像の"アダルト度(?)"を取得
>>> print response["responses"][0]["safeSearchAnnotation"]["adult"]
>>> # -> "VERY_UNLIKELY"
...
```

有害画像と判定する観点は"adult", "medical", "spoof", "violence"の４つがあります。
それぞれの意味は以下の表の通りです。  
  

| 観点 | 説明 | 
|-----------|------------|
| adult | アダルトな画像か |
| spoof | 何らかの画像を加工したものか(パクリ画像？) |
| medical | 医療的な画像か(内臓とか) |
| violence | 暴力的な描写の画像か(グロ画像？) |

　　
有害さは５段階で判定され、強い方から"VERY_LIKELY","LIKELY","POSSIBLE","UNLIKELY","VERY_LIKELY"となります。
また、"UNKNOWN"という値も存在するようです。これは上手く判定できなかったときのラベルでしょうか？？(今回試した中では、この値は返ってきませんでした。)

他の機能の結果の見方は、やはりこのページが参考になります。
[Cloud Vision APIの使い方まとめ (サンプルコード付き)](https://syncer.jp/cloud-vision-api)

## 精度
ここに結果を載せてしまうと確実に削除対象になってしまいますので感想だけ述べますと、精度はかなり高いと感じました。

気になる方はご自身の秘蔵のコレクションで試してみてください。

# まとめ
Google Cloud Vision APIの無料トライアルで有害画像検出を試すまでの手順を簡単にまとめました。

このサービスは機械学習の知識があまりない人や、知識はあれど学習データやマシンなどのリソースが揃えられない人も、簡単に最先端の技術を体験することが出来るとても良いものだと思います。
興味が湧いた方は、是非無料トライアルを試してみましょう。

とても楽しいですよ！

## 今回参考にしたページ
[Google Cloud Vision API](https://cloud.google.com/vision/)
[Cloud Vision API Requests and Responses](https://cloud.google.com/vision/docs/requests-and-responses#generating_json_requests)
[Cloud Vision APIの使い方まとめ (サンプルコード付き)](https://syncer.jp/cloud-vision-api)
[有害な画像に機械学習？Cloud Vision APIを使ってみる](http://design-lab.tuqulore.com/safety_image_upload_form_design/)