赏枫,实在是秋季亲近自然的一大妙方。
在规划赏枫行程的时候(没错,我们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 效果如下


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