Lewati ke isi
Profil penulisSeri Buku GIS Kehutanan dan Pertanian/ B3
Tampilkan bagian untuk:

BAB 6: NDVI: Mengukur Kehijauan Tanaman dengan Satu Rumus

#Studi kasus: "Kebun mana yang paling hijau?"

Kepala Seksi ingin membandingkan kondisi vegetasi KPH Alpha, Beta, dan Gamma. Memandangi citra warna palsu membuat Analis Muda hanya bisa berkata "yang ini lebih merah". Kepala Seksi menginginkan angka. Bab ini memperkenalkan indeks vegetasi NDVI, yang mengubah dua band menjadi satu angka kehijauan untuk tiap piksel.

#Konsep: NDVI dalam tiga kalimat

Daun sehat menyerap cahaya merah untuk berfotosintesis dan memantulkan banyak inframerah dekat, seperti cermin yang hanya memantulkan satu warna. NDVI membandingkan kedua pantulan itu dalam satu rumus: selisihnya dibagi jumlahnya. Hasilnya angka antara -1 dan 1, dan makin tinggi berarti makin lebat dan sehat vegetasinya.

Istilah baru bab ini:

  • Indeks vegetasi: angka hasil rumus beberapa band untuk menonjolkan vegetasi.
  • NDVI (Normalized Difference Vegetation Index): indeks vegetasi yang paling umum.
  • Pantulan (reflektansi): bagian cahaya yang dipantulkan permukaan.
  • Raster calculator: alat hitung antar-raster, piksel demi piksel.
  • Statistik zonal: ringkasan nilai raster (misalnya rata-rata) di dalam tiap poligon.
Ilustrasi 6.1: Pantulan merah dan inframerah dekat
Grafik batang nilai sintetis: pantulan merah dan inframerah dekat untuk lima jenis tutupan, beserta NDVI-nya

#Rumusnya

TEKS
NDVI = (NIR - Merah) / (NIR + Merah)

NIR adalah band inframerah dekat (band 4, B08). Merah adalah band 3 (B04). Contoh untuk hutan sintetis: pantulan NIR 0,40 dan merah 0,03. NDVI = (0,40 - 0,03) / (0,40 + 0,03) = 0,86.

#Cara membaca nilai NDVI

Kisaran NDVIBiasanya berarti
Di bawah 0Air
0 sampai sekitar 0,3Lahan terbuka atau tanah
Sekitar 0,3 sampai 0,6Vegetasi jarang atau tanaman muda
Di atas sekitar 0,6Vegetasi lebat

Kisaran ini pedoman kasar, bukan hukum. Nilai batas berbeda antar-citra dan antar-daerah. [kemungkinan: kebiasaan umum; batas kelas di buku ini pilihan penulis untuk latihan]

#Angka dari data latihan

NDVI rata-rata per jenis tutupan (data sintetis; dihitung dari piksel):

TutupanNDVI rata-rata
Hutan0,860
Kebun0,714
Sawah atau tanaman muda0,515
Lahan terbuka0,128
Air-0,201

Seluruh citra: NDVI terkecil -0,328, terbesar 0,903, rata-rata 0,735. Dikelompokkan dengan batas 0, 0,3, dan 0,6:

KelasPikselLuas (ha)
1 Air (sampai 0)1.2030,48
2 Lahan terbuka (0 sampai 0,3)1.7670,71
3 Vegetasi jarang (0,3 sampai 0,6)4.9942,00
4 Vegetasi rapat (di atas 0,6)32.03612,81

NDVI rata-rata per KPH: Alpha 0,814, Beta 0,614, Gamma 0,755. Beta paling rendah karena separuhnya adalah sawah atau tanaman muda. Alpha tinggi karena hampir seluruhnya hutan. Semua angka diuji di QGIS 4.0.2 (Skrip 6.1).

Ilustrasi 6.2: Peta NDVI dan kelasnya
Skema dari data latihan: peta NDVI berwarna merah ke hijau dan peta empat kelas

#Bagian A: QGIS

#Bagian A: Menghitung NDVI di QGIS

#Langkah 1: Raster Calculator

  1. Pastikan Citra_4band dari Bab 2 ada di proyek.
  2. Buka Raster ► Raster Calculator….
  3. Di kotak Raster Calculator Expression, ketik rumus berikut. Nama band ditulis nama_layer@nomor_band:
TEKS
("Citra_4band@4" - "Citra_4band@3") / ("Citra_4band@4" + "Citra_4band@3")
  1. Pada Output layer, pilih berkas, misalnya C:\kerja_b3\NDVI.tif. Biarkan format GeoTIFF.
  2. Pilih satu band Citra_4band di daftar Raster Bands, lalu klik tombol Selected Layer Extent supaya ukuran hasil sama dengan citra. Klik OK. [CEK: letak tombol]
  3. Hasilnya layer NDVI. Beri warna di Symbology ► Singleband pseudocolor dengan deretan merah ke kuning ke hijau, atau pilih mode Min/Max agar tampilannya jelas.

Anda mendapat nilai NDVI -0,328 sampai 0,903 (rata-rata 0,735). Bila nilainya tidak seperti itu, periksa nomor band dan tanda kurungnya.

#Langkah 2: mengelompokkan NDVI

Gunakan Reclassify by table (Bab 5) pada NDVI.tif dengan tabel:

MinimumMaximumValueArti
-101Air
00,32Lahan terbuka
0,30,63Vegetasi jarang
0,61,014Vegetasi rapat

Pilih Range boundaries = min < value <= max (bawaan), Output data type = Byte. Hitung luas dengan Raster layer unique values report.

#Langkah 3: rata-rata NDVI per KPH

  1. Buka Zonal statistics di Processing Toolbox.
  2. Isi Input layer dengan Batas_KPH, Raster layer dengan NDVI, dan Raster band dengan 1.
  3. Pada Statistics to calculate, centang Mean.
  4. Isi Output column prefix dengan ndvi_, lalu klik Run.
  5. Buka tabel atribut hasil. Kolom ndvi_mean berisi: Alpha 0,814, Beta 0,614, Gamma 0,755.

#Dengan Python (opsional)

Berkas skrip/b3_06_ndvi.py. Jalankan Skrip 2.1 lebih dulu.

PYTHON
import processing
from qgis.core import QgsRasterLayer, QgsProject
from qgis.analysis import QgsRasterCalculator, QgsRasterCalculatorEntry

DATA = r"D:/data/paket-b3"
OUT = r"C:/kerja_b3"

stack = QgsRasterLayer(OUT + "/Citra_4band.tif", "Citra_4band")
nir = QgsRasterCalculatorEntry()
nir.ref, nir.raster, nir.bandNumber = "nir@1", stack, 4      # band 4 = inframerah dekat
red = QgsRasterCalculatorEntry()
red.ref, red.raster, red.bandNumber = "red@1", stack, 3      # band 3 = merah

rumus = '("nir@1" - "red@1") / ("nir@1" + "red@1")'
calc = QgsRasterCalculator(rumus, OUT + "/NDVI.tif", "GTiff", stack.extent(), stack.width(), stack.height(),
                           [nir, red], QgsProject.instance().transformContext())
print("Kode hasil (0 = sukses):", calc.processCalculation())

st = processing.run("native:rasterlayerstatistics", {"INPUT": OUT + "/NDVI.tif", "BAND": 1})
print("NDVI min/maks/rata-rata:", round(st["MIN"], 3), "/", round(st["MAX"], 3), "/", round(st["MEAN"], 3))

# Kelompokkan: sampai 0 = air; 0-0,3 = lahan terbuka; 0,3-0,6 = vegetasi jarang; di atas 0,6 = vegetasi rapat
processing.run("native:reclassifybytable", {
    "INPUT_RASTER": OUT + "/NDVI.tif", "RASTER_BAND": 1,
    "TABLE": [-1, 0, 1,  0, 0.3, 2,  0.3, 0.6, 3,  0.6, 1.01, 4],
    "RANGE_BOUNDARIES": 0, "NODATA_FOR_MISSING": True, "NO_DATA": 255, "DATA_TYPE": 0,
    "OUTPUT": OUT + "/NDVI_kelas.tif"})
u = processing.run("native:rasterlayeruniquevaluesreport", {"INPUT": OUT + "/NDVI_kelas.tif", "BAND": 1,
                                                            "OUTPUT_TABLE": "TEMPORARY_OUTPUT"})
nama = {1: "Air", 2: "Lahan terbuka", 3: "Vegetasi jarang", 4: "Vegetasi rapat"}
for f in u["OUTPUT_TABLE"].getFeatures():
    k = int(f["value"])
    print(k, nama.get(k, "NoData"), f["count"], "piksel =", round(f["count"] * 4 / 10000, 2), "ha")

# Rata-rata NDVI per KPH
z = processing.run("native:zonalstatisticsfb", {
    "INPUT": DATA + "/Batas_KPH.gpkg|layername=Batas_KPH", "INPUT_RASTER": OUT + "/NDVI.tif", "RASTER_BAND": 1,
    "COLUMN_PREFIX": "ndvi_", "STATISTICS": [2], "OUTPUT": "TEMPORARY_OUTPUT"})
for f in z["OUTPUT"].getFeatures():
    print(f["NAMA_KPH"], "NDVI rata-rata:", round(f["ndvi_mean"], 3))

Keluaran yang diuji di QGIS 4.0.2:

TEKS
Kode hasil (0 = sukses): 0
NDVI min/maks/rata-rata: -0.328 / 0.903 / 0.735
1 Air 1203 piksel = 0.48 ha
2 Lahan terbuka 1767 piksel = 0.71 ha
3 Vegetasi jarang 4994 piksel = 2.0 ha
4 Vegetasi rapat 32036 piksel = 12.81 ha
KPH Alpha NDVI rata-rata: 0.814
KPH Beta NDVI rata-rata: 0.614
KPH Gamma NDVI rata-rata: 0.755

#Jebakan: rumus NDVI yang tampak benar tetapi salah

Alat Raster calculator dari grup GDAL (gdal:rastercalculator) memakai huruf A, B, dan seterusnya untuk layer. Ujilah rumus berikut dengan A = band NIR (Citra_B08) dan B = band merah (Citra_B04), keduanya bertipe UInt16, dan Output raster type = Float32:

RumusHasil min, maks, rata-rata
(A-B)/(A+B)0,001 / 155,83 / 4,68 (salah)
(A.astype(float)-B)/(A.astype(float)+B)-0,328 / 0,903 / 0,735 (benar)

Pada rumus pertama, piksel air dan lahan terbuka punya merah lebih besar dari NIR sehingga selisihnya negatif. Pada bilangan UInt16, selisih negatif "membungkus" menjadi angka sangat besar, lalu NDVI ikut melonjak melebihi 1. Rumus kedua mengubah NIR menjadi pecahan lebih dulu, sehingga aman. Angka diuji di QGIS 4.0.2.

#Bagian B: ArcGIS Pro

#Bagian B: ArcGIS Pro

  1. Gunakan Raster Calculator (Spatial Analyst Tools). Alat ini hanya untuk dipakai di aplikasi (panel Geoprocessing atau ModelBuilder), bukan skrip, menurut dokumentasi Esri.
  2. Ketik ekspresi dengan sintaks aljabar peta (map algebra). Karena band bilangan bulat, ubah dulu ke pecahan dengan fungsi Float:
TEKS
(Float("Citra_4band.tif - Band_4") - Float("Citra_4band.tif - Band_3")) / (Float("Citra_4band.tif - Band_4") + Float("Citra_4band.tif - Band_3"))

Nama layer di ekspresi mengikuti daftar Rasters pada alat. [CEK]

  1. Alasan memakai Float: dokumentasi alat Divide menyebut bahwa bila kedua masukan bilangan bulat, yang terjadi adalah pembagian bilangan bulat dan hasilnya bilangan bulat (3 dibagi 2 menjadi 1). Dokumentasi Raster Calculator sendiri tidak menjelaskan ini, jadi uji hasilnya. [CEK]
  2. Cara lain: fungsi raster NDVI. Menurut dokumentasi Esri, parameternya Visible Band ID (band merah), Infrared Band ID (band inframerah dekat), dan Scientific Output (nilai -1 sampai 1). Untuk Citra_4band, merah adalah band 3 dan inframerah dekat band 4. Lokasi fungsi di antarmuka: tab Imagery, bagian Raster Functions. [CEK]
  3. Statistik zonal: alat Zonal Statistics as Table dengan zona Batas_KPH dan statistik rata-rata. [CEK]

#Bagian C: ArcMap 10.8

#Bagian C: ArcMap 10.8

  1. Buka Raster Calculator (toolbox Spatial Analyst, toolset Map Algebra). Alat ini memakai sintaks Python dan, menurut dokumentasi Esri, hanya untuk dipakai di dalam aplikasi atau ModelBuilder.
  2. Gunakan fungsi Float seperti di Pro agar pembagian menghasilkan pecahan:
TEKS
(Float("Citra_4band.tif - Band_4") - Float("Citra_4band.tif - Band_3")) / (Float("Citra_4band.tif - Band_4") + Float("Citra_4band.tif - Band_3"))

[CEK]

  1. Ekstensi Spatial Analyst diperlukan.
  2. Statistik zonal: Zonal Statistics as Table (Spatial Analyst, toolset Zonal). [CEK]

#Cek paham

  1. Mengapa vegetasi sehat bernilai NDVI tinggi?
  2. Berapa kisaran nilai NDVI yang mungkin?
  3. Mengapa rumus (A-B)/(A+B) pada band UInt16 bisa salah di alat GDAL?

Jawaban:

  1. Daun sehat menyerap merah dan memantulkan banyak inframerah dekat. Selisihnya besar, jadi NDVI mendekati 1.
  2. Antara -1 dan 1.
  3. Selisih negatif pada bilangan tanpa tanda "membungkus" menjadi angka besar, sehingga hasil melebihi 1. Ubah ke pecahan dulu (astype(float)).

#Kesalahan umum

  • Salah memilih band. Tertukarnya band merah dan inframerah dekat membalik tanda NDVI. Cocokkan dengan Bab 2: merah band 3, NIR band 4.
  • Tipe bilangan bulat. Lihat jebakan di atas. Selalu periksa min dan maks hasil.
  • Menafsirkan angka mutlak sebagai kebenaran lapangan. Nilai NDVI bergantung pada sensor dan musim. Gunakan untuk membandingkan dalam satu citra, atau antar-tanggal dengan syarat yang sama.
  • Menghitung rata-rata dari raster yang tidak dipotong. Rata-rata seluruh citra bukan rata-rata satu KPH. Pakai statistik zonal atau potong dulu (Bab 4).

#Ringkasan dan latihan

Ringkasan: NDVI = (NIR - Merah) / (NIR + Merah), berkisar -1 sampai 1. Hitung dengan Raster Calculator, kelompokkan dengan reklasifikasi, dan ringkas per KPH dengan statistik zonal. Waspadai tipe bilangan bulat.

Latihan:

  1. Hitung NDVI, lalu temukan nilainya di titik bukaan lahan Alpha (E 312145, N 9996065). Jawaban uji: sekitar 0,15 (nilai asli di piksel itu 0,149; rata-rata lahan terbuka 0,128).
  2. Hitung NDVI rata-rata per KPH dan urutkan dari yang tertinggi. Jawaban uji: Alpha 0,814, Gamma 0,755, Beta 0,614.
  3. Mengapa Gamma lebih rendah dari Alpha padahal sama-sama hutan? Jawaban: Gamma memuat sungai (NDVI negatif) dan bukaan lahan bulat yang menurunkan rata-rata.

#Tabel perbandingan: NDVI

HalQGISArcGIS ProArcMap 10.8
Alat hitungRaster ► Raster CalculatorRaster Calculator (Spatial Analyst)Raster Calculator (Spatial Analyst)
Penulisan band"layer@4"Nama dari daftar RastersNama dari daftar Rasters
Cegah pembagian bulatRaster Calculator QGIS aman (diuji); alat GDAL perlu astype(float)Pakai Float [CEK]Pakai Float [CEK]
Fungsi NDVI siap pakaiTidak ada alat bawaan di buku iniFungsi raster NDVI [CEK]Perlu dicek [CEK]
Statistik per poligonZonal statisticsZonal Statistics as Table [CEK]Zonal Statistics as Table [CEK]