新型コロナによる海の変化は宇宙から見える?
この記事はUMITRON Advent Calendar 2021 12日目の記事です。
こんにちは、UMITRONの宮山(@jkatagi)です。趣味でSplatoon2というゲームをやっているのですが、そろそろプレイ時間が2000時間を超えそうでびっくりしています。
さてUMITRON Advent Calendar 12日目は新型コロナによる海の変化は宇宙から見える?という内容をお届けします。
新型コロナによる人々の行動の変化
2021年は2020年に引き続き、新型コロナの影響が大きい年でした。人間の活動が大きく制限される中で、自然環境にも影響が出ているようです。例えば世界各地で大規模なロックダウンが行われ、その結果として大気汚染物質の排出が軽減されたという報告が多数されています。
同様の変化が河川や海でも起きているようです。
例えばイタリアのベネチアではロックダウンによって観光客が減り、運河が
澄み渡ったようです。
またハワイのハナウマ湾では立ち入り制限により観光客が減り、その結果として海の透明度が42%も向上したようです。
元データはこちら
このような変化は新型コロナが終息した後は元に戻ってしまう可能性もありますが、大変興味深い現象です。この河川や海の変化、とりわけ(UMITRONなので)海の変化について宇宙から見れないかを検討してみようと思います。具体的には上で挙げたハワイのハナウマ湾の透明度の変化を見てみようと思います。
(先にネタバレしてしまうと今回の検討では捉えることができませんでした😢)
透明度を何で測るか
透明度と一口で言っても、測りかた(測るもの)はたくさんあります。透明度の原因が何かによって、リモートセンシングで用いる波長が異なります。今回はCDOM(有色溶存有機物)やクロロフィルaといった有機物の浮遊が減ったというよりは、普段水中を舞っていた砂が沈降したということで、無機物の浮遊量が減ったと仮定します。実際に元データを見てみると、Secchi disk methodによる計測が行われていました。Secchi disk methodとはSecchi diskというディスクを海面から沈めていって、そのdiskが見えなくなるところの深さを計測することにって透明度を測る手法のようです。Youtubeに計測の様子が上がっていたので貼っておきます。
今回はAdvent Calendarの時間的制約とこの分野の私の経験不足から、以下を参考に簡易的なバンド比を用いることします。
Google Earth Engineで見てみる
衛星画像解析ツールとしてGoogle Earth Engineを用います。まずはともあれハナウマ湾周辺の衛星画像を見てみます。ハナウマ湾は北緯21.27度西経157.71度あたりに位置しています。
砂浜から海に向かう途中に見える茶色いものはサンゴ礁です。下記ドローン動画を見ると湾の様子がよくわかります。
さてここで問題なのが、透明度が高くなったのがどのあたりの領域かです。
赤色で囲った浅いところ
緑色で囲ったの深いところ
赤色・緑色合わせた領域
先程の元データに戻ると、P11に領域の定義がされていました
上記いずれも赤色の領域に含まれているので、赤色の領域に着目すれば良さそうです。
衛星画像はSentinel-2のLevel-2Aプロダクト(大気下端の反射率)を用います。各バンドの波長は以下のようになっています
結果
以下にRGBの各バンド比を赤色の領域で計算した結果を示します。
2021/11/01のピークのデータは外れ値っぽいので省いて見てみます
ハナウマ湾が閉鎖されたのが2020/03/16とのことなので、その前後のデータに着目してみます。図中の赤い点が202/03/04です。2019年の同じ時期のデータを比較してみても、それらしい変化は見られませんでした。このデータを眺めながらそういえばGCOM-Cのプロダクトに懸濁物質濃度があったなーと思い出しました。しかし調べたところ解像度が1/24度(1度を約110kmとすると、1ピクセル約4.6km)で、ハナウマ湾が~0.25kmを考えると厳しいことがわかりました(無念)。そこで試しにGCOM-C/SGLIの懸濁物質濃度の変換式をSentinel-2に適用してみます(注:GCOM-C/SGLIのセンサー特性・日本周辺の現地観測に基づいた式のため、異なるセンサー・異なる領域に同じ式を適用するのはダメなのは分かりつつやっております)
うーむ、やはり年毎に比べてもそれらしい顕著な変化は見られませんでした。2020/11あたりの下落は季節性のもののような気もします。なお今回用いたコードは以下になります。
function maskS2clouds(image, divide) {
var qa = image.select('QA60');
var cloudBitMask = 1 << 10;
var cirrusBitMask = 1 << 11;
var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
.and(qa.bitwiseAnd(cirrusBitMask).eq(0));
return image.updateMask(mask);
}
function maskClouds(img) {
var clouds = ee.Image(img.get('cloud_mask')).select('probability');
var isNotCloud = clouds.lt(MAX_CLOUD_PROBABILITY);
return img.updateMask(isNotCloud);
}
function calcIndex1(image) {
var index1 = image.expression('index1 = B5-((B4+B6)/2)', {
'B5': image.select('B5').divide(10000),
'B4': image.select('B4').divide(10000),
'B6': image.select('B6').divide(10000),
})
return image.addBands([index1])
}
function calcIndex2(image) {
var index1 = image.expression('index1 = B2/B3', {
'B2': image.select('B2').divide(10000),
'B3': image.select('B3').divide(10000),
})
var index2 = image.expression('index2 = B2/B4', {
'B2': image.select('B2').divide(10000),
'B4': image.select('B4').divide(10000),
})
var index3 = image.expression('index3 = B3/B4', {
'B3': image.select('B3').divide(10000),
'B4': image.select('B4').divide(10000),
})
// https://suzaku.eorc.jaxa.jp/GCOM_C/data/ATBD/ver2/V2ATBD_O3AB_TSM_Toratani_jp.pdf
// log opereation cannot be used in image.expression, so calc step by step.
var ln10 = 2.3026
var index4 = image.select('B3')
.divide(image.select('B4'))
.log()
.divide(ln10) // convert log base to 10
.multiply(-1.5831)
.add(
image.select('B4')
.log()
.divide(ln10) // convert log base to 10
.multiply(0.3626)
)
.add(1.2096)
.rename('index4');
return image.addBands([index1, index2, index3, index4])
}
var startDate = '2017-03-28';
var endDate = '2021-11-01';
// var endDate = '2021-12-10';
var MAX_CLOUD_PROBABILITY = 65;
var s2Clouds = ee.ImageCollection('COPERNICUS/S2_CLOUD_PROBABILITY')
.filterDate(startDate, endDate);
var dataset = ee.ImageCollection('COPERNICUS/S2_SR')
.filterDate(startDate, endDate)
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',20))
.map(maskS2clouds)
.map(calcIndex2);
var datasetWithCloudMask = ee.Join.saveFirst('cloud_mask').apply({
primary: dataset,
secondary: s2Clouds,
condition:
ee.Filter.equals({leftField: 'system:index', rightField: 'system:index'})
})
var datasetWithMasked = ee.ImageCollection(datasetWithCloudMask)
.map(maskClouds);
var result = ui.Chart.image.series(
datasetWithMasked.select(['index1', 'index2', 'index3']),
redPolygon,
ee.Reducer.mean(),
10
).setOptions({
vAxis: {title: "value"},
hAxis: {title: "Date", format: 'YYYY-MM'},
})
print(result)
// visualize image at June
var juneImage = ee.ImageCollection('COPERNICUS/S2_SR')
.filterDate('2020-06-01', '2021-07-01')
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',20))
.map(maskS2clouds);
var visualization = {
min: 0.0,
max: 0.3 * 10000,
bands: ['B4', 'B3', 'B2'],
};
Map.setCenter(-157.7066461, 21.27003, 15);
Map.addLayer(juneImage, visualization);
考察
今回試してみて思うような結果は得られませんでした。考えられる理由としては
単純なバンド比では表せられない
報告されたような6~8 mの透明度の差はバンド比では見られない?
そもそも対象としている地域がかなり浅瀬の可能性があり、衛星画像で捉えるのが難しい?
他にもきちんと検証するためには現地の観測データとの突合や現地の水域の光学特性をきちんと理解するといった作業が必要そうです。
また今回時間の都合で検討できなかったデータとしてSentinel-3があります。今回のような領域ではもしかしたらこちらの衛星のセンサーを用いた方が良い結果が得られたかもしれません。
終わりに
今回は新型コロナによる海の変化は宇宙から見える?というテーマで取り組んでみました。結果として思うような結果が得られず、ノート自体没とするか迷いましたが公開することにします。余談ですが調べながら懸濁物質の推定の世界も奥が深い(観測ベースのものや物理に基づくものなど)ことがわかりました。また調べていく中でいくつか面白そうな論文を見つけたので(例えば冒頭で挙げたベネチアの水質変化が衛星画像から捉えられたようです)、それらの論文を読みつつ他の地域でも検討していつかリベンジしたいです。もしこういう手法なら綺麗に捉えられたよ〜というのがありましたら、ぜひコメントやTwitterなどで教えていただけると幸いです。
ウミトロンでは一緒に働く仲間を募集しております。持続可能な水産養殖を地球に実装するというミッションの元で、私たちと一緒に水産養殖xテクノロジーに取り組みませんか?