基于对象的方法

图片对象是一组具有相同整数值的连通像素。分类、分箱和布尔值图片数据适合对象分析。

Earth Engine 提供了一些方法,可用于为每个对象分配唯一 ID、统计构成对象的像素数,以及计算与对象相交的像素值的统计信息。

热点

以下部分提供了将基于对象的方法应用于 Landsat 8 地表温度的示例,每个部分都基于前一个部分。运行以下代码段可生成基础图片:旧金山一小区域的热点(高于 303 开氏度)。

// Make an area of interest geometry centered on San Francisco.
var point = ee.Geometry.Point(-122.1899, 37.5010);
var aoi = point.buffer(10000);

// Import a Landsat 8 image, subset the thermal band, and clip to the
// area of interest.
var kelvin = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318')
  .select(['B10'], ['kelvin'])
  .clip(aoi);

// Display the thermal band.
Map.centerObject(point, 13);
Map.addLayer(kelvin, {min: 288, max: 305}, 'Kelvin');

// Threshold the thermal band to set hot pixels as value 1, mask all else.
var hotspots = kelvin.gt(303)
  .selfMask()
  .rename('hotspots');

// Display the thermal hotspots on the Map.
Map.addLayer(hotspots, {palette: 'FF0000'}, 'Hotspots');

如需了解 Python API 以及如何使用 geemap 进行交互式开发,请参阅 Python 环境页面。

import ee
import geemap.core as geemap
# Make an area of interest geometry centered on San Francisco.
point = ee.Geometry.Point(-122.1899, 37.5010)
aoi = point.buffer(10000)

# Import a Landsat 8 image, subset the thermal band, and clip to the
# area of interest.
kelvin = (
    ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318')
    .select(['B10'], ['kelvin'])
    .clip(aoi)
)

# Threshold the thermal band to set hot pixels as value 1, mask all else.
hotspots = kelvin.gt(303).selfMask().rename('hotspots')

# Define a map centered on Redwood City, California.
map_objects = geemap.Map(center=[37.5010, -122.1899], zoom=13)

# Add the image layers to the map.
map_objects.add_layer(kelvin, {'min': 288, 'max': 305}, 'Kelvin')
map_objects.add_layer(hotspots, {'palette': 'FF0000'}, 'Hotspots')

图 1. 旧金山某个区域的温度。温度高于 303 开氏度的像素以红色标记(热点)。

标签对象

标记对象通常是对象分析的第一步。在这里,connectedComponents() 函数用于识别图片对象并为每个对象分配唯一 ID;属于某个对象的所有像素都分配相同的整数 ID 值。结果是输入图片的副本,其中包含一个额外的“标签”波段,用于根据图片第一波段中的像素连接性将像素与对象 ID 值相关联。

// Uniquely label the hotspot image objects.
var objectId = hotspots.connectedComponents({
  connectedness: ee.Kernel.plus(1),
  maxSize: 128
});

// Display the uniquely ID'ed objects to the Map.
Map.addLayer(objectId.randomVisualizer(), null, 'Objects');

如需了解 Python API 以及如何使用 geemap 进行交互式开发,请参阅 Python 环境页面。

import ee
import geemap.core as geemap
# Uniquely label the hotspot image objects.
object_id = hotspots.connectedComponents(
    connectedness=ee.Kernel.plus(1), maxSize=128
)

# Add the uniquely ID'ed objects to the map.
map_objects.add_layer(object_id.randomVisualizer(), None, 'Objects')

请注意,最大补丁大小设置为 128 像素;由更多像素组成的对象会被遮盖。连接性由 ee.Kernel.plus(1) 内核指定,该内核定义了四邻接连接;使用 ee.Kernel.square(1) 表示八邻接。


图 2. 热点对象,通过唯一 ID 进行标签和样式设置。

对象大小

像素数

使用 connectedPixelCount() 图片方法计算构成对象的像素数。了解对象中的像素数有助于按大小遮罩对象和计算对象区域。以下代码段会将 connectedPixelCount() 应用于上一部分中定义的 objectId 图像的“标签”波段。

// Compute the number of pixels in each object defined by the "labels" band.
var objectSize = objectId.select('labels')
  .connectedPixelCount({
    maxSize: 128, eightConnected: false
  });

// Display object pixel count to the Map.
Map.addLayer(objectSize, null, 'Object n pixels');

如需了解 Python API 以及如何使用 geemap 进行交互式开发,请参阅 Python 环境页面。

import ee
import geemap.core as geemap
# Compute the number of pixels in each object defined by the "labels" band.
object_size = object_id.select('labels').connectedPixelCount(
    maxSize=128, eightConnected=False
)

# Add the object pixel count to the map.
map_objects.add_layer(object_size, None, 'Object n pixels')

connectedPixelCount() 会返回输入图像的副本,其中每个波段的每个像素都包含相邻连接像素的数量,具体取决于传递给 eightConnected 参数的布尔值参数确定的四邻或八邻连接规则。请注意,系统会为输入图像的每个波段独立确定连通性。在此示例中,我们将表示对象 ID 的单波段图像 (objectId) 作为输入提供,因此系统返回了包含“标签”波段(在输入图像中以此形式显示)的单波段图像,但现在这些值表示构成对象的像素数;每个对象的每个像素将具有相同的像素数值。


图 3. 按大小标记和设置样式的热点对象。

领域

通过将单个像素的面积乘以构成对象的像素数(由 connectedPixelCount() 确定)来计算对象面积。像素面积由 ee.Image.pixelArea() 生成的图片提供。

// Get a pixel area image.
var pixelArea = ee.Image.pixelArea();

// Multiply pixel area by the number of pixels in an object to calculate
// the object area. The result is an image where each pixel
// of an object relates the area of the object in m^2.
var objectArea = objectSize.multiply(pixelArea);

// Display object area to the Map.
Map.addLayer(objectArea,
             {min: 0, max: 30000, palette: ['0000FF', 'FF00FF']},
             'Object area m^2');

如需了解 Python API 以及如何使用 geemap 进行交互式开发,请参阅 Python 环境页面。

import ee
import geemap.core as geemap
# Get a pixel area image.
pixel_area = ee.Image.pixelArea()

# Multiply pixel area by the number of pixels in an object to calculate
# the object area. The result is an image where each pixel
# of an object relates the area of the object in m^2.
object_area = object_size.multiply(pixel_area)

# Add the object area to the map.
map_objects.add_layer(
    object_area,
    {'min': 0, 'max': 30000, 'palette': ['0000FF', 'FF00FF']},
    'Object area m^2',
)

结果是,图片中对象的每个像素都与对象的面积(以平方米为单位)相关。在此示例中,objectSize 图片包含单个波段,如果它是多波段图片,则乘法运算会应用于图片的每个波段。

按大小过滤对象

对象大小可用作遮罩条件,以便将分析重点放在特定大小的对象上(例如,遮盖过小的对象)。在这里,上一步中计算出的 objectArea 图片用作掩码,用于移除面积小于 1 公顷的对象。

// Threshold the `objectArea` image to define a mask that will mask out
// objects below a given size (1 hectare in this case).
var areaMask = objectArea.gte(10000);

// Update the mask of the `objectId` layer defined previously using the
// minimum area mask just defined.
objectId = objectId.updateMask(areaMask);
Map.addLayer(objectId, null, 'Large hotspots');

如需了解 Python API 以及如何使用 geemap 进行交互式开发,请参阅 Python 环境页面。

import ee
import geemap.core as geemap
# Threshold the `object_area` image to define a mask that will mask out
# objects below a given size (1 hectare in this case).
area_mask = object_area.gte(10000)

# Update the mask of the `object_id` layer defined previously using the
# minimum area mask just defined.
object_id = object_id.updateMask(area_mask)
map_objects.add_layer(object_id, None, 'Large hotspots')

结果是 objectId 图片的副本,其中面积小于 1 公顷的对象被遮盖。

图 4a. 热点对象,按唯一 ID 标记和设置样式。 图 4b. 按最小面积(1 公顷)过滤的热点对象。

区域统计信息

reduceConnectedComponents() 方法会将缩减器应用于构成唯一对象的像素。以下代码段使用它来计算热点对象的平均温度。reduceConnectedComponents() 要求输入图像包含要缩减的波段(或波段)以及用于定义对象标签的波段。在这里,objectID“标签”图像波段会添加到 kelvin 温度图像中,以构建合适的输入图像。

// Make a suitable image for `reduceConnectedComponents()` by adding a label
// band to the `kelvin` temperature image.
kelvin = kelvin.addBands(objectId.select('labels'));

// Calculate the mean temperature per object defined by the previously added
// "labels" band.
var patchTemp = kelvin.reduceConnectedComponents({
  reducer: ee.Reducer.mean(),
  labelBand: 'labels'
});

// Display object mean temperature to the Map.
Map.addLayer(
  patchTemp,
  {min: 303, max: 304, palette: ['yellow', 'red']},
  'Mean temperature'
);

如需了解 Python API 以及如何使用 geemap 进行交互式开发,请参阅 Python 环境页面。

import ee
import geemap.core as geemap
# Make a suitable image for `reduceConnectedComponents()` by adding a label
# band to the `kelvin` temperature image.
kelvin = kelvin.addBands(object_id.select('labels'))

# Calculate the mean temperature per object defined by the previously added
# "labels" band.
patch_temp = kelvin.reduceConnectedComponents(
    reducer=ee.Reducer.mean(), labelBand='labels'
)

# Add object mean temperature to the map and display it.
map_objects.add_layer(
    patch_temp,
    {'min': 303, 'max': 304, 'palette': ['yellow', 'red']},
    'Mean temperature',
)
display(map_objects)

结果是输入图片的副本,其中不包含用于定义对象的波段,其中像素值表示每个对象在每个波段中的减小结果。


图 5. 按平均温度汇总和设置样式的热点对象像素。