针对某同学提出的“逐日下载水体提取结果(MNDWI结合Otsu算法)”需求,本文提出一种基于Google Earth Engine(GEE)平台的解决方案。考虑到逐日监测对数据连续性的高要求(光学影像易受云遮挡影响),采用Sentinel-1雷达影像作为数据源,结合Otsu阈值分割算法实现水体提取,并通过编程实现结果的自动化导出。该方法的核心逻辑可迁移至MNDWI数据处理中,为相关研究提供技术参考。(大家可以继续提一些想学的内容,大家互相交流,也请大家可以的话推荐推荐 我的公众号给需要的人。)
方法选择依据
数据源选择:Sentinel-1雷达影像的优势
在逐日水体监测中,数据源的时间连续性和稳定性是关键约束条件。Sentinel-1系列合成孔径雷达(SAR)影像具有以下优势:
- 全天时全天候观测能力:不受云层、降水及昼夜条件影响,可稳定获取数据,避免光学影像因云污染导致的有效数据缺失问题;
- 较高时间分辨率:通过Sentinel-1A与1B双星组网,可实现6天的重访周期,配合时间缓冲策略能满足逐日提取需求;
- 水体敏感性:VV极化模式下,水体因表面平滑表现为低后向散射特征,与非水体地物(如植被、建设用地)的灰度差异显著,便于后续分割。
分割算法:Otsu阈值法的适用性
Otsu算法(大津法)作为一种自适应阈值分割方法,无需人工设定阈值,其核心原理是通过最大化类间方差确定最优分割阈值,可有效区分水体与非水体地物。该算法对SAR影像的灰度分布特征适应性较强,能减少因区域差异或时间变化导致的阈值调整成本,适合批量自动化处理。
技术流程与实现代码
1. 基础参数设置
定义研究区范围与时间区间,作为后续数据处理的基础约束条件:
// 研究区定义(替换为目标区域矢量边界)
var roi = ee.FeatureCollection("projects/ee-hllutlu2024/assets/baoding_xian");
Map.centerObject(roi, 9); // 地图定位至研究区
// 时间范围设置(根据研究需求调整)
var startDate = '2023-12-02';
var endDate = '2023-12-04';
2. Sentinel-1影像获取与预处理
为解决单日影像缺失问题,设计时间缓冲机制获取目标日期前后2天内的可用影像,并进行降噪处理:
2.1 影像筛选函数
function getS1(date) {
// 构建目标日期±2天的时间窗口,提高数据获取成功率
var start = ee.Date(date).advance(-2, 'day');
var end = ee.Date(date).advance(2, 'day');
// 筛选符合条件的影像
var col = ee.ImageCollection('COPERNICUS/S1_GRD')
.filterBounds(roi) // 空间范围过滤
.filterDate(start, end) // 时间范围过滤
.filter(ee.Filter.eq('orbitProperties_pass', 'ASCENDING')) // 升轨影像(可根据研究区调整)
.filter(ee.Filter.listContains('transmitterReceiverPolarisation', 'VV')) // 保留VV极化
.sort('system:time_start'); // 按时间排序
return col.first(); // 返回时间最早的可用影像
}
2.2 影像降噪处理
SAR影像存在斑点噪声,需通过滤波消除以提高后续分割精度:
// 以单日影像为例:裁剪与降噪
var img = getS1(currentDate); // currentDate为循环中的单日日期
var vv = img.select('VV').focal_median(20, 'circle', 'meters').clip(roi); // 首次滤波去除大噪声
var vv_denoised = vv.focal_median(15, 'circle', 'meters'); // 二次滤波平滑影像
3. Otsu阈值分割算法实现
基于影像灰度直方图特征,通过Otsu算法计算最优分割阈值,实现水体与非水体的自动区分:
3.1 Otsu算法核心函数
function otsu(histogram) {
var counts = ee.Array(histogram.get('histogram')); // 灰度值频数数组
var means = ee.Array(histogram.get('bucketMeans')); // 灰度值中心数组
var size = means.length().get([0]); // 灰度级数量
var total = counts.reduce('sum', [0]).get([0]); // 总像素数
var sum = means.multiply(counts).reduce('sum', [0]).get([0]); // 灰度值总和
var mean = sum.divide(total); // 总均值
// 计算各类间方差并确定最优阈值
var between = ee.List.sequence(1, size).map(function(i) {
i = ee.Number(i);
// 计算两类权重
var w0 = counts.slice(0, 0, i).reduce('sum',

最低0.47元/天 解锁文章
155

被折叠的 条评论
为什么被折叠?



