基于AIE的贵阳市冷热岛效应分析

基于 Landsat-8 数据进行贵阳市冷热岛分析

初始化环境

import aie

aie.Authenticate()
aie.Initialize()

Landsat-8 数据检索

指定区域、时间、云量检索 Landsat-8 ,并对数据进行去云处理。

region = aie.FeatureCollection('China_City') \
            .filter(aie.Filter.eq('city', '贵阳市')) \
            .geometry()
dataset = aie.ImageCollection('LANDSAT_LC08_C02_T1_L2') \
             .filterBounds(region) \
             .filterDate('2021-05-01', '2021-10-1') \
             .filter(aie.Filter.lte('eo:cloud_cover', 30.0))

print(dataset.size().getInfo())

Landsat-8 数据去云

def removeLandsatCloud(image):
    cloudShadowBitMask = (1 << 4)
    cloudsBitMask = (1 << 3)
    qa = image.select('QA_PIXEL')
    mask = qa.bitwiseAnd(aie.Image(cloudShadowBitMask)).eq(aie.Image(0)).And(qa.bitwiseAnd(aie.Image(cloudsBitMask)).eq(aie.Image(0)))
    return image.updateMask(mask)
# median运算
image = dataset.median()
# clip裁剪
image = image.clip(region)
# 去云
# 去云会造成数据缺失,所以我这里不去云了
# image = removeLandsatCloud(image)
  
map = aie.Map(
    center=image.getCenter(),
    height=800,
    zoom=7
)
rgb_params = {
    'bands': ['SR_B4', 'SR_B3', 'SR_B2'],
    'min': 8000,
    'max': 13000
}
map.addLayer(
    image,
    rgb_params,
    'raw_img',
    bounds = image.getBounds()
)
map

计算 NDVI

ndvi计算 NIR-R/NIR+R

ndvi = image.normalizedDifference(['SR_B5', 'SR_B4']).rename(['NDVI'])
ndvi_params = {
    'min': 0,
    'max': 1.0,
    'palette': [
        '#FFFFFF', '#CE7E45', '#DF923D', '#F1B555', '#FCD163', '#99B718', '#74A901',
        '#66A000', '#529400', '#3E8601', '#207401', '#056201', '#004C00', '#023B01',
        '#012E01', '#011D01', '#011301'
    ]
}

map.addLayer(
    ndvi,
    ndvi_params,
    'NDVI',
    bounds = image.getBounds()
)
map
贵阳市ndvi分布图
task = aie.Export.image.toAsset(ndvi,'guiyang_ndvi',50)
task.start()

计算 Fractional Vegetation

植被覆盖度计算 NDVI-NDVI_min / NDVI_max-NDVI_min

import numpy as np

scale = 1000

histogram = ndvi.reduceRegion(aie.Reducer.histogram(2000), None, scale)
histogram_info = histogram.getInfo()
# print(histogram_info)


bucketKey = histogram_info['NDVI_range']
bucketValue = histogram_info['NDVI_counts']

key = np.array(bucketValue)
accSum = np.cumsum(key)
# print(accSum[20])
# print(accSum[-1])
accPercent = accSum / accSum[-1]
    
p2 = np.searchsorted(accPercent, 0.2)

min_ndvi = bucketKey[p2 + 1]
print('min_ndvi:%f' % min_ndvi)

p98 = np.searchsorted(accPercent, 0.98)
max_ndvi = bucketKey[p98]
print('max_ndvi:%f' % max_ndvi)
ndvi
min = aie.Image(min_ndvi)
max = aie.Image(max_ndvi)
fv = ndvi.where(ndvi.lt(min),aie.Image(0))\
           .where(ndvi.gt(max),aie.Image(1))\
           .where(ndvi.gt(min).And(ndvi.lt(max)),\
           ndvi.subtract(min).divide(max.subtract(min)))\
           .rename(['FV'])
fv_params = {
    'min': 0,
    'max': 1
}
map.addLayer(
    fv,
    fv_params,
    'fv',
    bounds = image.getBounds()
)
map

计算比辐射率 Emissivity

em = ndvi.where(ndvi.lte(aie.Image(0.2)),aie.Image(0.995))\
           .where(ndvi.gt(aie.Image(0.2)).And(ndvi.lt(aie.Image(0.4))),\
                  aie.Image(0.9589).add((aie.Image(0.086)).multiply(fv))\
                  .subtract(aie.Image(0.0617).multiply(fv).pow(aie.Image(2))))\
           .where(ndvi.gte(aie.Image(0.4)),aie.Image(0.9625).add(aie.Image(0.0614))\
                  .multiply(fv).subtract(aie.Image(0.0461)).multiply(fv).pow(aie.Image(2)))\
           .rename(['EM'])
scale = 1000

histogram = em.reduceRegion(aie.Reducer.mean())
histogram_info = histogram.getInfo()
print(histogram_info)
histogram = em.reduceRegion(aie.Reducer.max())
histogram_info = histogram.getInfo()
print(histogram_info)
histogram = em.reduceRegion(aie.Reducer.min())
histogram_info = histogram.getInfo()
print(histogram_info)
EM

计算 Thermal

同温黑体辐射亮度计算

th = image.select('ST_B10').multiply(aie.Image(0.00341802)).add(aie.Image(149)).rename(['TH'])
scale = 1000

histogram = th.reduceRegion(aie.Reducer.mean())
histogram_info = histogram.getInfo()
print(histogram_info)
histogram = th.reduceRegion(aie.Reducer.max())
histogram_info = histogram.getInfo()
print(histogram_info)
histogram = th.reduceRegion(aie.Reducer.min())
histogram_info = histogram.getInfo()
print(histogram_info)
Thermal范围
th_params = {
    'min': 240,
    'max': 330,
    'palette': [
        '#0000FF', '#FFFFFF', '#008000'
    ]
}
map.addLayer(
    th,
    th_params,
    'thermal',
    bounds = image.getBounds()
)
map

计算地表温度 ( LST )

tb = th.select(['TH'])
eb = em.select(['EM'])

lst = tb.divide(tb.multiply(aie.Image(0.00115)).divide(aie.Image(1.4388)).multiply(eb.log())\
                  .add(aie.Image(1))).subtract(aie.Image(273)).rename(['LST'])
scale = 1000

histogram = lst.reduceRegion(aie.Reducer.mean())
histogram_info = histogram.getInfo()
print(histogram_info)
histogram = lst.reduceRegion(aie.Reducer.max())
histogram_info = histogram.getInfo()
print(histogram_info)
histogram = lst.reduceRegion(aie.Reducer.min())
histogram_info = histogram.getInfo()
print(histogram_info)

histogram = lst.reduceRegion(aie.Reducer.histogram(2000), None, scale)
histogram_info = histogram.getInfo()
# print(histogram_info)
bucketKey = histogram_info['LST_range']
bucketValue = histogram_info['LST_counts']

key = np.array(bucketValue)
accSum = np.cumsum(key)
# print(accSum[20])
# print(accSum[-1])
accPercent = accSum / accSum[-1]
    
p1 = np.searchsorted(accPercent, 0.01)

min_lst = bucketKey[p1 + 1]
print('min_LST:%f' % min_lst)

p99 = np.searchsorted(accPercent, 0.99)
max_lst = bucketKey[p99]
print('max_LST:%f' % max_lst)
lst范围

消除lst噪点

用1%和99%消除噪点

# 消除噪点,用1%和99.9%消除噪点
lst = lst.where(lst.lte(aie.Image(10)),aie.Image(10))\
           .where(lst.gt(aie.Image(10)).And(ndvi.lt(aie.Image(44))),lst)\
           .where(lst.gte(aie.Image(44)),aie.Image(44))
lst_params = {
    'min': 10,
    'max': 45,
    'palette': ['#040274', '#040281', '#0502a3', '#0502b8', '#0502ce', '#0502e6',
                '#0602ff', '#235cb1', '#307ef3', '#269db1', '#30c8e2', '#32d3ef',
                '#3be285', '#3ff38f', '#86e26f', '#3ae237', '#b5e22e', '#d6e21f',
                '#fff705', '#ffd611', '#ffb613', '#ff8b13', '#ff6e08', '#ff500d',
                '#ff0000', '#de0101', '#c21301', '#a71001', '#911003']
}

map.addLayer(
    lst,
    lst_params,
    'lst',
    bounds = image.getBounds()
)
map
贵阳市地表温度结果
task = aie.Export.image.toAsset(lst,'lst',50)
task.start()

城市冷热岛分析

城市冷岛分析


scale = 1000

histogram = lst.reduceRegion(aie.Reducer.mean())
histogram_info = histogram.getInfo()
print(histogram_info)
mean_lst =  aie.Image(histogram_info.get('LST_mean'))

# subtract运算
uci =  lst.subtract(mean_lst)

# lst二分类,将lst小于0的区域设置为1,将lst大于0的区域设置为nodata
uci_extent = lst.where(lst.lte(mean_lst),aie.Image(1))\
           .where(lst.gt(mean_lst),aie.Image(0))


uci_final = lst.where(lst.lte(mean_lst),uci)\
           .where(lst.gt(mean_lst),aie.Image(0))

task = aie.Export.image.toAsset(uci_final,'guiyang_uci_final',50)
task.start()

mask_vis  = {
    'min': 0,
    'max': 1,
    'palette': ['#ffffff', '#0000cd']    # 0:白色, 1:蓝色
}

map.addLayer(uci_extent,mask_vis, 'uci_extent', bounds=region.getBounds())    # 蓝色区域为冷岛

冷岛
histogram = uci_final.reduceRegion(aie.Reducer.min())
histogram_info = histogram.getInfo()
print(histogram_info)
冷岛强度分布图

城市热岛分析

tr =  lst.subtract(mean_lst).divide(mean_lst)
# lst二分类,将lst小于0的区域设置为1,将lst大于0的区域设置为nodata
uhi_extent = tr.where(tr.lt(aie.Image(0)),aie.Image(0))\
               .where(tr.gt(aie.Image(0)),aie.Image(1))
mask_vis  = {
    'min': 0,
    'max': 1,
    'palette': ['#ffffff', '#ff7070']    # 0:白色, 1:红色
}


map.addLayer(uhi_extent,mask_vis, 'uhi_extent', bounds=region.getBounds())    # 红色区域为热岛
热岛
uhi_final = uhi_extent.multiply(tr)
task = aie.Export.image.toAsset(tr,'guiyang_uhi_final',50)
task.start()
uhi_params  = {
    'min': 0.1,
    'max': 0.8,
    'palette': ['#fff705', '#ffd611', '#ffb613', '#ff8b13', '#ff6e08', '#ff500d',
                '#ff0000', '#de0101', '#c21301', '#a71001', '#911003']
}


map.addLayer(uhi_final,uhi_params, 'uhi_final', bounds=region.getBounds())
热岛强度图

总结

总的来说,这个不难,难在精准,难在精准的地表温度反演,比如我遇到的异常值问题,需要去除噪点。还有就是阿里云的小哥哥们很热心,也多亏他们的帮助,当然我这个地表温度反演做的比较简单,也不是很准确,希望大家有更加准确的算法。这个实验还是比较好的拟合了贵阳市的实际,也说明AIE可以很好的使用。
本文主要引用了AIE的官方案例,《城市与区域规划空间分析实验教程》的实验19,还有网络上使用ENVI利用landsat8数据进行地表温度反演的例子。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352

推荐阅读更多精彩内容