GEE | OTSU 算法简单提取水体

文摘   2024-07-16 00:00   山西  

LXX

读完需要

2
分钟

速读仅需 1 分钟

前言:

我国洪涝、干旱灾害和水资源短缺等水问题突出,地面监测系统目前还不能实现全面覆盖。各种遥感卫星具有全天候全天时对地观测能力,可以不分昼夜、阴雨天气进行对地观测。针对洪涝灾害监测、水资源管理等水利应用需求,实现水体的自动化提取,可以补充地面监测能力的不足,在提升水利监测能力方面发挥重要作用。本文简单分享通过 OTSU 算法进行水体提取。


1

   

水体提取方法

常用的水体提取技术包括目视解译、监督分类、纹理特征分析、动态轮廓模型、阈值分割等。阈值分割法是应用最为广泛的水体提取方法,其原理是设定阈值分割雷达影像,将图像中小于阈值部分标记为水体,大于阈值部分标记为背景,获得水体范围二值图。该方法易于实现,速度快,但难点在于阈值的确定。最直接的方式是通过人机交互的方式选取阈值,但当处理大批量数据时效率低下,并且获取的结果主观性强,可追踪性差。针对人机交互阈值选取方法上的不便,自动化阈值选取方法被应用到水体提取算法中。常用的自动阈值分割选取方法有双峰法、OTSU 方法、最大熵阈值法和最小误差阈值法。

2

   

OTSU 算法

在图像分析中,我们经常需要一种自动的、数据驱动的方法来区分两种相对同质的事物,例如土地与水、森林与草或前景与背景。对于具有双峰像素分布的单波段图像,可以通过找到将两个类别分开的单个阈值来执行两类分割。

最大类间方差法(又名otsu、大津法)是由日本学者OTSU于1979年提出的一种对图像进行二值化的高效算法。算法假定该图像根据频率分布直方图把包含两类像元(前景像元和背景像元),计算能将两类分开的最佳阈值,使得它们的类内方差最小;由于两两平方距离恒定,所以即它们的类间方差最大。
优点:计算简单快速,不受图像亮度和对比度的影响。
缺点:对图像噪声敏感;如果图像中的前景像元和背景像元的面积相差很大,直方图没有明显的双峰,或者两个峰的大小相差很大,分割效果不佳。实际应用中,常结合其他方法。
原理:大津法借助穷举法搜索能使类内方差最小的阈值,计算两个类的方差的加权和,权值为两类各自的概率,前人证明了最小化类内方差和最大化类间方差是相同的。图像的总平均灰度为:M=P1(t) * M0 + P2(t) * M1前景与背景像元类间方差:S=P1(t) * (M1 - M) * (M1 - M) + P2(t) * (M2 - M) * (M2 - M)。t为前景与背景的分割阈值,前景像元占图像比例为P1(t),平均灰度为M1;背景像元占图像比例为P2(t),平均灰度为M1。

(OTSU 是一种阈值分割方法,前提是要计算出 MDWI 等水体指数,再对水体指数灰度图像进行最优阈值分割(方法 1 是直接人为设定一个阈值)。

由于不同水质和光照条件下,水体的 NDWI 值不尽相同,准确识别水体边界还需要对 NDWI 灰度影像图进行二值化分割。Otsu 算法(Otsu, 1979)是根据影像分割信息的最大类间方差来计算分割阈值,可以最大程度上区分出水体与非水体信息。)


3

   

实现代码

var cor = [  [44.89140339357055,37.09921636762552],  [46.05595417482055,37.09921636762552],  [46.05595417482055,38.354790162350284],  [44.89140339357055,38.354790162350284],  [44.89140339357055,37.09921636762552]  ]
var roi = ee.Geometry.Polygon(cor)
Map.centerObject(roi);Map.addLayer(roi)
//调用modis表面反射图像
var modis = ee.ImageCollection("MODIS/061/MOD09A1").filterDate('2001','2023').map(function(img){ var bands = img.select('sur_refl.*').multiply(0.0001); var ndwi = bands.normalizedDifference(['sur_refl_b04','sur_refl_b02']).rename('ndwi'); return ndwi .copyProperties(img, img.propertyNames()) }); Map.addLayer(modis.median().clip(roi),[],'modis',false);
print( ui.Chart.image.histogram(modis.median(),roi,500) )
//otsu函数求阈值
var oeel=require('users/image');
var otsu = oeel.ImageCollection.OtsuThreshold(modis, 'ndwi');
print( ui.Chart.image.histogram(otsu,roi,500) ) var thr = ee.Number(otsu.reduceRegion({ reducer: ee.Reducer.mean(), geometry: roi, scale: 500 }).values().get(0)); print('water body threshold',thr)

var ndwis = modis.filterDate('2020','2021').toBands().gt(thr);
Map.addLayer(ndwis.clip(roi),[],'ndwi_thr',false)


遥感小屋
分享遥感相关文章、代码,大家一起交流,互帮互助
 最新文章