赏枫,实在是秋季亲近自然的一大妙方。
在规划赏枫行程的时候(没错,我们J人就是这么喜欢规划),我却遇到了一个问题:“我怎么知道哪里适合赏枫?”最简单的方法当然是出行前看下小红书,判断是否适合赏枫,但如果提前一个星期多进行规划就不方便了(是的我们J人就是喜欢超前规划)。而且,也不是所有地方都会有人发枫叶状况,这该怎么办呢?
巧的很,我现在学的是遥感方向,那就找点遥感图像看看呗。
尝试(With GPT5)
虽说我是遥感方向,但是我本科完全不懂遥感啊,顶天了解CV相关的语意分割、目标检测啥的。所以我问了下GPT该怎么衡量该区域是否要落叶了,他给出的回答是 NDVI在0.3~0.5 之间 一般是落叶区域。我在 Copernicus Data Space Browser 中使用 Sentinel-2 拍摄的实时数据进行分析,发现城市区域造成的视觉干扰很大:
于是我使用 SCL 并mask掉了城市区域。此外,我还将NDVI0.3~0.5区域标红。
//VERSION=3function setup() { return { input: ["B04", "B08", "SCL", "dataMask"],57 collapsed lines
output: [ { id: "default", bands: 4 }, { id: "index", bands: 1, sampleType: "FLOAT32" }, { id: "eobrowserStats", bands: 2, sampleType: "FLOAT32" }, { id: "dataMask", bands: 1 } ] };}
// 参数:根据需要微调这三个阈值const NDVI_MIN = 0.25; // 低于此值基本认为非有效植被(透明)const FALL_LO = 0.30; // 落叶/变色窗口下界(偏黄)const FALL_HI = 0.55; // 落叶/变色窗口上界(偏红)
function isVegetation(scl) { return scl === 4; // SCL=4: Vegetation}
function lerp(a,b,t){ return a + (b-a)*t; }function clamp01(x){ return Math.max(0, Math.min(1, x)); }
function evaluatePixel(s) { const ndvi = (s.B08 - s.B04) / (s.B08 + s.B04); const veg = isVegetation(s.SCL) && s.dataMask === 1;
// 非植被或无效像素:透明 if (!veg || ndvi < NDVI_MIN) { return { default: [0,0,0,0], index: [NaN], eobrowserStats: [0,0], dataMask: [0] }; }
let rgba;
if (ndvi >= FALL_LO && ndvi <= FALL_HI) { // 在“变色窗口”内:黄(#FFC800) → 红(#FF0000) 渐变 const t = clamp01((ndvi - FALL_LO) / (FALL_HI - FALL_LO)); // 0..1 const r = lerp(1.00, 1.00, t); const g = lerp(0.78, 0.00, t); const b = lerp(0.00, 0.00, t); rgba = [r, g, b, 1]; // 高亮标红 } else if (ndvi > FALL_HI) { // 常绿/高NDVI:降饱和的深绿,避免喧宾夺主 const g = clamp01((ndvi - FALL_HI) / (0.85 - FALL_HI)); // 0..1 rgba = [0.05, 0.25 + 0.5*g, 0.08, 0.9]; } else { // 介于 NDVI_MIN 和 FALL_LO:稀疏植被,弱黄棕 rgba = [0.75, 0.65, 0.35, 0.9]; }
return { default: rgba, index: [ndvi], eobrowserStats: [ndvi, 0], dataMask: [1] };}效果如下:
但是,这只是落叶区域啊?
我该怎么判断枫树在哪里😨?
“在最近NDVI大幅变化的大概率是阔叶林。”GPT如是说。
//VERSION=3function setup() {50 collapsed lines
return { input: ["B04","B08","SCL","dataMask"], output: [{ id:"default", bands:4 }], mosaicking: "ORBIT" // 允许多时相 };}
// ---- 参数可调 ----const NDVI_MIN = 0.25; // 植被下限(低于则透明)const DROP_LO = 0.05; // 认为“开始变色”的NDVI下降阈值const DROP_HI = 0.25; // 强变色上限(越接近越红)const CLOUDS = new Set([7,8,9,10]); // SCL 云类(排除)
function ndvi(s){ return (s.B08 - s.B04) / (s.B08 + s.B04); }function clamp01(x){ return Math.max(0, Math.min(1, x)); }
function goodVeg(s){ return s.dataMask === 1 && s.SCL === 4; // 仅植被}function notCloud(s){ return !CLOUDS.has(s.SCL); }
function evaluatePixel(samples, scenes) { if (samples.length < 2) return [0,0,0,0];
// 约定:samples[0] 较新,samples[samples.length-1] 较早 const sNew = samples[0]; const sOld = samples[samples.length-1];
// 基本质量控制:两期都得是植被且非云 if (!(goodVeg(sNew) && goodVeg(sOld) && notCloud(sNew) && notCloud(sOld))) { return [0,0,0,0]; }
const nNew = ndvi(sNew); const nOld = ndvi(sOld); if (nNew < NDVI_MIN && nOld < NDVI_MIN) return [0,0,0,0];
const drop = nOld - nNew; // NDVI 下降为正值 = 疑似变色/落叶 if (drop >= DROP_LO) { // 黄(#FFC800) -> 红(#FF0000) 渐变 const t = clamp01((drop - DROP_LO) / (DROP_HI - DROP_LO)); const r = 1.0; const g = 0.78*(1.0 - t); // 0.78 -> 0 const b = 0.0; return [r, g, b, 1.0]; } else { // 变化不大:用低饱和绿显示“仍然茂盛的林地” // 这样红色区域会非常醒目 const g = clamp01((nNew - NDVI_MIN) / (0.85 - NDVI_MIN)); return [0.05, 0.25 + 0.5*g, 0.08, 0.6]; }}但是田也会被标出来,就先这样吧。如果把两张图叠加,或许能筛选出高概率红的枫叶林:
gallery 效果如下


小红书上云观景了一下 和统计结果差不多 没有太多红的地方。
结果最后决定爬山去了。