曾經看過一個公民科學app的應用,那個app知悉你的位置之後,當有衛星通過你的上空拍下照片後,它會通知你,要你也往天空拍一張照片,然後就可以對照衛星圖和地面觀測的影像。
那麼我不如反過來做吧,就一直做地面觀測天空的攝影,然後再拿衛星圖來對照就好了啊。
先來看看成果。
這張組圖裡使用了中央氣象局的六種衛星觀測的產品,由左至右,由上而下分別是
真實色影像 紅外線雲圖-黑白 紅外線雲圖-彩色
紅外線雲圖-色調強化 可見光雲圖 雷達合成回波圖
最右邊則是地面觀測的照片
這樣組合可以觀察什麼資訊呢?
- 真實色:可以觀察珊瑚紅色表示的低雲(或霧區)、灰、白色系為雲頂較高的雲層(詳細說明)
- 色調強化:可以觀察雲頂的高度,藉此觀察對流系統的發展。顏色越綠等,代表雲頂溫度越低,也就是雲頂越高(詳細說明)
- 雷達回波:有顏色反應的訊號代表降水的強度,藉此可以知道哪邊在降雨(詳細說明)
- 紅外線黑白和可見光(直行第二排):兩張圖可以互相對照。可見光圖層可以看「雲的厚薄」,雲越厚就會越白。紅外線看的是「雲頂高度」,雲越高就會越冷,顏色就越白。
在可見光看的到雲,但紅外線看不到雲,就是有厚厚的雲,但是雲的高度很低,例如冬天北部的層狀雲。
在紅外線看得到雲,但可見光看不到雲,代表雲薄薄的,但是雲很高,那麼就是高空的卷雲、卷積雲等。(詳細說明)
搭配地面觀測的照片,就可以從原本只是平面的地面觀測照片獲得多維度的資訊,同時看到這片雲的高度、厚度或是降水。我上面組圖特別選這張,是因為地面觀測到一片橫過天空的雲,而在衛星觀測上就看到一段橫過新竹到宜蘭的雲,剛好能互相對照。
以下這支程式就是用FTP下載手機照片後,再上中央氣象局網站抓取衛星圖,做成組圖的程式。預設都是晚上天黑後我才會執行,這樣才能夠下載到當天白天的所有圖片。
不過目前有幾個部份我還沒修正,
1.每天10:40會停止觀測,所以會少那時間的衛星資料,但是我程式沒有去處理這個部份,所以執行到這個時間的衛星圖組圖時,就會跳錯誤
2.有些手機照片會有拍攝錯誤的狀況,如果遇到這種照片,也會跳錯誤。
3.有兩個地方要手動改時間,第一個是下載衛星圖的區塊,如這段是下載2019年1月4日上午4點開始的衛星圖,程式中設定了下載此天從4點到20點的衛星圖。所以如果手機拍攝了兩天才下載,手機照片就會有兩天的圖片,而衛星圖就要下載兩天份的,所以就要改下載日期再重新執行一次。(不過氣象局只能下載48小時內的衛星圖)
start = datetime.datetime(2019, 1, 4, 4, 0, 0) #下載日期
date = datetime.datetime(2019, 1, 4, 6, 0, 0)
以下是程式檔,我也同時放一份ipython notebook的在github
import subprocess import datetime
import ospath = "/home/shawn-pc/桌面/SkyAndsatellite/" if not os.path.isdir(path): #檢查資料夾是否存在 os.mkdir(path)
#從手機下載照片 from ftplib import FTP HOST = "192.168.1.116" PORT = 2221 pathFtp = "/opencamera" ftp = FTP() ftp.connect(HOST, PORT) ftp.login() ftp.cwd(pathFtp) filenames = ftp.nlst() for filename in filenames: if int(filename[13:15]) >=5 and int(filename[13:15]) <= 19: #下載在5點到20點的照片 dateFolder = filename[4:12] if not os.path.isdir(path + dateFolder+"/"): #檢查日期資料夾是否存在 os.mkdir(path + dateFolder+"/") if not os.path.isdir(path + dateFolder+"/"+"sky/"): #檢查日期資料夾裡的sky資料夾是否存在 os.mkdir(path + dateFolder+"/"+"sky/") local_filename = os.path.join(path + dateFolder+"/"+"sky/", filename) file = open(local_filename, 'wb') ftp.retrbinary('RETR '+ filename, file.write) print("download "+filename) file.close() ftp.delete(filename) ftp.quit()
#下載衛星圖,先建立日期資料夾 import time start = datetime.datetime(2019, 1, 4, 4, 0, 0) #下載日期 pathDay = start.strftime(path+"%Y%m%d/") if not os.path.isdir(pathDay): os.mkdir(pathDay) print(pathDay) #從cwb下載衛星圖 import requests imgurl = "https://www.cwb.gov.tw/V7/observe/satellite/Data/{}/{}-{}.jpg" def getImage(mapType): date = start pathSateType = pathDay + mapType +"/" if not os.path.isdir(pathSateType): os.mkdir(pathSateType) for i in range(6*(20-5)): mapTime = date.strftime("%Y-%m-%d-%H-%M") fname = mapType+"-"+mapTime+".jpg" with open(pathSateType+fname,'wb') as f: res = requests.get(imgurl.format(mapType,mapType,mapTime)) f.write(res.content) date = date + datetime.timedelta(minutes = 10) getImage("sbo") #可見光 getImage("s3p") #紅外線雲圖彩色 getImage("s3o") #紅外線雲圖黑白 getImage("s3q") #色調強化 getImage("ts3p") #真實影像色彩 ##下載雷達回波圖 radarUrl = "https://www.cwb.gov.tw/V7/observe/radar/Data/HD_Radar/CV1_TW_3600_{}.png" def getRadar(date): pathRadar = pathDay + "radar/" if not os.path.isdir(pathRadar): os.mkdir(pathRadar) for i in range(6*(20-5)): mapTime = date.strftime("%Y%m%d%H%M") fname = "radar" + "-" + date.strftime("%Y-%m-%d-%H-%M") + ".png" with open(pathRadar+fname,'wb') as f: res = requests.get(radarUrl.format(mapTime)) f.write(res.content) date = date + datetime.timedelta(minutes = 10) getRadar(date) #下載雷達回波
#製作組圖 from PIL import Image, ImageDraw, ImageFont import re """檢查照片檔案是否存在""" def is_jpg(filename): try: i=Image.open(filename) return i.format =='JPEG' except IOError: return False except FileNotFoundError: return False """取得衛星照片的路徑""" def getMapPath(mapType,date): fname = mapType + date.strftime("-%Y-%m-%d-%H-%M.jpg") path = pathDay + mapType + "/" + fname return path def getRadarPath(date): fname = "radar" + date.strftime("-%Y-%m-%d-%H-%M.png") path = pathDay + "radar" + "/" + fname return path """取得天空拍照的照片路徑""" def getSkyPath(date): imgNamePre =date.strftime("IMG_%Y%m%d_%H%M") for fname in os.listdir(pathDay + "sky/"): if re.match(imgNamePre+"\d+.jpeg", fname): return pathDay + "sky/" +fname ##製作組圖 def create_collage(width, height, listofimages, sky): cols = 4 rows = 2 thumbnail_width = width//cols thumbnail_height = height//rows size = thumbnail_width, thumbnail_height new_im = Image.new('RGB', (width, height)) ims = [] for p in listofimages: im = Image.open(p) im.thumbnail(size) ims.append(im) i = 0 x = 0 y = 0 for col in range(cols): for row in range(rows): if i < len(ims): print(i, x, y) new_im.paste(ims[i], (x, y)) i += 1 y += thumbnail_height x += thumbnail_width y = 0 #把天空攝影放在最右邊的欄 imSky = Image.open(sky) area = (416,4,416+1060,4+3076) #切割天空 imSky = imSky.crop(area) sizeSky = thumbnail_width , height imSky.thumbnail(sizeSky) x = thumbnail_width * 3 new_im.paste(imSky, (x, 0)) new_im.save(date.strftime(pathDay+"%Y%m%d%H%M.jpg")) #new_im.show() date = datetime.datetime(2019, 1, 4, 6, 0, 0)pathDay = date.strftime(path+"%Y%m%d/")for i in range(90): s3o = getMapPath("s3o",date) s3p = getMapPath("s3p",date) s3q = getMapPath("s3q",date) sbo = getMapPath("sbo",date) ts3p = getMapPath("ts3p",date) radar = getRadarPath(date) sky = getSkyPath(date) #檢查路徑是否存在,如果存在才進行下一步 #how? listofimages=[ts3p,s3q,s3o,sbo,s3p,radar] create_collage(2000, 1000, listofimages,sky) date = date + datetime.timedelta(minutes = 10)