2025年5月27日

利用 Google Earth Engine 查看 NDVI 歷史變化

 最近教到群集的消長變化時,突然想到可以用Google Earth Engine來做NDVI的分析。

以前做這個東西,真的花很多時間,但是現在AI協作,幫忙在GGE平台上寫程式,一下就可以做出來了。

這是程式連結

NDVI(Normalized Difference Vegetation Index,正規化植生指數)是最常被用來評估綠意程度的指標之一。

NDVI 是由衛星量測紅光(Red)與近紅外光(NIR)反射率計算而來的簡單比值,用來表示地表上綠色植物的生長情況。

它是衡量植物生長狀況的指標,根據植被對近紅外光與紅光的反射特性計算而得。指數值範圍從 -1 到 1,數值越高代表綠意越旺盛,常用來分析森林覆蓋變化、農作物生長週期,甚至是氣候變遷影響。


NDVI = (NIR - RED) / (NIR + RED)

NDVI 越高,代表綠色植物越茂盛。

一般數值範圍是 -1 到 1(實際上通常落在 0 ~ 0.8)。

例如:

NDVI ≈ 0.6:森林或健康農作物

NDVI ≈ 0.2:草地或乾燥灌木

NDVI ≈ 0.0 或負值:裸土、城市、雲、積雪或水體

這段程式使用的衛星資料來自MODIS。MODIS 是美國 NASA Terra 與 Aqua 衛星搭載的儀器,從 2000 年起每天環繞地球,觀察大氣、海洋與陸地變化。MOD13Q1 是 MODIS 的 NDVI 資料產品,每 16 天提供一次雲遮減少、經過處理的高品質 NDVI 值,解析度約為 250 公尺。


在這程式上使用者只需要:

  1. 在地圖上圈選感興趣的區域(例如一塊山坡地或農田)
  2. 選擇想查看的時間範圍(例如 2015 到 2024 年)
  3. 選擇時間(年、季、月,依照需求)


系統會自動下載 MODIS NDVI 影像、進行正規化、計算區域平均值,並畫出時間變化圖表。還可以透過滑桿查看每一張影像的空間分布。

可以做哪些應用?

森林變化監測:觀察保護區十年來 NDVI 是否穩定?是否有非法砍伐跡象?
農業分析:農田的 NDVI 是否逐年穩定?是否有氣候影響?
都市擴張:城市邊緣 NDVI 是否逐年下降,代表綠地消失?
生態恢復追蹤:林火或颱風後,NDVI 是否逐年回升?


下圖就是十八尖山區域的NDVI變化


以下是操作的影片說明



--
程式內容

// ===[ 1. 使用者設定區塊 ]===
var config = {
  startYear: 2000,
  endYear: 2024,
  scale: 250, // MODIS 的空間解析度
  timeScale: 'yearly' // 可選:'yearly', 'quarterly', 'monthly', 'original'
};

// ===[ 2. 幾何區域:使用你畫的範圍 ]===
Map.centerObject(geometry, 12);  // geometry 為互動選取區域
Map.addLayer(geometry, {color: 'red'}, '分析範圍');

// ===[ 3. 載入 MODIS NDVI 並正規化 ]===
var modis = ee.ImageCollection("MODIS/006/MOD13Q1")
  .filterBounds(geometry)
  .filterDate(config.startYear + '-01-01', config.endYear + '-12-31')
  .select('NDVI');

var scaled = modis.map(function(img) {
  return img.multiply(0.0001)
            .copyProperties(img, ['system:time_start']);
});

// ===[ 4. 時間尺度函式 ]===
var timeReduced;
if (config.timeScale === 'yearly') {
  var years = ee.List.sequence(config.startYear, config.endYear);
  timeReduced = ee.ImageCollection.fromImages(
    years.map(function(y) {
      var start = ee.Date.fromYMD(y, 1, 1);
      var end = ee.Date.fromYMD(y, 12, 31);
      return scaled.filterDate(start, end).mean()
        .set('system:time_start', start.millis())
        .set('label', y.toString());
    })
  );
} else if (config.timeScale === 'quarterly') {
  var quarters = ee.List.sequence(0, ee.Number(config.endYear).subtract(config.startYear).multiply(4).subtract(1));
  timeReduced = ee.ImageCollection.fromImages(
    quarters.map(function(q) {
      var start = ee.Date(config.startYear + '-01-01').advance(q, 'quarter');
      var end = start.advance(1, 'quarter');
      return scaled.filterDate(start, end).mean()
        .set('system:time_start', start.millis())
        .set('label', start.format('YYYY Q'));
    })
  );
} else if (config.timeScale === 'monthly') {
  var months = ee.List.sequence(0, ee.Date(config.endYear + '-12-01').difference(ee.Date(config.startYear + '-01-01'), 'month').subtract(1));
  timeReduced = ee.ImageCollection.fromImages(
    months.map(function(m) {
      var start = ee.Date(config.startYear + '-01-01').advance(m, 'month');
      var end = start.advance(1, 'month');
      return scaled.filterDate(start, end).mean()
        .set('system:time_start', start.millis())
        .set('label', start.format('YYYY-MM'));
    })
  );
} else if (config.timeScale === 'original') {
  timeReduced = scaled;
} else {
  throw new Error('Unsupported timeScale: ' + config.timeScale);
}

// ===[ 5. 繪製圖表 ]===
var chart = ui.Chart.image.series({
  imageCollection: timeReduced.select('NDVI'),
  region: geometry,
  reducer: ee.Reducer.mean(),
  scale: config.scale,
  xProperty: 'system:time_start'
}).setOptions({
  title: 'NDVI 時間序列變化(' + config.timeScale + ')',
  hAxis: {title: '時間'},
  vAxis: {title: 'NDVI(正規化)'},
  lineWidth: 2,
  pointSize: 3
});
print(chart);

// ===[ 6. 顯示最新 NDVI 圖層 ]===
var latest = timeReduced.sort('system:time_start', false).first();
Map.addLayer(latest, {min: 0, max: 1, palette: ['white', 'green']}, '最新 NDVI (' + config.timeScale + ')');
// ===[ 7. 滑桿與時間標籤 UI ]===
var timeLabels = timeReduced.aggregate_array('label').getInfo();

// 建立時間標籤
var dateLabel = ui.Label('日期:' + timeLabels[timeLabels.length - 1]);

// 建立滑桿控制時間點
var slider = ui.Slider({
  min: 0,
  max: timeLabels.length - 1,
  step: 1,
  value: timeLabels.length - 1,
  style: {width: '400px'}
});

// 初始圖層
var currentImage = ee.Image(timeReduced.toList(timeReduced.size()).get(timeLabels.length - 1));
var currentLayer = ui.Map.Layer(currentImage, {min:0, max:1, palette:['white','green']}, 'NDVI ' + timeLabels[timeLabels.length - 1]);
Map.layers().set(0, currentLayer);

// 當滑桿變動時更新圖層與時間標籤
slider.onChange(function(index) {
  var label = timeLabels[index];
  dateLabel.setValue('日期:' + label);
  var img = ee.Image(timeReduced.toList(timeReduced.size()).get(index));
  Map.layers().set(0, ui.Map.Layer(img, {min:0, max:1, palette:['white','green']}, 'NDVI ' + label));
});

// 加入 UI 元件(先建立一個 panel)
var panel = ui.Panel({
  widgets: [dateLabel, slider],
  layout: ui.Panel.Layout.flow('vertical'),
  style: {position: 'bottom-left'}
});
Map.add(panel);

2025年5月24日

讓科展報告說人話:用 AI 把你的研究變成精彩演講!

為什麼學生的科展發表總讓人覺得可惜?

最近正值許多學校進行專題成果發表的季節。這些年來聽了不少學生的發表,常常都有一種很可惜的感覺。

大家常常把自己精彩的研究發表弄得很無聊,常見的問題像是:

四個常見的報告致命傷

  1. 照本宣科的報告架構
     許多學生沿用紙本報告的格式發表,從題目、摘要開始,一路講到參考文獻。由於文字量龐大,不是匆匆念過,就是讓觀眾自行閱讀。

  2. 花太多時間在不重要的細節上
     像是詳盡的文獻探討、設備清單、研究步驟或原始數據表格,這些對沒有專業背景的聽眾來說既難以理解,也缺乏吸引力,容易讓人失去耐心。

  3. 缺乏吸引人的敘事節奏
     學術報告的格式是為了系統性記錄,而非講故事。逐字照稿念、缺乏起承轉合與情緒起伏,使得演講難以抓住聽眾注意力。

  4. 資訊平均分配,重點不突出
     學術報告常會平等呈現所有資訊,然而科普演講則需要聚焦在最關鍵、最有趣的發現。若直接照搬報告內容,亮點反而會被埋沒在細節裡。

不是學生不努力,是沒有人教他們怎麼說故事

簡而言之,學生們大多尚未學會如何進行一場吸引人的演講。其實學生會這樣發表,也不是不努力,而是缺乏演講訓練或不知道可以怎麼做。

以前看過有些大學會辦過一個活動,讓研究生在五分鐘內,向一般民眾說明自己的研究。最近也看到一些國外的大學,舉辦類似比賽,邀請博士班學生用五分鐘進行大眾導向的演講。

為什麼中學生也應該這樣做?

中學生的專題成果發表,其實也應該朝這個方向發展。畢竟聽眾通常是年齡相仿的同學或學弟妹。

一場好的口頭發表,應該是從報告中挑出最精彩、最容易理解、最具啟發性的部分,用講故事的方式重新組織內容,加入情感與共鳴元素,並將複雜的科學概念轉譯成一般人聽得懂的語言。這麼做可能會略微犧牲學術上的完整性與細節,但卻能大幅提升演講的趣味性、吸引力與理解度,甚至帶來那種「啊哈!」的 Eureka 時刻。

AI 協作時代

只是喔,過去不管我怎麼鼓勵學生往這個方向嘗試,真正做得好的還是少數。不過現在有 AI 協作的工具了,應該可以做得更好了。

其實只要一個簡單的 prompt,就可以做得到:


任務:根據這份科展報告,產出一份科普演講稿。
目標聽眾:國中生或對科學感興趣的大眾。
時間限制:5 到 7 分鐘。
風格要求:生動有趣、淺顯易懂、避免艱深術語。
目前困難:我不確定該怎麼把報告內容轉化為演講流程,也不清楚哪些細節該保留、哪些該刪去,需要你的協助。


試試看讓 AI 幫你說出好故事

各位可以試試看:到「科展群傑廳」下載幾份中小學科展的報告,放進 NotebookLM,搭配前面提到的 prompt,一起看看 AI 會怎麼轉化內容。

即使是那些充滿公式、表格、技術細節的報告,NotebookLM 也總是能萃取出精彩的核心,轉化成精彩的講稿。光是看這些講稿,就像在看一段引人入勝的科學小故事。