◆ラズパイ天気予報 【東京地方】
— プログラミング素人 (@s51517765) 2018年3月3日
4日は、晴れるでしょう。
5日は、曇りで昼前から雨となる見込みです。
ラズパイで天気予報を取得して毎朝Tweetするようにしていますが、より細かい雨の様子を取得してみたいと思います。
これには、日本気象協会のHPから自宅付近の雨雲の様子を取得して解析すればできそうです。
tenki.jp
python3とSeleniumで雨雲の様子を取得し、Open CVで雨雲の分析をします。
雨が降っていたら、さらにSlackerに画像をアップするようにしました。
ブラウザはヘッドレスのPhantomJSを使用しました。
今回使うMojuleはAnacondaの他に↓のあたりが追加で必要となります。(Windowsです。)
入ってないときはAnacondano Promptからpip installします。
pip install opencv-python pip install selenium pip instal slacker
今回のプログラム構成
①ヘッドレスブラウザで天気情報(雨雲)にアクセス②画面キャプチャ
③必要な部分を切り取る
一度試しに各自の環境にてキャプチャをとってみて、必要な部分をトリミングします。
④雨雲情報を取得したい場所を指定
⑤雨雲情報を取得した部分をわかりやすく四角で囲む
ここでは雨雲情報を取得したい場所を中心に上下15pxの四角に囲みました
⑥画像を保存
⑦雨雲状況を判断
⑧雨だったらslackに投稿
雨の判定
これが今回結構難しかったです。こういうのをやろうとすると、すぐにディープラーニングとかNNとかAIとか考えがちですが、そこまでやらなくてもできます。
雨雲情報の右下にある雨の強さを表すカラーバーにしたがって、色情報を取得して対応させます。
まずは、このカラーバーの色情報を分析してみました。
このスクリーンショットのカラーバーをOpen CVで解析します。
画像の下から上までのRGB情報を取得します。
def bar(): clp = cv2.imread("bar.png") y=12 print("B,G,R") for x in range(120): pixelValue = [clp[120-x, y, 0], clp[120-x, y, 1], clp[120-x, y, 2]] print(pixelValue[0],",",pixelValue[1],",",pixelValue[2],)
これをグラフにすると、↓のようになります。
ここから、弱い雨はCyan、その次がBlueということがわかり、RGBで判断できます。
閾値は、いくつかの雨の強度の違うところの情報を取得して決めました。
今日は、日本全国あまり雨が降っていないので確認できるのは2段階ぐらいですが。
東京は雨が降っていないので、青森県へ出張しています(嘘です)。
弱い雨
やや強い雨
海の上だけど(笑)
Slackへの通知
↓のあたりを参考にBotのアカウントで投稿するようにしました。nuxx.noob.jp
qiita.com
主要部分のコード
# -*- coding: utf-8 -*- from slacker import Slacker import slackbot_settings as setting #アカウント情報 from datetime import datetime as dt from selenium.webdriver.support.ui import WebDriverWait from selenium import webdriver import cv2 import requests # botアカウントのトークンを指定 BOT_TOKEN = setting.API_TOKEN #別のファイルから読み込むようにしておくと間違ってアップロードする危険性が低くなる def main(): tdatetime = dt.now() time=tdatetime.strftime('%Y%m%d%H%M%S') browser = webdriver.PhantomJS() #url = "https://tenki.jp/radar/3/16/" #東京 url="https://tenki.jp/radar/2/5/" #青森 browser.get(url) print("get url") browser.save_screenshot("tmp.png") #スクリーンショット …① img = cv2.imread("tmp.png") #…② clp = img[320:980, 20:708] # [高さ, 幅] スライス #…③ file = "Pictures/weather" + time + ".png" cv2.imwrite(file, clp) x,y=274,355 #pxを取得する座標 #…④ dx,dy=15,15 #…⑤ B,G,R = clp[y,x,0],clp[y,x,1],clp[y,x,2] cv2.line(clp, (x-dx, y-dy), (x+dx, y-dy), (0, 0, 255), 2) #ファイル名,(始点x,y),(終点x,y),(color),太さ) cv2.line(clp, (x+dx, y-dy), (x+dx, y+dy), (0, 0, 255), 2) cv2.line(clp, (x+dx, y+dy), (x-dx, y+dy), (0, 0, 255), 2) cv2.line(clp, (x-dx, y+dy), (x-dx, y-dy), (0, 0, 255), 2) print("BGR= ") print(B, ",", G, ",", R) file = "Pictures/1weather"+time+".png" # …⑥ cv2.imwrite(file, clp) print("Time = "+time) if R<30 and B>190 : #…⑦ print("弱い雨") text ="少し雨が降ってるよ!" slacker.chat.post_message('general', 'テスト', as_user=True) #…⑧ slacker.files.upload(file, channels=['general'], title=text) elif R < 30 and B < 190 and G<150: print("やや強い雨") text ="かなり雨降ってるよ!!" slacker.chat.post_message('general', 'テスト', as_user=True) slacker.files.upload(file, channels=['general'], title=text) else: print("多分晴れ") text="多分晴れ"
Pythonでは
x,y=274,355 dx,dy=15,15
のような変数の代入の記法があります。視認性が高くていいですね。