写真からランドマークを検出して住所情報を自動取得させてみた


# 概要
いろいろなAPIを利用して、自動で、写真からランドマークを検出し、住所情報も取得した。

# 利用したAPI
![t.jpg](https://qiita-image-store.s3.amazonaws.com/0/199902/4e2ed071-f637-900b-e865-6f91b4f6ee98.jpeg)


## Vision API
![vision api.png](https://qiita-image-store.s3.amazonaws.com/0/199902/890edb50-fff5-1192-29ec-7702b6295319.png)

https://cloud.google.com/vision/?hl=ja
Googleが提供している画像コンテンツ解析API
写真に写っているランドマークを検出するLANDMARK_DETECTIONや、写っているものを識別してラベルとして返すLABEL_DETECTION、テキスト検出や、顔検出、ロゴサーチ、セーフサーチなどの機能がある。
今回は`LANDMARK_DETECTION`を利用して、ランドマークとその緯度経度を検出させる。

### 事前準備
下記URLに従って、VisionAPIを有効化する必要がある。
https://cloud.google.com/vision/docs/before-you-begin?hl=ja

ローカル環境でPythonなどのライブラリ経由で利用するため、IAMでの認証設定・ライブラリインストールも必要。
https://cloud.google.com/vision/docs/libraries?hl=ja#client-libraries-install-python


## Google Maps API
![google maps api.jpg](https://qiita-image-store.s3.amazonaws.com/0/199902/67494444-a426-33c5-271f-e92f4c5eea21.jpeg)

https://cloud.google.com/maps-platform/?hl=ja
Webサイト上にGoogle Mapを載せたり、住所から緯度経度を、緯度経度から住所を取得できたりするAPI。
今回利用したのは、緯度経度から住所情報を取得する`Geocoding API`
一点注意が必要なのが、レスポンスはすべて英語となっており、日本語での住所情報が欲しい場合は他のAPIを利用する必要がある。

### 事前準備
同じくGoogle Maps APIを有効化する必要がある。
Google Maps APIは、VisionAPIと違ってAPI Keyが必須なので注意。
参考：[Google Maps API を使ってみた
](https://qiita.com/Haruka-Ogawa/items/997401a2edcd20e61037)




## Geo API
![geoapi.png](https://qiita-image-store.s3.amazonaws.com/0/199902/7a5050f9-642e-6550-7501-8e7e4c5ea53f.png)

http://geoapi.heartrails.com/
緯度経度から住所情報を取得するAPI。
こちらは日本に特化したものとなっており、日本語で住所情報を取得可能。



# 試してみた
## ターゲット
伏見稲荷大社の写真で試してみる。

![fushimi-inari.jpg](https://qiita-image-store.s3.amazonaws.com/0/199902/06707921-56a7-038e-bd60-999295b780e7.jpeg)

住所は**〒612-0882 京都府京都市伏見区深草藪之内町６８**である。

## Vision API
今回はpython3

```python
>>> import os, io
>>> from google.cloud import vision
>>> from google.cloud.vision import types
>>> client = vision.ImageAnnotatorClient()
>>> file_name = "Desktop/fushimi-inari.jpg"
>>> with io.open(file_name, 'rb') as image_file:
...     content = image_file.read()
... 
>>> image = types.Image(content=content)
>>> response = client.landmark_detection(image=image)
>>> response.landmark_annotations[0]
mid: "/m/05ldrm"
description: "Fushimi Inari-Taisha"
score: 0.7252039909362793
bounding_poly {
  vertices {
    x: 165
    y: 193
  }
  vertices {
    x: 928
    y: 193
  }
  vertices {
    x: 928
    y: 781
  }
  vertices {
    x: 165
    y: 781
  }
}
locations {
  lat_lng {
    latitude: 34.967139
    longitude: 135.77301
  }
}

```

見事、`description`にあるように、ランドマークとしてFushimi Inari-Taishaが検出された。
`score`は確度、`bounding_poly`は検出された位置を示している。
そして、`location`として緯度経度も取得できた。

## Google Maps API

```python
>>> import googlemaps
>>> from pprint import pprint
>>> GOOGLE_MAPS_API_KEY="your API key"
>>> gmaps = googlemaps.Client(key=GOOGLE_MAPS_API_KEY)
>>> latitude = response.landmark_annotations[0].locations[0].lat_lng.latitude
>>> longitude = response.landmark_annotations[0].locations[0].lat_lng.longitude
>>> result = gmaps.reverse_geocode((latitude, longitude))
>>> pprint(result)
[{'address_components': [{'long_name': '68',
                          'short_name': '68',
                          'types': ['premise']},
                         {'long_name': 'Fukakusa Yabunouchichō',
                          'short_name': 'Fukakusa Yabunouchichō',
                          'types': ['political',
                                    'sublocality',
                                    'sublocality_level_2']},
                         {'long_name': 'Fushimi-ku',
                          'short_name': 'Fushimi-ku',
                          'types': ['political',
                                    'sublocality',
                                    'sublocality_level_1']},
                         {'long_name': 'Kyōto-shi',
                          'short_name': 'Kyōto-shi',
                          'types': ['locality', 'political']},
                         {'long_name': 'Kyōto-fu',
                          'short_name': 'Kyōto-fu',
                          'types': ['administrative_area_level_1',
                                    'political']},
                         {'long_name': 'Japan',
                          'short_name': 'JP',
                          'types': ['country', 'political']},
                         {'long_name': '612-0882',
                          'short_name': '612-0882',
                          'types': ['postal_code']}],
  'formatted_address': '68 Fukakusa Yabunouchichō, Fushimi-ku, Kyōto-shi, '
                       'Kyōto-fu 612-0882, Japan',
  'geometry': {'location': {'lat': 34.96718810000001, 'lng': 135.7732651},
               'location_type': 'ROOFTOP',
               'viewport': {'northeast': {'lat': 34.96853708029151,
                                          'lng': 135.7746140802915},
                            'southwest': {'lat': 34.96583911970851,
                                          'lng': 135.7719161197085}}},
  'place_id': 'ChIJ7-v-BhUPAWAR3z0uXSNuPO8',
  'plus_code': {'compound_code': 'XQ8F+V8 Kyoto, Kyoto Prefecture, Japan',
                'global_code': '8Q6QXQ8F+V8'},
  'types': ['street_address']},
 {'address_components': ...以後省略
```

`formatted_address`が住所情報で、構成する要素が`address_components`に格納されている。

取得できた住所は、**8 Fukakusa Yabunouchichō, Fushimi-ku, Kyōto-shi, Kyōto-fu 612-0882, Japan**
英語ではあるが、正しい住所情報を取得できた。

## geoAPI
続いて、getAPIで日本語での住所情報も取得する。
APIのエンドポイントは`http://geoapi.heartrails.com/api/json`。ここにGETすればよい
必要なパラメータはこちら

|パラメータ|値|
|-------|-------|
|method|searchByGeoLocation（固定）|
|x| 経度|
|y| 緯度|

```python
>>> url = "http://geoapi.heartrails.com/api/json?method=searchByGeoLocation"
>>> params = {
...         "x": longitude,
...         "y": latitude
...     }
>>> import requests
>>> r = requests.get(url, params=params)
>>> pprint(r.json())
{'response': {'location': [{'city': '京都市伏見区',
                            'city_kana': 'きょうとしふしみく',
                            'distance': 71.82043454757451,
                            'postal': '6120882',
                            'prefecture': '京都府',
                            'town': '深草薮之内町',
                            'town_kana': 'ふかくさやぶのうちちょう',
                            'x': '135.772224',
                            'y': '34.967102'},
                           {'city': '京都市伏見区',
                            'city_kana': 'きょうとしふしみく',
                            'distance': 173.26500637918542,
                            'postal': '6120881',
                            'prefecture': '京都府',
                            'town': '深草稲荷御前町',
                            'town_kana': 'ふかくさいなりおんまえちょう',
                            'x': '135.771117',
                            'y': '34.967266'},
                           {'city': '京都市伏見区',
                            'city_kana': 'きょうとしふしみく',
                            'distance': 238.45040420335357,
                            'postal': '6120888',
                            'prefecture': '京都府',
                            'town': '深草大門町',
                            'town_kana': 'ふかくさだいもんちょう',
                            'x': '135.772471',
                            'y': '34.965043'},
                           {'city': '京都市伏見区',
                            'city_kana': 'きょうとしふしみく',
                            'distance': 247.53084931789914,
                            'postal': '6120807',
                            'prefecture': '京都府',
                            'town': '深草稲荷中之町',
                            'town_kana': 'ふかくさいなりなかのちょう',
                            'x': '135.77084',
                            'y': '34.968474'},
                           {'city': '京都市伏見区',
                            'city_kana': 'きょうとしふしみく',
                            'distance': 282.43664119023936,
                            'postal': '6120806',
                            'prefecture': '京都府',
                            'town': '深草開土町',
                            'town_kana': 'ふかくさかいどちょう',
                            'x': '135.773046',
                            'y': '34.969676'},
                           {'city': '京都市伏見区',
                            'city_kana': 'きょうとしふしみく',
                            'distance': 283.5300564540047,
                            'postal': '6120805',
                            'prefecture': '京都府',
                            'town': '深草開土口町',
                            'town_kana': 'ふかくさかいどぐちちょう',
                            'x': '135.774601',
                            'y': '34.969327'},
                           {'city': '京都市伏見区',
                            'city_kana': 'きょうとしふしみく',
                            'distance': 290.88767776536855,
                            'postal': '6120889',
                            'prefecture': '京都府',
                            'town': '深草直違橋十一丁目',
                            'town_kana': 'ふかくさすじかいばし11ちょうめ',
                            'x': '135.770897',
                            'y': '34.965182'},
                           {'city': '京都市伏見区',
                            'city_kana': 'きょうとしふしみく',
                            'distance': 311.7538119765497,
                            'postal': '6120013',
                            'prefecture': '京都府',
                            'town': '深草祓川町',
                            'town_kana': 'ふかくさはらいがわちょう',
                            'x': '135.769595',
                            'y': '34.967245'},
                           {'city': '京都市伏見区',
                            'city_kana': 'きょうとしふしみく',
                            'distance': 320.4272613869519,
                            'postal': '6120808',
                            'prefecture': '京都府',
                            'town': '深草稲荷榎木橋町',
                            'town_kana': 'ふかくさいなりえのきばしちょう',
                            'x': '135.770798',
                            'y': '34.969375'},
                           {'city': '京都市伏見区',
                            'city_kana': 'きょうとしふしみく',
                            'distance': 330.8874458592692,
                            'postal': '6120811',
                            'prefecture': '京都府',
                            'town': '深草笹山町',
                            'town_kana': 'ふかくさささやまちょう',
                            'x': '135.776632',
                            'y': '34.967298'}]}}
```

日本語での住所情報として、**京都市伏見区深草薮之内町**が取得できた。


# 最後に
個人開発した旅行写真紹介サイト[【Where to Visit?】](https://gae2.fk-management.com)では、このAPI連携を利用して、写真の住所情報やランドマークを自動登録しているので、ぜひ見てみてください。

参照：[GAE×DjangoでWebサービスを開発してみた
](https://qiita.com/tfuruya/items/f935b37e4007ea890574)