Android で CloudVision API を使って顔検出する

[Android で CloudVision API を使ってラベル検出する](https://qiita.com/ohwada/items/b34718df6a6362e493dc)
の続きです。


前回の記事では、ラベル検出を行った。
今回は、顔検出を行う。

下記を参考にした。

[docs : 顔検出のチュートリアル](https://cloud.google.com/vision/docs/face-tutorial)

[docs : 顔の検出](https://cloud.google.com/vision/docs/detecting-faces)


### リクエストの作成

基本的な処理は、ラベル検出と同じです。

違いは、機能のタイプに顔検出を指定すること。

[docs : Feature 機能](https://cloud.google.com/vision/docs/features)

```
                Feature feature = new Feature();
// 顔検出を指定する
                feature.setType("FACE_DETECTION");
```

### 顔検出のレスポンス

ラベル検出では、取得できるアノテーションはラベルだけでした。

顔検出では、下記のアノテーションが取得できる。

- 顔の輪郭
- 目や口などのランドマーク
- 顔の角度
- 喜びや怒りなどの感情

まずは、チュートリアルにあるように、
顔の輪郭を描画する。

### 顔の輪郭を取得する

### FaceAnnotation

顔検出のレスポンスのクラス

[Api: FaceAnnotation](https://developers.google.com/resources/api-libraries/documentation/vision/v1/java/latest/com/google/api/services/vision/v1/model/FaceAnnotation.html)

getBoundingPoly と getFdBoundingPoly　という
よく似た２つのメソッドがあり、どちらを使うのか迷う。
下記の注釈がついているが、よく分からない。
fd_bounding_poly は boundingPoly よりもタイトで、
顔の肌の部分のみを囲みます。
これはランドマークの結果には基づいておらず、最初の顔検出のみに基づいているため、fd（顔検出）プレフィックスが付いています。

幾つか試してみると、getBoundingPoly には２つの頂点の値しかの入っていない場合があった。
２つでは多角形にならないので、
fd_bounding_poly を使うことにする。


### BoundingPoly

顔の輪郭を示す多角形のメタデータ
多角形の頂点のx y 座標が取得できる

[Api : BoundingPoly](https://developers.google.com/resources/api-libraries/documentation/vision/v1/java/latest/com/google/api/services/vision/v1/model/BoundingPoly.html)


### Vertex

多角形の頂点のメタデータ

x y 座標が取得できる


[Api : Vertex](https://developers.google.com/resources/api-libraries/documentation/vision/v1/java/latest/com/google/api/services/vision/v1/model/Vertex.html)


下記のように、顔の輪郭の情報を取得する

```
FaceAnnotation faceAnnotation;
BoundingPoly	boundingPoly = faceAnnotation.getFdBoundingPoly();
List<Vertex> vertices = boundingPoly.getVertices()
```

### 顔の輪郭を描画する

下記のように、顔の輪郭の情報をAndroid の Path クラスに変換する

[reference : Path]( https://developer.android.com/reference/android/graphics/Path)


```
    List<Vertex> vertices;

    Path path = new Path();
   int x0 = 0;
    int y0 = 0;
    for (int i=0; i<vertices; i++ ) {
            Vertex = vertice = vertices.get(i);
            int x = vertice.getX();
            int y = vertice.getY();
            if(i == 0) {
                x0 = x;
                y0 = y;
                path.moveTo(x, y);
            } else {
                path.lineTo(x, y);
            }
    }
    path.lineTo(x0, y0);
```

### 実行例

スクリーンショト
人の顔を検出して顔の輪郭を描画する
![cloudvision4_face_detect.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64075/b0b85596-9246-4ac4-fa04-870a1f7f9218.png)

### 感情の検出

下記のような結果になる。
いずれも VERY_UNLIKELY なので、無表情かな。

> joyLikelihood: VERY_UNLIKELY
> angerLikelihood: VERY_UNLIKELY
> sorrowLikelihood: VERY_UNLIKELY
> surpriseLikelihood: VERY_UNLIKELY
> headwearLikelihood: VERY_UNLIKELY
> blurredLikelihood: VERY_UNLIKELY
> underExposedLikelihood: VERY_UNLIKELY
> underExposedLikelihood: VERY_UNLIKELY
> underExposedLikelihood: VERY_UNLIKELY
> underExposedLikelihood: VERY_UNLIKELY

感情の検出はこれといったアプリの案が浮かばなかった。
参考までに、下記の記事を紹介する。

- [Cloud Vison APIを使って、笑ってはいけないのアレができる
Androidアプリを作ってみた](https://qiita.com/hiesiea/items/4027fed7701ccc0c1225)

- [Cloud Vision APIをAndroidで使って感情検知する](https://qiita.com/tebasakyu/items/f4af67019be8d98899b8)

サンプルコードをgithub に公開した。
https://github.com/ohwada/Android_Samples/tree/master/CloudVision4