4
2

More than 3 years have passed since last update.

PythonでGoogleStreetViewから画像をダウンロードする

Posted at

はじめに

GoogleStreetViewのAPIを利用してパノラマ画像をダウンロードする際に、いい感じの記事が見つからず少し悩んだのでメモ。

ソースコードの全体像はこちら
./street_view_download.py
import argparse
import requests

import google_streetview.api
from bs4 import BeautifulSoup

# デバック用パッケージ
from icecream import ic


class StreetViewRepository:
    def __init__(self, api_key, size=(600, 300)):
        self.api_key = api_key
        self.size = str(size[0]) + "x" + str(size[1])

    def _create_param(
        self, location: str, pitch: int, heading: int, fov: int = 90
    ) -> {}:
        params = [
            {
                "size": self.size,  # max 640x640 pixels
                "location": location,
                "pitch": str(pitch),  # 上下の角度 -90~90 (-90: 真下, 90: 真上)
                "heading": str(heading),  # 方位 0~360 (0:北, 90:東, 180:南, 270:西)
                "fov": str(fov),  # ズーム 0~120
                "key": self.api_key,
            }
        ]
        return params

    def get_pano_for_address(
        self, address: str, pitch: int, heading: int, fov: int = 90
    ):
        """住所からGoogleStreetViewの画像を返すプログラム

        Args:
            address (str): 検索対象の住所
            pitch (int): 上下方向の角度
            heading (int): 水平方向の角度
            fov (int): ズーム
        """
        target_coodinate = self._coordinate(address)
        location = str(target_coodinate[0]) + "," + str(target_coodinate[1])

        ic(address, location)
        params = self._create_param(location, pitch, heading)

        results = google_streetview.api.results(params)
        ic(results.preview())
        results.download_links("downloads")

    def _coordinate(self, address) -> []:
        """
        addressに住所を指定すると緯度経度を返す。

        >>> coordinate('東京都文京区本郷7-3-1')
        ['35.712056', '139.762775']
        """
        URL = "http://www.geocoding.jp/api/"  # Geocording Apiを利用する。
        payload = {"q": address}
        html = requests.get(URL, params=payload)
        soup = BeautifulSoup(html.content, "html.parser")
        if soup.find("error"):
            raise ValueError(f"Invalid address submitted. {address}")
        latitude = soup.find("lat").string
        longitude = soup.find("lng").string
        return [latitude, longitude]


def download_photo(
    api_key: str, address: str, pitch: int = 0, heading: int = 0, fov: int = 90
):
    """住所からGoogleStreetViewの画像を保存する
    Args:
        api_key (str): GoogleStreetViewから取得するAPIキー
        address (str): 検索対象の住所
        pitch (int): 上下方向の角度
        heading (int): 水平方向の角度
        fov (int): ズームの割合
    """
    # 初期化
    sr = StreetViewRepository(api_key=api_key)

    # 画像のダウンロード処理
    sr.get_pano_for_address(
        address=address,
        pitch=pitch,
        heading=heading,
        fov=fov,
    )


if __name__ == "__main__":
    # 引数の設定
    parser = argparse.ArgumentParser()

    parser.add_argument("api_key", help="GoogleStreetViewから取得するAPIキー")
    parser.add_argument("address", help="検索対象の住所")
    parser.add_argument("--pitch", default=0, help="上下方向の角度")
    parser.add_argument("--heading", default=0, help="水平方向の角度")
    parser.add_argument("--fov", default=0, help="ズームの割合")

    args = parser.parse_args()

    download_photo(
        api_key=args.api_key,
        address=args.address,
        pitch=args.pitch,
        heading=args.heading,
        fov=args.fov,
    )

実行コマンドを以下に示す。${APIキー}の箇所には、各自で取得したAPIキーを入力する。

$ python street_view_download.py ${APIキー} 東京都千代田区
ic| address: '東京都千代田区', location: '35.694031,139.753772'

[0] UdOQn3fvD27X6L7Mr48uog
===========================
date: 2020-02
location: 
  lat: 35.6942363
  lng: 139.7538972
pano_id: UdOQn3fvD27X6L7Mr48uog
status: OK
ic| results.preview(): None
$ 

APIの有効化

GoogleStreetViewApiを利用する認証キーの取得方法は、以下の公式のドキュメントを参照。APIの利用にはクレジットカードの登録が必要になるので注意。

実装

google-streetview

GoogleStreetViewをPythonで利用する際には、非公式のライブラリのgoogle-streetviewを利用するのが一番簡単。

インストールは、以下のコマンドで実施する。

pip install google_streetview

指定可能なオプション

GoogleStreetViewのAPIを利用して画像をダウンロードする際に、指定可能なオプションを以下に示す。
ズームや上下の角度の調整など、かなり細かい範囲まで指定できる。

パラメータ名 意味 フォーマット
size ダウンロードする画像のサイズ {縦}x{横}
location 緯度経度 {緯度},{経度}
heading 方位(0:北, 90:東, 180:南, 270:西) [0-360]の範囲の数字
fov ズームの量 [0-120]の範囲の数字
pitch 上下の角度 -90~90 (-90: 真下, 90: 真上) [-90-90]の範囲の数字

ダウンロードする画像のサイズを、{縦}x(エックスの小文字){横}で指定するなど、少し引っ掛かりポイントがあるので注意。筆者も最初はエックスの小文字を算術記号の×を入力していたため、ダウンロードできず少し悩んだ。

住所->緯度経度に変換

APIは緯度経度を入力することで、その地点の画像をダウンロードできると言う仕組みである。しかし、日本のある地点の画像をダウンロードしたいときは、緯度経度を入力するより、住所の入力からその地点の画像をダウンロードできるほうが簡単。その為、入力した日本の住所を緯度経度に変換するコードを作成した。
実装には、以下の方のコードを参考にした。

住所から緯度経度を取得するpythonスニペット - Qiita

    def _coordinate(self, address) -> []:
        """
        addressに住所を指定すると緯度経度を返す。

        >>> coordinate('東京都文京区本郷7-3-1')
        ['35.712056', '139.762775']
        """
        URL = "http://www.geocoding.jp/api/"  # Geocording Apiを利用する。
        payload = {"q": address}
        html = requests.get(URL, params=payload)
        soup = BeautifulSoup(html.content, "html.parser")
        if soup.find("error"):
            raise ValueError(f"Invalid address submitted. {address}")
        latitude = soup.find("lat").string
        longitude = soup.find("lng").string
        return [latitude, longitude]

実行

作成したプログラムで、試しにスカイツリーの地点のStreetViewの画像をダウンロードしてみる。実行コマンドは以下の通り。

$ python street_view_download.py ${APIキー} 東京都墨田区押上1丁目1−2n
ic| address: '東京都墨田区押上1丁目1−2', location: '35.710256,139.810795'

[0] CAoSLEFGMVFpcE5ZVERCVHVLaHhsYkxtdXN5S25NTk5XOWtjaWFydGNoaHlMbWFR
=====================================================================
date: 2020-09
location: 
  lat: 35.71023864335756
  lng: 139.8107896372676
pano_id: CAoSLEFGMVFpcE5ZVERCVHVLaHhsYkxtdXN5S25NTk5XOWtjaWFydGNoaHlMbWFR
status: OK
ic| results.preview(): None

ダウンロードされた画像はこちら。なんとスカイツリーの中に進入できた。

5d6d0ce9.jpg

おわりに

いろんな地点の画像を簡単にダウンロードできて便利。APIの呼び出し回数だけには注意。

GitHub - sey323/google-streetview-downloader: Download Image from Google Streetview in Japan

参考資料

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2