It’s safe to say that Google Earth Engine (GEE) has changed the world for geospatial analysis. By providing access to a massive catalog of satellite imagery, it allows us to analyze our planet in ways that were previously unthinkable. Despite this, it’s often difficult to translate that raw data into a solution for a complex, real-world problem like locating viable groundwater sources.
This article presents a novel technique for using GEE’s infrared (IR) imagery to identify indicators of groundwater. By analyzing specific spectral patterns in the satellite data, we can significantly narrow down areas of interest, making groundwater exploration more targeted and efficient.
This article will demonstrate how to use Google Earth Engine to find indicators of groundwater. By the end, you’ll understand:
- Why Near-Infrared (NIR) imagery is a key tool for this task.
- How remote sensing indices like NDVI and NDMI work.
- How to use Gemini to analyze the resulting images to pinpoint promising locations.
- The high-level steps to implement this on Google Cloud.
Now that we understand the goal, let’s look at the remote sensing techniques we can use.
To understand the solution, we first need to define some basic concepts. Groundwater is water held underground in soil or in rock crevices and cavities. It’s different from surface water, which includes things like lakes, rivers, and streams.
Why is groundwater important? For one, it’s a major source of drinking water. Beyond that, it’s used for agriculture and in various industries including manufacturing, mining, and energy production. Additionally, groundwater can help resupply low levels of surface water during times of drought.
So why is finding groundwater efficiently such a big deal? It comes down to a few key reasons. Traditional methods (often involving manual inspections) are slow, expensive, and hit-or-miss. A better approach using remote sensing offers clear advantages:
- Addresses Water Scarcity: Quickly identifies new, sustainable water sources to support communities and agriculture, especially in drought-prone regions.
- Lowers Costs and Reduces Risk: Saves significant time and money by pinpointing the most promising locations for drilling, reducing the need for costly and often unsuccessful exploratory work.
- Minimizes Environmental Impact: Prevents unnecessary land disruption and protects existing ecosystems by making exploration targeted and precise.
- Supports Infrastructure Repair: Has the potential to identify large slow-water leaks that may go unnoticed for long periods of time.
The key to using remote sensing for this task lies in observing what we can see — vegetation and soil moisture — to infer what we can’t see underground. Healthy, well-hydrated vegetation in an otherwise arid area is often a strong indicator of a shallow groundwater source. To detect these patterns, we use specific wavelengths of light captured by satellites.
Near-Infrared (NIR) is a part of the electromagnetic spectrum that’s invisible to the human eye, with wavelengths slightly longer than visible light. It’s crucial in remote sensing because healthy vegetation strongly reflects NIR light while absorbing visible red light. This distinct reflection pattern allows scientists to assess vegetation health and density.
Google Earth Engine (GEE) provides extensive access to satellite imagery that includes both NIR and visible color bands. Satellites like Landsat and Sentinel-2 are key sources for this data. Within GEE, users can select specific satellite image collections and then choose the desired spectral bands (like Red, Green, Blue for visible color, and the NIR band) to analyze or visualize. This enables various applications, such as creating natural color images or false-color composites that highlight vegetation using the NIR band.
Here’s an example image that shows visible, NIR, and shortwave infrared (SWIR) images for the same person:
To turn raw satellite data into actionable insights, we use remote sensing indices — mathematical combinations of different spectral bands. For groundwater detection, two of the most effective are the Normalized Difference Vegetation Index (NDVI) and the Normalized Difference Moisture Index (NDMI).
NDVI is a widely used indicator of healthy, green vegetation. It’s calculated based on the difference between near-infrared (NIR) and red light reflected by plants. Healthy vegetation absorbs most visible red light while reflecting a large portion of NIR light.
- How it’s calculated: NDVI=(NIR−Red)/(NIR+Red)
- Relevance to groundwater: Areas with higher groundwater availability often support more vigorous vegetation, especially in arid regions. Identifying pockets of high NDVI can help us infer subsurface water sources that are sustaining plant growth.
Also known as the Normalized Difference Water Index (NDWI), NDMI is used to assess the water content in vegetation. It utilizes the near-infrared (NIR) and shortwave-infrared (SWIR) bands, as water in plants absorbs SWIR light.
- How it’s calculated: NDMI=(NIR−SWIR)/(NIR+SWIR)
- Relevance to groundwater: Elevated NDMI values indicate well-hydrated plants, which could be a direct result of access to shallow groundwater. This is especially useful for detecting subtle moisture differences that aren’t visible to the naked eye.
By combining the insights from both NDVI and NDMI, we can develop a more comprehensive understanding of potential groundwater locations:
- Identifying Water-Stressed Areas: Low NDVI and NDMI could indicate areas where vegetation is stressed due to lack of surface or groundwater, thus directing exploration away from such regions.
- Locating Phreatophytes: Certain plant species, known as phreatophytes, have roots that extend deep enough to reach the water table. These plants often exhibit high NDVI and NDMI values. Mapping clusters of these vigorous, well-hydrated plants can point to shallow groundwater reserves.
- Detecting Anomalies: Unexpectedly high NDVI or NDMI in an otherwise arid landscape can signal a hidden groundwater source. These anomalies might be indicative of springs, seeps, or areas where the water table is close to the surface.
- Monitoring Seasonal Changes: Analyzing how these indices change over different seasons can provide insights into the dynamics of groundwater. For example, if vegetation remains green and moist during dry seasons, it strongly suggests a reliable groundwater source.
- Complementary Data: These indices are most effective when used in conjunction with other geospatial data, such as geological maps, topographic data, and soil moisture information, to provide a more robust assessment of groundwater potential.
As you can see above, both NDVI and NDMI produce images that are color-coded for the data they are displaying. We can look at a set of images of the same area over time to detect changes in groundwater indicators like these, but that’s a fairly manual process. Instead, the simplest approach is to provide the images to Gemini and ask it to examine them.
Using Gemini for the analysis of NDVI and NDMI images is an efficient approach to identifying groundwater indicators. Instead of manual visual inspection (which can be time-consuming and prone to human error), Gemini can be leveraged to process and interpret these remote sensing outputs.
By feeding the generated NDVI and NDMI images (or the underlying spectral data) into Gemini, the AI can be prompted to identify specific patterns, anomalies, and relationships indicative of groundwater presence. For instance, Gemini can be instructed to highlight areas with consistently high NDVI values in arid regions, especially during dry seasons, as this strongly suggests subsurface water sustaining the vegetation. Similarly, it can pinpoint regions with elevated NDMI values, indicating high moisture content in vegetation, which might be linked to shallow groundwater tables.
Additionally, Gemini can go beyond simple value thresholds by integrating temporal data. It can analyze sequences of NDVI and NDMI images collected over various seasons or years to detect subtle changes that reveal groundwater dynamics. For example, if an area shows a sustained high NDMI despite prolonged drought conditions, Gemini can identify this as a significant anomaly pointing to a resilient groundwater source. The AI’s ability to process vast amounts of imagery and identify complex, multi-variable correlations makes it an invaluable tool for groundwater exploration, allowing for more precise targeting of areas for further investigation and significantly reducing the time and resources traditionally required for such endeavors.
At this point, we understand the theory. Now let’s walk through the high-level steps to implement this on Google Cloud. The basic process involves selecting a satellite data source, retrieving images for a specific location and time, and then generating our NDVI and NDMI indices.
1. Accessing Google Earth Engine
First, you’ll need to be able to make calls to the GEE platform. If you haven’t already, you can sign up on the GEE Developer page. From there, you can work in the web-based Code Editor or use the Python API in a Jupyter notebook environment, which is what we’ll be doing here.
2. Retrieving and Processing Imagery
The core of the workflow is to query an image collection, like COPERNICUS/S2_SR_HARMONIZED from the Sentinel-2 satellite, which contains the spectral bands we need. We filter this collection by our region of interest and a specific date range.
The following Python code demonstrates this entire process. It defines functions to:
- Query GEE for relevant Sentinel-2 imagery for a given location and date.
- Download the separate Red, Near-Infrared (NIR), and Shortwave-Infrared (SWIR) bands.
- Calculate the NDVI and NDMI values from those bands.
- Visualize the final indices as color-coded images ready for analysis.
import requests
import ee
import numpy as np
import datetime
import matplotlib.pyplot as plt
from PIL import ImageMY_PROJECT_ID = "something"
ee.Initialize(project=MY_PROJECT_ID)
def load_image(image_path):
"""
Loads an image and converts it to a floating point numpy array.
"""
img = Image.open(image_path).convert('RGB')
img_array = np.array(img, dtype=np.float32) / 255.0 # Normalize to 0-1
return img_array
def calculate_ndvi(nir, red):
"""
Calculates the Normalized Difference Vegetation Index (NDVI).
"""
numerator = nir - red
denominator = nir + red
ndvi = np.where(denominator != 0, numerator / denominator, 0)
return ndvi
def calculate_ndmi(nir, swir):
"""
Calculates the Normalized Difference Moisture Index (NDMI).
"""
numerator = nir - swir
denominator = nir + swir
ndmi = np.where(denominator != 0, numerator / denominator, 0)
return ndmi
def create_index_images(true_color_image, nir_image, swir_image, output_suffix, formatted_datetime):
# Extract bands from the true color image
red_band = true_color_image[:, :, 0]
green_band = true_color_image[:, :, 1]
# blue_band = true_color_image[:, :, 2]
# Ensure NIR and SWIR are single-band images; if RGB, take one channel
if nir_image.ndim == 3:
nir_band = nir_image[:, :, 0] # Take the first channel
else:
nir_band = nir_image # assume already single band
if swir_image.ndim == 3:
swir_band = swir_image[:, :, 0] # Take the first channel
else:
swir_band = swir_image # assume already single band
# Calculate indices
ndvi_image = calculate_ndvi(nir_band, red_band)
ndmi_image = calculate_ndmi(nir_band, swir_band)
visualize_index(ndvi_image, f'NDVI: {formatted_datetime}', f'ndvi_{output_suffix}.png')
visualize_index(ndmi_image, f'NDMI: {formatted_datetime}', f'ndmi_{output_suffix}.png')
def visualize_index(index_array, title, output_path, cmap='RdYlGn'):
"""
Visualizes the index array using a colormap and saves the image.
"""
plt.ioff() # Turn interactive mode off
plt.figure(figsize=(10, 8))
plt.imshow(index_array, cmap=cmap)
plt.colorbar(label=title)
plt.title(title)
plt.savefig(output_path)
plt.close()
def get_satellite_imagery(longitude, latitude, start_datetime_str, end_datetime_str, buffer_distance):
# Convert datetime string to ee.Date
start_date = ee.Date(start_datetime_str)
end_date = ee.Date(end_datetime_str)
# Create point geometry. Note that "buffer_distance" is in meters, unless a specific projection is specified
point = ee.Geometry.Point([longitude, latitude])
region = point.buffer(buffer_distance)
# Get Sentinel-2 collection
s2_collection = (
ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED')
.filterBounds(region)
.filterDate(start_date, end_date)
.sort('system:time_start')
)
return s2_collection, region
def save_multiband_imagery(image, region, base_filename, pixel_width):
"""
Save true color, NIR, and SWIR versions of the satellite imagery.
Args:
image (ee.Image): Earth Engine image object
region (ee.Geometry): Region of interest
base_filename (str): Base filename without extension
image_scale (int): Image dimensions in pixels
"""
# Define visualization parameters for different band combinations
vis_params = {
'true_color': {
'bands': ['B4', 'B3', 'B2'],
'min': 0,
'max': 3000,
'filename': f"true_color_{base_filename}.png",
'scale': 10
},
'nir': {
'bands': ['B8'],
'min': 0,
'max': 3000,
'filename': f"nir_{base_filename}.png",
'scale': 10
},
'swir': {
'bands': ['B11'],
'min': 0,
'max': 3000,
'filename': f"swir_{base_filename}.png",
'scale': 20
}
}
# Save each band combination
fnames = []
for band_type, params in vis_params.items():
thumb_params = {
'region': region,
'format': 'png',
'bands': params['bands'],
'min': params['min'],
'max': params['max'],
'dimensions': pixel_width
}
url = image.getThumbURL(thumb_params)
response = requests.get(url)
if response.status_code == 200:
with open(params['filename'], 'wb') as f:
f.write(response.content)
fnames.append(params['filename'])
else:
print(f"Failed to download {band_type} image. Status code: {response.status_code}")
return fnames
def main():
# define our date range and the location to examine
start_datetime_str = '2023-12-25'
end_datetime_str = '2024-01-15'
latitude, longitude = 35.089248, -106.637810
# center on the coord, within a box (buffer_distance is in meters, and talks about space around center point)
collection, region = get_satellite_imagery(
longitude, latitude,
start_datetime_str,
end_datetime_str,
buffer_distance=500, # this gives us 1 KM square bitmap
)
collection_info = collection.getInfo()
num_images = len(collection_info['features'])
print(f"Number of images in the collection: {num_images}")
for index, feature in enumerate(collection_info['features']):
image_id = feature['id'] # Get the image ID
image = ee.Image(image_id)
info = image.getInfo()
# Convert milliseconds to seconds and create a datetime object
image_datetime = info['properties']['GENERATION_TIME']
datetime_object = datetime.datetime.fromtimestamp(image_datetime / 1000)
formatted_datetime = datetime_object.strftime("%Y-%m-%d %H:%M:%S")
truecolor_fname, nir_fname, swir_fname = save_multiband_imagery(image, region, f"{index}", pixel_width=100)
truecolor = load_image(truecolor_fname)
nir = load_image(nir_fname)
swir = load_image(swir_fname)
print(f'Creating index images for image {index}, taken on {formatted_datetime}')
create_index_images(truecolor, nir, swir, f"{index:03d}", formatted_datetime)
if __name__ == "__main__":
main()
This article has demonstrated the power of Google Earth Engine (GEE) and remote sensing indices in the important task of groundwater exploration. We’ve seen how leveraging GEE’s satellite imagery datasets, particularly those including Near-Infrared (NIR) and Shortwave Infrared (SWIR) bands, allows for the calculation of indices like NDVI and NDMI. These indices provide invaluable insights into vegetation health and moisture content, which serve as strong indicators of underlying groundwater reserves. By moving beyond traditional, labor-intensive methods, this approach offers a more efficient, cost-effective, and environmentally friendly way to pinpoint areas with high groundwater potential, ultimately contributing to better water resource management and addressing the challenges of water scarcity.
The integration of advanced AI tools like Gemini further amplifies the capabilities of this remote sensing methodology. Gemini’s ability to analyze complex patterns, anomalies, and temporal changes within NDVI and NDMI imagery transforms a manual interpretation process into an automated, data-driven assessment. This not only accelerates the identification of promising groundwater locations but also enables a more nuanced understanding of groundwater dynamics over time. By combining the rich data available through GEE with intelligent analytical platforms, we can significantly enhance our capacity to discover, monitor, and sustainably manage this indispensable natural resource for the benefit of communities and ecosystems worldwide.
Source Credit: https://medium.com/google-cloud/finding-groundwater-using-google-earth-engine-and-gemini-d5d355e49697?source=rss—-e52cf94d98af—4