Weather Challenge:雲画像予測 チュートリアル

create date : Aug. 6, 2019 at 15:40:00

概要

「Weather Challenge:雲画像予測」で扱う特殊な気象データについてのチュートリアルです。

テレビのお天気コーナーやインターネット・スマホアプリなどで手軽に衛星画像を見ることはできますが、実際にデータとして入手して何らかの解析を行う機会は少ないと思います。また気象庁ウェブサイトからアメダス観測データをダウンロードして利用したことがある方は少なくないかもしれませんが、コンピュータで解析して作られた3次元の気象データに触れたことのある方はあまりいないのではないかと思います。

本チュートリアルは、多くの方にとって馴染みがないと思われる気象データについて、可視化を通じて理解を深めていただくことを目的としています。直接的にモデル構築をサポートする内容ではありませんが、気象データについて理解の一助となれば幸いです。

本チュートリアルの構成は以下の通りです。

  • 使用するライブラリ
  • データの準備
  • 衛星画像
    • 夏と冬の違い
    • 天気パターンによる違い
    • 日変化がわかる場合
    • データの欠損について
  • 気象データ
    • 関数の準備
    • 850hPaの気温
    • 海面気圧
    • 700hPaの湿度
    • 500hPaの高度
    • 300hPaの風
    • 風向・風速の計算
  • まとめ
  • 付録:評価領域の切り取り方法

必要なライブラリ

PNG形式の衛星画像の読み込みにはOpenCVを使用しています。インストールについてはPyPI等のウェブサイトをご参照下さい。scikit-image等、他のライブラリを使用される場合は適宜読み替えて下さい。

バイナリの気象データの読み込みにはNumpyを使用しています。gzip圧縮されたバイナリ形式のファイルは、gzipとshutilを用いて解凍処理をしています。

気象データの可視化にはBasemapを使用しています。インストールについてはこちらのGitHub等をご参照下さい。

日時の取り扱いにはdatetimeを使用しています。

データの準備

コンペティションのウェブサイトからダウンロードできるデータのうち、2017年のデータを使います。ダウンロードしたzipファイルを解凍すると、以下のようなディレクトリ構成で展開されます。

  • train/
    • sat/
      • YYYY-MM-DD/
        • YYYY-MM-DD-HH-00.fv.png
    • met/
      • YYYY/
        • MM/
          • DD/
            • <Element_Name>.<Height_Info>.3.YYYYMMDDHH.gz

ここでYYYY・MM・DD・HHは日時情報、<Element_Name>は気象要素、<Height_Info>は高度情報を表します。

以下、カレントディレクトリに上記のようにデータが展開されているものとして記述していきます。

衛星画像

とりあえず使用するライブラリをまとめてインポートしておきます。

In [1]:
import numpy as np
import cv2
import os
import gzip
import shutil
from datetime import datetime as dt
from datetime import timedelta
from mpl_toolkits.basemap import Basemap
from mpl_toolkits.axes_grid1 import make_axes_locatable
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
import warnings
warnings.filterwarnings('ignore', category=matplotlib.MatplotlibDeprecationWarning)

本コンペティションで使用する衛星画像の種類は赤外画像です。地表面・雲・大気から放射される赤外線を観測し、温度を測定しています。可視画像は昼間しか観測できないのに対し、赤外画像は24時間観測できるので、一定間隔で連続した画像を得ることができます。

元々のデータは温度(輝度温度)のデータですが、配布したデータは低い温度ほど白くなるよう調整した256階調グレースケールの画像ファイルです。

夏と冬の違い

では実際の衛星画像を見てみましょう。衛星画像自体は見たことがあっても、夏と冬の画像を並べて見ることはなかなかありません。そこで(左)2017年8月1日00UTCと、(右)2017年12月27日00UTCの画像を並べて見てみましょう。

In [2]:
file1 = "train/sat/2017-08-01/2017-08-01-00-00.fv.png"
file2 = "train/sat/2017-12-27/2017-12-27-00-00.fv.png"

img1 = cv2.imread(file1, 0)
img2 = cv2.imread(file2, 0)

print( "image shape : ", img1.shape )
print( "data type : ", img1.dtype )

fig, axes = plt.subplots(1, 2, figsize=(12,8))
axes[0].imshow(img1, cmap='gray')
axes[0].set_title("Satellite Image on 2017/08/01 00:00UTC")
axes[1].imshow(img2, cmap='gray')
axes[1].set_title("Satellite Image on 2017/12/27 00:00UTC")
plt.show()
image shape :  (672, 512)
data type :  uint8

余談ですが、画像ファイルのshapeは(672, 512)、データ型はuint8となっています。

さて見比べてみますと、随分と印象が異なることがわかります。夏は陸地・海面ともに温度が高くなっているため黒く写り、また雲頂が10000mを超える積乱雲群は雲頂温度が低くて真っ白に写ります。このため黒白のコントラストがはっきりします。なお南海上の渦巻く白い雲域は台風5号です。

これに対し冬は陸地が冷えるためグレーになり、海陸の温度差が広がって海岸線がはっきり見えるようになります。また雲も夏のような雲頂の高い雲が少なくなり、ほとんどがグレーで写っています。このため全般にグレー寄りの色となります。

この様子をヒストグラムでも見てみましょう。2017年8月と2017年12月の、それぞれ1ヶ月分の衛星画像を読み込みます。

In [3]:
img08 = []
img12 = []
date08 = dt(2017, 8 , 1, 0, 0, 0)
date12 = dt(2017, 12 , 1, 0, 0, 0)

# 1ヶ月分の衛星画像を読み込む
for i in range(31*24):
    file08 = "train/sat/{year}-{month:02}-{day:02}/{year}-{month:02}-{day:02}-{hour:02}-00.fv.png".\
                    format(year=date08.year, month=date08.month, day=date08.day, hour=date08.hour)
    if os.path.exists(file08):
        img = cv2.imread(file08, 0)
        img08.append(img)
        
    file12 = "train/sat/{year}-{month:02}-{day:02}/{year}-{month:02}-{day:02}-{hour:02}-00.fv.png".\
                    format(year=date12.year, month=date12.month, day=date12.day, hour=date12.hour)
    if os.path.exists(file12):
        img = cv2.imread(file12, 0)
        img12.append(img)

    date08 = date08 + timedelta(hours=1)
    date12 = date12 + timedelta(hours=1)

# ヒストグラム作成
all_img08 = np.concatenate(img08).flatten()
all_img12 = np.concatenate(img12).flatten()

fig, ax = plt.subplots(1, 1, figsize=(8,8))
ax.hist(all_img08, bins=np.arange(256 + 1), alpha=0.3, color="r", label="August, 2017")
ax.hist(all_img12, bins=np.arange(256 + 1), alpha=0.3, color="b", label="December, 2017")
ax.set_title("Histogram of Satellite Images")
ax.set_ylim(0, 6000000)
plt.legend()
plt.show()

8月は雲のないエリアがほぼ黒になるため画素値の小さいところにピークがありますが、冬は陸地もグレーになるので真ん中あたりに集まっています。

また画素値が200以上になると夏の方が多くなっています。255にピークがあるのは、一定閾値以下の温度をまとめて255にしているためです。

天気パターンによる違い

では次に天気パターンによる違いの一例をご紹介します。(左)2017年4月11日00UTCは前線を伴った低気圧が日本列島に接近したときの衛星画像、(右)2017年6月29日18UTCは長崎・壱岐市で記録的な大雨となったときの衛星画像です。

In [4]:
file3 = "train/sat/2017-04-11/2017-04-11-00-00.fv.png"
file4 = "train/sat/2017-06-29/2017-06-29-18-00.fv.png"

img3 = cv2.imread(file3, 0)
img4 = cv2.imread(file4, 0)

fig, axes = plt.subplots(1, 2, figsize=(12,8))
axes[0].imshow(img3, cmap='gray')
axes[0].set_title("Satellite Image on 2017/04/11 00:00UTC")
axes[1].imshow(img4, cmap='gray')
axes[1].set_title("Satellite Image on 2017/06/29 18:00UTC")
plt.show()

左側、画像の中央付近から南東・南西に伸びる帯状の雲域は前線に伴うものです。また画像の上部に半円状に広がる雲は上空の強い風によって広がったもので、はけで掃いたような形状をしています。この低気圧による雲域は、層状の雲やもくもくとした積雲が混ざっており、高さも様々なため斑ら模様のようになっています。一般に低気圧に伴う雲域は、低気圧の移動とともに順調に西から東へ流れていきます。

一方で右側、画像中央付近の白い雲は積乱雲の塊で、雲頂高度が高いため真っ白になっています。また積乱雲群は雲域の輪郭が比較的シャープになることも特徴の1つです。こうした雲も上空の風によって東寄りに流されますが、発生源は地上近くにあって動きが遅いため、結果として積乱雲が同じ場所に長時間掛かり続けることになり、記録的な大雨をもたらすことがあります。

なお各日の天気図については気象庁ウェブサイトをご参照下さい。

日変化がわかる場合

では次に、朝と昼の見え方の違いを紹介します。(左)2017年12月26日21UTC、つまり日本時間で27日の朝の衛星画像です。(右)2017年12月27日03UTC、つまり同じ日の正午の衛星画像です。

In [5]:
file5 = "train/sat/2017-12-26/2017-12-26-21-00.fv.png"
file6 = "train/sat/2017-12-27/2017-12-27-03-00.fv.png"

img5 = cv2.imread(file5, 0)
img6 = cv2.imread(file6, 0)

fig, axes = plt.subplots(1, 2, figsize=(12,8))
axes[0].imshow(img5, cmap='gray')
axes[0].set_title("Satellite Image on 2017/12/26 21:00UTC")
axes[1].imshow(img6, cmap='gray')
axes[1].set_title("Satellite Image on 2017/12/27 03:00UTC")
plt.show()