Digital Images
Google Earth Engine (GEE) provides powerful tools for working with digital images, which are essential for remote sensing and geospatial analysis. GEE allows users to access and process vast collections of satellite imagery and other geospatial datasets. The platform supports a variety of image processing tasks such as cloud masking, normalization, and feature extraction, making it easier to prepare data for analysis. Users can apply algorithms to classify land cover, detect changes over time, and derive meaningful insights from raw image data. By leveraging GEE's computational power and extensive dataset repository, researchers can efficiently manage and analyze large-scale digital images for diverse environmental and scientific applications.
Digital Image
A digital image is a matrix of equally-sized square pixels that are each defined by two attributes:
- The position within the matrix (defined by row, column, and layer, or band)
- The value associated with that position
In the context of geospatial imagery, we refer to these pixel-based data structures as 'raster', as opposed to 'vector' data (points, lines, polygons). While vector and raster data work in conjunction with one another, they have different attributes and characteristics.
Understanding Digital Images
Before we discuss geospatial raster imagery, let's understand how a regular photograph is created. A digital photograph is made up of a grid of pixels, where each pixel has a specific color value, typically defined by three channels: Red, Green, and Blue (RGB). This combination of color values creates the images we see. The matrix structure of a digital image allows for efficient storage, manipulation, and analysis of the image data.
Geospatial Raster Imagery
Geospatial raster imagery, such as satellite images, follows the same principles as regular digital photographs but includes additional geospatial information. Each pixel in a geospatial raster image represents a specific area on the Earth's surface, and its value corresponds to a particular attribute, such as reflectance, temperature, or elevation. Unlike regular photographs, geospatial raster data often includes multiple spectral bands beyond the visible spectrum (e.g., near-infrared, thermal).
Google Earth Engine (GEE) provides powerful tools for working with digital images, making it possible to access, process, and analyze vast collections of satellite imagery and other geospatial datasets. GEE supports a variety of image processing tasks such as cloud masking, normalization, and feature extraction, which are essential for preparing data for analysis. Users can apply algorithms to classify land cover, detect changes over time, and derive meaningful insights from raw image data.
Integration of Raster and Vector Data
In geospatial analysis, raster and vector data often complement each other. For instance, vector data such as points, lines, and polygons can be overlaid on raster images to highlight specific areas of interest or to provide additional contextual information. Conversely, raster data can be used to generate new vector datasets through processes like classification and contour extraction.
Example - One Layer Grayscale
Let's start with a grayscale image of some peppers. This image is a rectangle that contains 384 rows and 512 columns of pixels. Because it is grayscale, there is only one brightness magnitude value (between 0 and 255) for each position. While humans see shapes, hues, and definition, a computer is only recording a brightness value for each pixel.
Below is a small segment of the matrix of values of the grayscale image between rows 50 and 60 and columns 50 and 60. Note that when working with imagery, the row/column position starts at the top left. Using our row/column designation:
grayscale(54, 50)
has a value of 52grayscale(50, 54)
has a value of 49grayscale(60, 60)
has a value of 47
Three Layer Color Image
The image is still the same, although it now has color. The number of rows, columns, and the size of each pixel remain the same, but unlike the grayscale image, we now have three layers, or bands. Each band represents the value in each of the three primary colors: red, green, and blue. If we look at the size of our matrix, it is now 384x512x3. For each row and column position, we now have three separate values between 0 and 255, which blend together into a color that we, as humans, can process.
Extension to Geospatial Imagery
Geospatial imagery poses two additional complications on top of a traditional color photograph. For analysis, we need to be able to tie our imagery to the real world. In the image of peppers, each pixel was built on an arbitrary axis of rows and columns that start at zero. However, this gives us no meaningful information about where in the world the red bell pepper is located. With geospatial imagery, we need to associate pixels with location. We need to know the exact size of the pixel and its position on Earth.
The high-resolution imagery below is produced by the 'National Agriculture Imagery Program'. This imagery has a red, green, and blue value and a latitude and longitude (-74.01, 40.72), in addition to a size (each pixel represents 1 meter by 1 meter). With this information, we can associate our pixel values with a location on Earth (New York) and aggregate the information we need.
Bands in Satellite Imagery
The other complexity we are faced with is that satellite imagery often has many layers. While our image of peppers had only red, green, and blue values, many satellite platforms are equipped to provide much more information. Most platforms have a value in the near-infrared range, while others might have numerous bands with different scales and resolutions. For instance, the Landsat 8 sensor has eleven bands capturing information from eleven different portions of the electromagnetic spectrum, including near-infrared (NIR) and thermal bands that are invisible to the human eye. Many machine learning projects, which we will explore in later labs, involve normalizing or transforming the information contained within each of these layers.
Note that while each pixel size must be the same within each individual layer, the layers can have different sizes. For instance, a satellite platform may have a 5-meter spatial resolution in the red/green/blue range but 60-meter resolution in the near-infrared range. While visualizing satellite imagery as a traditional photograph is a good starting point, there's much more information that we can incorporate into our analysis. We often build false or pseudocolor images by utilizing different combinations of bands, or we can focus on certain infrared signatures to detect asphalt roads and roofs. The possibilities of analysis within remote sensing are endless, but this also leads to complications.
As mentioned before, digital images are often referred to as 'raster' data. ESRI, makers of ArcGIS, has an excellent overview of using raster imagery in geospatial analysis featured here.
From Digital Image to Geospatial Image
To make the connection between our satellite imagery and real-world location even more complicated is the fact that a digital image is a flat, square surface - the earth is spherical. To make use of remote sensing imagery, we need to align the pixels in our image to a real-world location. There's quite a bit of mathematics involved in this process, but we will focus on two main components - establishing a Geographic Coordinate System (GCS) and a Projected Coordinate System (PCS).
The GCS defines the spherical location of the image, whereas the PCS defines how the grid around that location is constructed. Because the earth is not a perfect sphere, there are different GCS for different regions, such as 'North American Datum: 83', which is used to accurately define North America, and 'World Geodetic System of 1984', which is used globally.
The PCS then constructs a flat grid based on the GCS to create a relationship between each pixel of a 2-dimensional image to the corresponding area on the world. Some of the common PCS formats include EPSG, Albers Conic, Lambert, Eckert, Equidistant, etc. Different types of PCS are designed for different use cases, as the needs of a petroleum engineer working over a few square miles will differ from a climate change researcher measuring global change. Much of the discussion of defining GCS is outside the scope of this course, but the important thing to note is that a GCS defines the starting point for a projection.
ESRI has an article discussing the difference between GCS and PCS that provides further context on this relationship. While you should be aware of these two major terms - especially when you intend to run analysis on the data you download from GEE in another system, such as R, Python, or ArcGIS - GEE takes care of much of the complexity of these differences behind the scenes. Further documentation on the GEE methodology can be found here. In our first exercise, we will show you how to identify the PCS so you can understand the underlying structure.
Understanding the bands available in your datasets, identifying which bands are necessary (and appropriate) for your analysis, and ensuring that these data represent consistent spatial locations is essential.
Visualize a Digital Image
Let’s view a digital image in GEE to better understand this concept. There are three major ways to import imagery within GEE.
- Navigate to the GEE Datasets Page: You can go to the GEE datasets page, choose the image collection you would like to work with, and import the code example (click the button called
import
), which is normally located at the bottom of each dataset page. This code example is a standalone code chunk that will correctly visualize the data and is an excellent way to get an understanding of the different satellite platforms. Feel free to explore some datasets you are interested in, change variables and inputs to see what happens.
- Search in the Code Editor: In the search bar of the code editor, you can search for the specific imagery you are looking for. When you click on it, a pop-up window will come up that allows you to either import the image directly (bottom right) or copy the path to the image collection (left-hand side). They both work the same way; using the import button will incorporate it into the variable list directly (separated top section of the editor), where you have to specifically define the variable if you copy the path to the image collection.
- Define Area of Interest Using Geometry Drawing Tools: In the map window of GEE, click on the
point
geometry tool using the geometry drawing tools to define your area of interest. For the purpose of consistency in this exercise, place a point on the Virginia Tech Drillfield, which will bring you roughly to (-80.42, 37.23). As a reminder, you can find more information on geometry drawing tools in GEE’s Guides. Name the importpoint
.
Note: Some programming languages and frameworks read in latitude and longitude differently - Most read in the values as longitude/latitude. Double-check your values; if you are importing data from Google Maps, you will have to switch the latitude and longitude when using within GEE.
Example: Importing and Visualizing NAIP Imagery
-
Import NAIP imagery by searching for 'naip' and choosing the 'NAIP: National Agriculture Imagery Program' raster dataset. Name the import
naip
. -
Get a single, recent NAIP image over your study area and inspect it. Here's an example code snippet to get you started:
- JavaScript
- Python
// Define the point of interest
var point = ee.Geometry.Point([-80.42, 37.23]);
// Import the NAIP image collection
var naip = ee.ImageCollection('USDA/NAIP/DOQQ')
.filterBounds(point)
.filterDate('2020-01-01', '2021-01-01')
.sort('system:time_start', false);
// Get the most recent image
var recentNaip = naip.first();
// Center the map on the point of interest
Map.centerObject(point, 15);
// Add the recent NAIP image to the map
Map.addLayer(recentNaip, {bands: ['N', 'R', 'G'], max: 255}, 'Recent NAIP Image');
# Define the point of interest
point = ee.Geometry.Point([-80.42, 37.23])
# Import the NAIP image collection
naip = ee.ImageCollection('USDA/NAIP/DOQQ') \
.filterBounds(point) \
.filterDate('2020-01-01', '2021-01-01') \
.sort('system:time_start', False)
# Get the most recent image
recent_naip = naip.first()
# Create a map centered on the point of interest
Map = geemap.Map(center=[37.23, -80.42], zoom=15)
# Add the recent NAIP image to the map
Map.addLayer(recent_naip, {'bands': ['N', 'R', 'G'], 'max': 255}, 'Recent NAIP Image')
# Display the map
Map
- JavaScript
- Python
var lat = 37.22; var lon = -80.42; var zoom = 15
// Get a single NAIP image over the area of interest.
var image = ee.Image(ee.ImageCollection("USDA/NAIP/DOQQ")
.filterBounds(ee.Geometry.Point([lon, lat]))
.sort('system:time_start', false)
.first());
Map.centerObject(ee.Geometry.Point([lon, lat]), 18);
Map.addLayer(image, {}, 'Original image');
lat = 37.22; lon = -80.42; zoom = 15
# Get a single NAIP image over the area of interest.
image = ee.Image(ee.ImageCollection("USDA/NAIP/DOQQ")
.filterBounds(ee.Geometry.Point([lon, lat]))
.sort('system:time_start', False)
.first());
map = build_map(lat, lon, zoom, {}, image, name)
map
Evaluate the image object printed to the console by selecting the wrench and clicking on the "information" or "i" button in the upper left-hand set of options. Select a location on the map after clicking the "i" button to see the bands.
The following sentence is most relevant for the JavaScript, interaction version of this tutorial: Expand the property called bands
and expand one of the bands (0, for example). Note that the CRS transform is stored in the crs_transform
property underneath the band dropdown and the CRS is stored in the crs
property, which references an EPSG code.
EPSG Codes are 4-5 digit numbers that represent CRS definitions. The acronym EPSG, comes from the (now defunct) European Petroleum Survey Group. The CRS of this image is EPSG:26917. You can learn more about these codes from the EPSG homepage.
The CRS transform is a list [m00, m01, m02, m10, m11, m12]
in the notation of this reference. The CRS transform defines how to map pixel coordinates to their associated spherical coordinate through an affine transformation. While affine transformations are beyond the scope of this class, more information can be found at Rasterio, which provides detailed documentation for the popular Python library designed for working with geospatial data.
In addition to using the dropdowns, you can also access these data programmatically with the .projection()
method:
- JavaScript
- Python
// Display the projection of band 0
print('Inspect the projection of band 0:', image.select(0).projection());
# Display the projection of band 0
print('Inspect the projection of band 0:', image.select(0).projection().getInfo())
Note that the projection can differ by band, which is why it's good practice to inspect the projection of individual image bands. If you call .projection()
on an image for which the projection differs by band, you'll get an error. Exchange the NAIP imagery with the Planet SkySat MultiSpectral image collection, and note that the error occurs because the 'P' band has a different pixel size than the others. Explore the ee.Projection
docs to learn about useful methods offered by the Projection
object. To play with projections offline, try this tool.