[Vision API] Javaで画像内のランドマークを検出する

Googleが提供しているVision APIをJavaで使ってみました。

APIを使用し、画像内に含まれているランドマークを検出します。
ランドマークとは、よく知られている自然や人工建造物を示すそうです。

画像内のランドマークの位置だけではなく、**緯度と経度**も取得できます。

:::note info
APIを利用する環境の準備から始める場合や、コードを実行する際は、
[⧉[Vision API] Javaで画像内のいろいろなものを検出する](https://qiita.com/doran/items/444cb6231b7dffb9ddac)
を参照ください。
:::

|No||目次|
|---|---|---|
|1||[Feature.Typeの指定](#1-featuretypeの指定)|
|2||[実行結果の取得](#2-実行結果の取得)|
||1|[レスポンスの出力](#21-レスポンスの出力)|
||2|[レスポンスの内容](#22-レスポンスの内容)|
|3||[結果の検証](#3-結果の検証)|
||1|[ランドマークが少ない場合](#31-ランドマークが少ない場合)|
||2|[ランドマークが多い場合](#32-ランドマークが多い場合)|
||3|[自然のランドマーク](#33-自然のランドマーク)|

# 1. Feature.Typeの指定
ランドマークを検出する場合は、
**Feature.Type.LANDMARK_DETECTION**
を指定します。

以下の記事でexecApi()にタイプを指定します。
[⧉[Vision API] Javaで画像内のいろいろなものを検出する](https://qiita.com/doran/items/444cb6231b7dffb9ddac#25-apiを呼び出す)

# 2. 実行結果の取得
### 2.1. レスポンスの出力
取得した結果をコンソールに出力します。
```
private static void output(BatchAnnotateImagesResponse response){
    List<AnnotateImageResponse> responses = response.getResponsesList();

    for (AnnotateImageResponse res : responses) {
        if (res.hasError()) {
            System.out.format("Error: %s%n", res.getError().getMessage());
            return;
        }
        for (EntityAnnotation annotation : res.getLandmarkAnnotationsList()) {
            LocationInfo info = annotation.getLocationsList().listIterator().next();
            System.out.format("Landmark: %s%n %s%n", annotation.getDescription(), info.getLatLng());
        }
    }
}
```
### 2.2. レスポンスの内容
BatchAnnotateImagesResponseの
getResponsesListでAnnotateImageResponseリストが取得できます。
検出されなった場合は、空のリストが返ってきます。
#### AnnotateImageResponse
|メソッド|戻り値|内容|
|---|---|---|
|getLandmarkAnnotationsList|List\<[EntityAnnotation](#entityannotation)\>|検出された情報|
#### EntityAnnotation
|メソッド|戻り値|内容|
|---|---|---|
|getMid|string|OpaqueエンティティID|
|getDescription|string|検出されたランドマークの説明文|
|getScore|float|検出結果の信頼度。範囲は0〜1|
|getBoundingPoly|[BoundingPoly](#boundingpoly)|ランドマークの画像領域<br><font color="red">値は返ってきますが、未使用だそうです</font>|
|getLocationsList|List\<[LocationInfo](#locationinfo)\>|ランドマークの位置情報|
#### BoundingPoly
未使用だそうです。
|メソッド|戻り値|内容|
|---|---|---|
|getVerticesList|List\<[Vertex](#vertex)\>|境界ポリゴンの頂点。<br>左上、右上、左下、右下の順|
#### Vertex
|メソッド|戻り値|内容|
|---|---|---|
|getX|int|X座標|
|getY|int|Y座標|
#### LocationInfo
|メソッド|戻り値|内容|
|---|---|---|
|getLatLng|[LatLng](#latlng)|ランドマークの緯度と経度の位置座標|
#### LatLng
|メソッド|戻り値|内容|
|---|---|---|
|getLatitude|double|緯度|
|getLongitude|double|経度|

## 3. 結果の検証
画像に含まれるランドマークが少ない場合と多い場合、自然についてそれぞれ検証してみました。

### 3.1. ランドマークが少ない場合
**検出させる元画像**
元の画像、熊本城です。
<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/402f4f0d-6ad2-e351-bf5e-a690ea0a5768.jpeg">

**検出された結果**
検出結果信頼度: 0.7037737
ランドマーク: Kumamoto Castle Honmaru Palace
緯度: 32.80546909999999
経度: 130.7063329
熊本城の本丸とでました。

### 3.2. ランドマークが多い場合
**検出させる元画像**
どこの場所かわからない画像を検出させてみました。
<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/2adde904-da1c-f897-9627-4baf213c4bc6.jpeg">

**検出された結果**
どうやら大阪の梅田みたいです。
検出の信頼度は低いですが、Googleが言っているんだから多分そうなのでしょうw

・グランフロント大阪 タワーA
検出結果信頼度: 0.49405774
ランドマーク: Grand Front Osaka South Building Tower A
緯度: 34.7043234
経度: 135.4950067

・梅田阪急ビル オフィスタワー
検出結果信頼度: 0.40376985
ランドマーク: Umeda Hankyu Building Office Tower
緯度: 34.702442999999995
経度: 135.4991101

・梅田スカイビル
検出結果信頼度: 0.25185502
ランドマーク: Umeda Sky Building
緯度: 34.7052872
経度: 135.4896527

### 3.3. 自然のランドマーク

#### 3.3.1. 富士山の場合
**検出させる元画像**
まずは日本人なら誰でも知っている富士山！
<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/e7932672-4e3e-c29f-f2b9-6ba5ad213372.jpeg">

**検出された結果**
なんと！検出されませんでした。
検出されない場合は、AnnotateImageResponseのリストが空で返ってきます。

#### 3.3.2. エアーズロックの場合
**検出させる元画像**
こちらはエアーズロック。こちらもみんな知っている
<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/512ee765-758e-1aff-8c52-0522e1042b3f.jpeg">

**検出された結果**
こちらは出てきた。
エアーズロックが見られる場所をウルルサンセットビューエリアというらしい。

・ウルルサンセットビューエリア
検出結果信頼度: 0.7684352
ランドマーク: Uluru Sunset Viewing Area
緯度: -25.336152099999996
経度: 131.0048557



<BR>
<BR>
おしまい。。。