Last active
October 15, 2024 19:30
-
-
Save jmasselink/be618d52bf164965d464f6fa561f6806 to your computer and use it in GitHub Desktop.
Water detection in Sentinel Hub
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//VERSION=3 | |
const colorRamp = [[0, 0x000000], [1, 0xFFFFFF]]; // Color ramp for water detection (black for water) | |
let viz = new ColorRampVisualizer(colorRamp); | |
function setup() { | |
return { | |
input: ["B02", "B03", "B04", "B08", "B11", "dataMask"], | |
output: [ | |
{ id: "default", bands: 4 }, // RGBA output for combined visualization | |
{ id: "index", bands: 1, sampleType: 'FLOAT32' }, // Binary index output | |
{ id: "eobrowserStats", bands: 2, sampleType: 'FLOAT32' }, // Stats for mNDWI and data mask | |
{ id: "dataMask", bands: 1 } // Mask output | |
] | |
}; | |
} | |
function evaluatePixel(samples) { | |
// Step 1: Create True-Color RGB Image (using B04, B03, B02) | |
let trueColor = [samples.B04 * 2.5, samples.B03 * 2.5, samples.B02 * 2.5]; // Adjust brightness | |
// Step 2: Calculate indices for water detection | |
let mNDWI = (samples.B03 - samples.B11) / (samples.B03 + samples.B11); | |
let NDVI = (samples.B08 - samples.B04) / (samples.B08 + samples.B04); | |
let EVI = 2.5 * (samples.B08 - samples.B04) / (samples.B08 + 6 * samples.B04 - 7.5 * samples.B02 + 1); | |
// Step 3: Apply water detection criteria from Xia et al. | |
let isWater = (mNDWI > NDVI && EVI < 0.1) && (mNDWI > EVI && EVI < 0.1); | |
// Step 4: Create Overlay for Water Detection: Black for water, transparent for non-water | |
let overlay = isWater ? [0, 0, 1, 0.6] : [0, 0, 0, 0]; // Water is black, non-water is transparent | |
// Step 5: Combine True Color Image and Water Detection Overlay | |
let combined = [ | |
trueColor[0] * (1 - overlay[3]) + overlay[0], trueColor[1] * (1 - overlay[3]) + overlay[1],trueColor[2] * (1 - overlay[3]) + overlay[2],samples.dataMask | |
]; | |
let indexVal = samples.dataMask === 1 ? (isWater ? 1 : 0) : NaN; | |
return { | |
default: combined, // Visualization: True color + water detection overlay | |
index: [indexVal], // Binary index (1 for water, 0 for non-water) | |
eobrowserStats: [mNDWI, samples.dataMask], // Output mNDWI for analysis | |
dataMask: [samples.dataMask] // Data mask | |
}; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//VERSION=3 | |
const colorRamp = [[0, 0xFF69B4], [1, 0x000000]]; | |
let viz = new ColorRampVisualizer(colorRamp); | |
function setup() { | |
return { | |
input: ["B02", "B03", "B04", "B08", "B11", "dataMask"], | |
output: [ | |
{ id: "default", bands: 4 }, // RGBA output for combined visualization | |
{ id: "index", bands: 1, sampleType: 'FLOAT32' }, // Binary index output | |
{ id: "eobrowserStats", bands: 2, sampleType: 'FLOAT32' }, // Stats for mNDWI and data mask | |
{ id: "dataMask", bands: 1 } // Mask output | |
] | |
}; | |
} | |
function evaluatePixel(samples) { | |
// Step 1: RGB | |
let trueColor = [samples.B04 * 2.55, samples.B03 * 2.55, samples.B02 * 2.55]; | |
// Step 2: water detection | |
let mNDWI = (samples.B03 - samples.B11) / (samples.B03 + samples.B11); | |
let NDVI = (samples.B08 - samples.B04) / (samples.B08 + samples.B04); | |
let EVI = 2.5 * (samples.B08 - samples.B04) / (samples.B08 + 6 * samples.B04 - 7.5 * samples.B02 + 1); | |
// Step 3: Apply water detection | |
let isWater = (mNDWI > NDVI && EVI < 0.1) && (mNDWI > EVI && EVI < 0.1); | |
// Step 4: Create Overlay | |
let overlay = isWater ? [1, 0.11, 0.71, 0.8] : [0, 0, 0, 0]; // Water is pink, non-water is transparent | |
// Step 5: | |
let combined = [ | |
trueColor[0] * (1 - overlay[3]) + overlay[0], // Red channel | |
trueColor[1] * (1 - overlay[3]) + overlay[1], // Green channel | |
trueColor[2] * (1 - overlay[3]) + overlay[2], // Blue channel | |
samples.dataMask // Alpha channel (transparency based on mask) | |
]; | |
// Step 6: Handle index and stats output | |
let indexVal = samples.dataMask === 1 ? (isWater ? 1 : 0) : NaN; | |
return { | |
default: combined, | |
index: [indexVal], | |
eobrowserStats: [mNDWI, samples.dataMask], dataMask: [samples.dataMask] | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment