LoginSignup
6
10

More than 3 years have passed since last update.

衛星データとPythonを使って植物の活性状況を宇宙から可視化

Last updated at Posted at 2019-11-26

前提

Arcgisと呼ばれるGISツールを使いNDVI(植生指数)を計算するプログラム
植生指数とは植物の光の反射の特性を活かし、植物の量や活性状況を簡易的に示す指標
使用したエディタはJupyterで言語はPython

準備

下記のURLを参考にArcgis Rest APIを使えるように登録
Client ID
Client Secret
の2つをのちに使用。

コード

import pandas as pd
import requests
import urllib.request

# Pandasでの表示が省略されないように設定
pd.set_option("max_columns", 100)
pd.set_option('max_rows',1000)
pd.set_option('max_info_columns',100)

まずはライブラリをimportする

ARCGIS_CLIENT_ID = ''
ARCGIS_CLIENT_SECRET = ''

登録した際に取得したCLIENT_IDとCLIENT_SECRETを環境変数として登録

def get_arcgis_token():
    response = requests.get('https://www.arcgis.com/sharing/rest/oauth2/token/',
                            params = {'client_id' : ARCGIS_CLIENT_ID,
                                              'client_secret': ARCGIS_CLIENT_SECRET,
                                              'grant_type': 'client_credentials'})
    arcgis_token = response.json()['access_token']
    return arcgis_token

access_tokenを取得するための関数を定義
APIにアクセスするときに必要

field_center =[[120.095415,40.345695]]
satellite_date = '2019/05/20'
arcgis_token = get_arcgis_token()

・field_center 
NDVIを計測したい土地の座標
複数座標を渡すことも可能

・satellite_date 
データが欲しい時期

・arcgis_token 
APIにアクセスするためのtoken

#points
#複数地点の衛星波長データを取りたいときに使う
#ここではSentinelと呼ばれるヨーロッパの衛星を使う
def get_sentinel_sample(arcgis_token):
    response = requests.get('https://sentinel.arcgis.com/arcgis/rest/services/Sentinel2/ImageServer/getSamples',
                        params = urllib.parse.urlencode({'geometryType' : 'esriGeometryMultiPoint',
                           'geometry': { "points":field_center, 'spatialReference': { 'wkid': 4326}},
                           'mosaicRule': {'mosaicMethod': 'esriMosaicAttribute',
                                                  'where': 'category = 1 AND cloudcover <= 0.10',
                                                  'sortField': 'acquisitionDate',
                                                  'sortValue': satellite_date,
                                                  'ascending': 'true' 
                                                   },
                            'token': arcgis_token,
                            'returnFirstValueOnly': 'true',
                            'f': 'json' }))
    sent_sample = response.json()
    return sent_sample

・"points":field_center, 'spatialReference': { 'wkid': 4326}}
先ほど指定した座標
位置情報を表す際に様々な座標系があるのだがwkidでどの座標系を使用するのか定義する
4326は地理座標系でありGPSで得られる座標系のこと

・'category = 1 AND cloudcover <= 0.10' 
たまに背景画像である灰色の画像が返ってくるのでcategoryを指定し衛星画像しか返ってこないようにする
cloudcoverを指定し雲がか10%以下しかかっていない衛星画像を指定

・'sortValue': satellite_date,
先ほど指定した日付

・token': arcgis_token, 'returnFirstValueOnly': 'true',
先ほど取得したtoken
APIが非常に重いのでここでは初めの値だけ返すように指定

詳しいAPIの仕様については公式のドキュメントを参照(かなり分かりにくい)
https://developers.arcgis.com/rest/services-reference/get-samples.htm

sent_sample = get_sentinel_sample(arcgis_token)
sat_val = sent_sample['samples'][0][('value')]
df_sat_band = pd.DataFrame(columns=['band1','band2','band3','band4','band5','band6','band7','band8','band8a','band9','band10','band11','band12'])
band_val = pd.Series([int(strip_num.strip()) for strip_num in sat_val.split()],index=df_sat_band.columns)
#appendは戻り値で新しいインスタンスを返すため代入し直す
df_sat_band  = df_sat_band.append(band_val, ignore_index=True)
df_sat_band['NDVI'] = (df_sat_band['band8'] - df_sat_band['band4']) /(df_sat_band['band8'] + df_sat_band['band4'])

返ってきたデータを整形しpandasのデータフレーム型にしNDVIを計算しカラムに追加
Sentinelの場合バンド4が赤の波長域でバンド8が近赤外の波長域である
※NDVI計算式 NDVI=(IR-R)/(IR+R)

Screen Shot 2019-11-26 at 9.33.42.png

このようにNDVIを計算することができている

参考文献
https://developers.arcgis.com/rest/services-reference/get-samples.htm
https://qiita.com/boiledorange73/items/b98d3d1ef3abf7299aba

6
10
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
6
10