Google Earth Engine(GEE)——提取指定矢量集合中的NDVI值并附时间属性

本文介绍了如何在GoogleEarthEngine中将影像数据转化为数组,通过数组的轴进行切片和排序,特别是针对NDVI指数进行操作。首先,将图像集合转为数组图像,然后提取NDVI并排序,选取最高NDVI的20%像素,最后通过平均化减少计算得到最高NDVI的平均值。这种方法用于影像分析,如马赛克制作和特征选择。
摘要由CSDN通过智能技术生成

本教程的主要目的是实现影像转化为数组,然后我们需要直到其转化为的数组的轴,然后根据轴的信息进行切片,切片后完成时间属性的标准转化,这里一定要对影像结果提取完成后再对矢量集合进行操作,最后就可以提取指定的属性信息。

阵列排序对于获得自定义质量的马赛克非常有用,这涉及到根据不同波段的值reduce图像波段的子集。下面的例子按NDVI排序,然后得到集合中NDVI值最高的观测值子集的值:

与线性建模的例子一样,使用arraySlice()沿波段轴将感兴趣的波段与排序索引(NDVI)分开。然后用arraySort()按排序索引对感兴趣的波段进行排序。在像素按NDVI降序排序后,沿imageAxis使用arraySlice(),得到20%的最高NDVI像素。最后,沿着imageAxis应用arrayReduce(),用一个平均减速器得到最高NDVI像素的平均值。最后一步是将阵列图像转换为多波段图像进行显示 

函数:

toArray()

Converts an image collection into an image of 2D arrays. At each pixel, the images that have valid (unmasked) values in all bands are laid out along the first axis of the array in the order they appear in the image collection. The bands of each image are laid out along the second axis of the array, in the order the bands appear in that image. The array element type will be the union of the types of each band.

将一个图像集合转换为一个二维数组的图像。在每个像素点上,在所有波段中具有有效(未屏蔽)值的图像,按照它们在图像集合中出现的顺序,沿着阵列的第一轴排列。每幅图像的波段沿数组的第二轴排列,以波段在该图像中出现的顺序排列。数组元素的类型将是每个波段的类型的结合。

Arguments:

this:collection (ImageCollection):

Image collection to convert to an array image. Bands must have scalar values, not array values.

Returns: Image

first(image2)

Selects the value of the first value for each matched pair of bands in image1 and image2. If either image1 or image2 has only 1 band, then it is used against all the bands in the other image. If the images have the same number of bands, but not the same names, they're used pairwise in the natural order. The output bands are named for the longer of the two inputs, or if they're equal in length, in image1's order. The type of the output pixels is the union of the input types.

 选择图像1和图像2中每一对匹配的波段的第一个值。如果图像1或图像2只有1个条带,那么它将被用来对付另一个图像中的所有条带。如果图像有相同数量的条带,但名字不一样,它们就按自然顺序成对使用。输出的带子以两个输入中较长的命名,或者如果它们的长度相等,则以图像1的顺序命名。输出像素的类型是输入类型的联合。

Arguments:

this:image1 (Image):

The image from which the left operand bands are taken.

image2 (Image):

The image from which the right operand bands are taken.

Returns: Image

arraySlice(axisstartendstep)

Creates a subarray by slicing out each position along the given axis from the 'start' (inclusive) to 'end' (exclusive) by increments of 'step'. The result will have as many dimensions as the input, and the same length in all directions except the slicing axis, where the length will be the number of positions from 'start' to 'end' by 'step' that are in range of the input array's length along 'axis'. This means the result can be length 0 along the given axis if start=end, or if the start or end values are entirely out of range.

创建一个子数组,沿着给定的轴从'开始'(包括)到'结束'(不包括)按'步长'的增量切出每个位置。结果将具有与输入相同的维度,并且在所有方向上具有相同的长度,除了切片轴之外,长度将是沿'轴'的输入数组长度范围内的从'开始'到'结束'的'步'的位置数。这意味着如果start=end,或者start或end的值完全不在范围内,结果可以是沿给定轴的长度为0。 

Arguments:

this:input (Image):

Input array image.

axis (Integer, default: 0):

Axis to subset.

start (Image, default: null):

The coordinate of the first slice (inclusive) along 'axis'. Negative numbers are used to position the start of slicing relative to the end of the array, where -1 starts at the last position on the axis, -2 starts at the next to last position, etc. There must one band for start indices, or one band per 'input' band. If this argument is not set or masked at some pixel, then the slice at that pixel will start at index 0.

end (Image, default: null):

The coordinate (exclusive) at which to stop taking slices. By default this will be the length of the given axis. Negative numbers are used to position the end of slicing relative to the end of the array, where -1 will exclude the last position, -2 will exclude the last two positions, etc. There must be one band for end indices, or one band per 'input' band. If this argument is not set or masked at some pixel, then the slice at that pixel will end just after the last index.

step (Integer, default: 1):

The separation between slices along 'axis'; a slice will be taken at each whole multiple of 'step' from 'start' (inclusive) to 'end' (exclusive). Must be positive.

Returns: Image

arraySort(keys)

Sorts elements of each array pixel along one axis.沿着一个轴对每个阵列像素的元素进行排序。

Arguments:

this:image (Image):

Array image to sort.

keys (Image, default: null):

Optional keys to sort by. If not provided, the values are used as the keys. The keys can only have multiple elements along one axis, which determines the direction to sort in.

Returns: Image

arrayFlatten(coordinateLabels, separator)

Converts a single band image of equal-shape multidimensional pixels to an image of scalar pixels, with one band for each element of the array.

将等形多维像素的单波段图像转换为标量像素的图像,阵列的每个元素都有一个波段。

Arguments:

this:image (Image):

Image of multidimensional pixels to flatten.

coordinateLabels (List):

Name of each position along each axis. For example, 2x2 arrays with axes meaning 'day' and 'color' could have labels like [['monday', 'tuesday'], ['red', 'green']], resulting in band names'monday_red', 'monday_green', 'tuesday_red', and 'tuesday_green'.

separator (String, default: "_"):

Separator between array labels in each band name.

Returns: Image

 

arrayProject(axes)

Projects the array in each pixel to a lower dimensional space by specifying the axes to retain. Dropped axes must be at most length 1.

通过指定要保留的轴,将每个像素的数组投影到一个较低维度的空间。被放弃的轴必须最多长度为1。

Arguments:

this:input (Image):

Input image.

axes (List):

The axes to retain. Other axes will be discarded and must be at most length 1.

Returns: Image

代码:

//导入需要进行采样的点数据
var table = ee.FeatureCollection("projects/ee-nimrabanuhphd18/assets/Karnataka"),
    fc = /* color: #d63000 */ee.FeatureCollection(
        [ee.Feature(
            ee.Geometry.Point([74.99433244730658, 15.254586051704365]),
            {
              "system:index": "0"
            }),
        ee.Feature(
            ee.Geometry.Point([74.99438595166671, 15.518067901203736]),
            {
              "system:index": "1"
            }),
        ee.Feature(
            ee.Geometry.Point([75.25805782666671, 15.506158494397534]),
            {
              "system:index": "2"
            }),
        ee.Feature(
            ee.Geometry.Point([75.26904415479171, 15.402914915549081]),
            {
              "system:index": "3"
            }),
        ee.Feature(
            ee.Geometry.Point([75.21685909619796, 15.296970799825159]),
            {
              "system:index": "4"
            })]);
var roi = fc

//NDVI函数
var getNDVI = function(img){
  return img.normalizedDifference(['sur_refl_b02','sur_refl_b01']).rename('ndvi')
    .copyProperties(img, ['system:time_start'])
};

//添加时间属性给每一个需要采样的点
var addTime = function(img){
  return img.addBands(ee.Image.constant(img.get('system:time_start')).long().rename('time'))
};

//进行应先国家在
var MOD = ee.ImageCollection('MODIS/006/MOD09A1').
          filterDate('2022-11-15','2023-04-01').
          filterBounds(roi);
print(MOD)
var NDVI = MOD.map(getNDVI).map(addTime);
print(NDVI.first())

//讲影像转化为数组
// see https://developers.google.com/earth-engine/guides/arrays_sorting_reducing
var array = NDVI.toArray()
Map.addLayer(array, {}, 'array', false) // for inspector

// 预设要进行数组切片的轴
var imageAxis = 0;
var bandAxis = 1;

// 获取NDVI切片和感兴趣的波段。
var bandNames = NDVI.first().bandNames();
var bands = array.arraySlice(bandAxis, 0, bandNames.length());
var ndvi = array.arraySlice(bandAxis, 0, 1);

// 从高到低筛选数组
var sorted = bands.arraySort(ndvi.multiply(-1));
Map.addLayer(sorted, {}, 'sorted', false) // for inspector, from high to low

// 获取每个像素的最高NDVI观测值。
var numImages = 1
var highestNdvi = sorted.arraySlice(imageAxis, 0, numImages);

// 将reduce的阵列图像变成多波段图像进行显示。
var maxImage = highestNdvi.arrayProject([bandAxis]).arrayFlatten([bandNames]);

print(maxImage)
Map.addLayer(maxImage, {}, 'max NDVI value + time', false)

// 获取值和事件,因为这里由高到低排行了,所以只选取第一个值即可
var maxValues = maxImage.reduceRegions(fc, ee.Reducer.first(), 100)

// 将其事件标准化
maxValues = maxValues.map(function(f) {
  return f.set({ time: ee.Date(f.get('time')).format('YYYY-MM-dd HH:mm:ss') })
})

print(maxValues)

代码2:

// Define a function that scales and masks Landsat 8 surface reflectance images
// and adds an NDVI band.
function prepSrL8(image) {
  // Develop masks for unwanted pixels (fill, cloud, cloud shadow).
  var qaMask = image.select('QA_PIXEL').bitwiseAnd(parseInt('11111', 2)).eq(0);
  var saturationMask = image.select('QA_RADSAT').eq(0);

  // Apply the scaling factors to the appropriate bands.
  var opticalBands = image.select('SR_B.').multiply(0.0000275).add(-0.2);
  var thermalBands = image.select('ST_B.*').multiply(0.00341802).add(149.0);

  // Calculate NDVI.
  var ndvi = opticalBands.normalizedDifference(['SR_B5', 'SR_B4'])
      .rename('NDVI');

  // Replace original bands with scaled bands, add NDVI band, and apply masks.
  return image.addBands(opticalBands, null, true)
      .addBands(thermalBands, null, true)
      .addBands(ndvi)
      .updateMask(qaMask)
      .updateMask(saturationMask);
}

// Define an arbitrary region of interest as a point.
var roi = ee.Geometry.Point(-122.26032, 37.87187);

// Load a Landsat 8 surface reflectance collection.
var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
  // Filter to get only imagery at a point of interest.
  .filterBounds(roi)
  // Filter to get only six months of data.
  .filterDate('2021-01-01', '2021-07-01')
  // Prepare images by mapping the prepSrL8 function over the collection.
  .map(prepSrL8)
  // Select the bands of interest to avoid taking up unneeded memory.
  .select('SR_B.|NDVI');

// Convert the collection to an array.
var array = collection.toArray();

// Label of the axes.
var imageAxis = 0;
var bandAxis = 1;

// Get the NDVI slice and the bands of interest.
var bandNames = collection.first().bandNames();
var bands = array.arraySlice(bandAxis, 0, bandNames.length());
var ndvi = array.arraySlice(bandAxis, -1);

// Sort by descending NDVI.
var sorted = bands.arraySort(ndvi.multiply(-1));

// Get the highest 20% NDVI observations per pixel.
var numImages = sorted.arrayLength(imageAxis).multiply(0.2).int();
var highestNdvi = sorted.arraySlice(imageAxis, 0, numImages);

// Get the mean of the highest 20% NDVI observations by reducing
// along the image axis.
var mean = highestNdvi.arrayReduce({
  reducer: ee.Reducer.mean(),
  axes: [imageAxis]
});

// Turn the reduced array image into a multi-band image for display.
var meanImage = mean.arrayProject([bandAxis]).arrayFlatten([bandNames]);
Map.centerObject(roi, 12);
Map.addLayer(meanImage, {bands: ['SR_B6', 'SR_B5', 'SR_B4'], min: 0, max: 0.4});

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是使用Google Earth Engine获取逐日NDVI的代码示例: ```javascript // 设置ROI var roi = ee.Geometry.Rectangle([xmin, ymin, xmax, ymax]); // 设置起始和结束日期 var startDate = ee.Date('2019-01-01'); var endDate = ee.Date('2019-12-31'); // 加载MODIS数据 var modis = ee.ImageCollection('MODIS/006/MOD13A1') .filterBounds(roi) .filterDate(startDate, endDate) .select('NDVI'); // 定义函数计算每个图像的年份和日数 var addDate = function(image) { var doy = image.date().getRelative('day', 'year'); return image.addBands(doy).addBands(image.date().get('year')); }; // 对图像集应用函数 var modisWithDate = modis.map(addDate); // 定义函数计算每个年份和日数的平均NDVI var reduceDaily = function(imageCollection, year, doy) { var filtered = imageCollection.filter(ee.Filter.calendarRange(year, year, 'year')) .filter(ee.Filter.calendarRange(doy, doy, 'day_of_year')); return filtered.mean().set('year', year).set('doy', doy); }; // 创建一个二维数组,其第一维表示年份,第二维表示一年的日数 var years = ee.List.sequence(startDate.get('year'), endDate.get('year')); var days = ee.List.sequence(1, 365); // 对所有年份和日数应用reduceDaily函数 var dailyNDVI = ee.ImageCollection.fromImages(years.map(function(y){ return days.map(function(d){ return reduceDaily(modisWithDate, y, d); }); }).flatten()); // 打印输出结果 print(dailyNDVI); ``` 在上述代码,首先定义了一个感兴趣区域(ROI),然后加载了2000年至今的MODIS NDVI数据,并对其进行了筛选。接着定义了两个函数,一个函数用于向每个图像添加年份和日数作为带宽,另一个函数用于计算每个年份和日数的平均NDVI。最后,将所有年份和日数应用到reduceDaily函数,生成逐日的NDVI
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

此星光明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值