#ImageCollection
Found a striking #lichen on a large decaying tree trunk in moist coniferous forest canyon. In dry conditions thallus is a bright pale green patch with pale pink apothecia. With rainfall/moisture the thallus becomes deeper green and apothecia orangish. Fairly common w. Montana.
November 24, 2025 at 5:09 AM
Found this single specimen in flower at Blue Mountain (Missoula, MT) the other day. This spot consistently has the earliest flowering Cous Biscuitroot #wildflower. Meriwether Lewis collected a plant in 1806 and noted Native Americans then ate the root as a biscuit.
April 1, 2025 at 12:46 AM
Morning walk with Max, (well, wasn't noon yet 🫠) with native flowers jumping up to show their colors. Description of each in the Alt text. Tomorrow I'll try to take some I noticed this evening but was too tired to add to the walk.
April 16, 2025 at 5:05 AM
#Fungi finding tip: We're having some rain with warmer temps. While #birding I kept an eye to the ground and an ear to the trees. Was able to spy cup fungi (pictured, at a spot usually productive) due to the water inside the cup reflecting up...can be seen even with grasses over the top 😊
May 14, 2025 at 4:28 AM
July 2025's High-Resolution Imagery Collections – Pléiades 1 – Europe (Minus Russia), February to May 2025. See it in this month's issue of the #GeoSpatialTimes newsletter!

See it: apollomapping.com/blog/high-re...

#ImageHunter #ImageCollection
July 15, 2025 at 2:15 PM
"The ImageCollection editor remembers the character selected as the file name and size separator, from the previous use of the dialog."

Is it weird that I am genuinely excited by this?

blogs.embarcadero.com/improvements...
Improvements to the VCL Image Collection Editor in 12.3
blogs.embarcadero.com
March 24, 2025 at 8:25 PM
To create a single histogram, or one for each image in the collection? For the latter I think the problem is that an imagecollection treats each image independently. To have all values accessible at once doesn't sound like something gee would be good at (?)
October 23, 2024 at 8:34 PM
Apply a function with a loop for in imagecollection
I am trying to apply a mask to a imagecollection, I want to a apply this mask image a image, because if I apply the mask to the whole collection, I cant extract values by points. I am using a mask of fitoprincipe, https://github.com/fitoprincipe/geetools-code-editor/wiki/Cloud-Masks But when I apply this I can't get it to mask anything. Outline_Trigo is a perimeter shape Outline.shp points is a points shape points_all.shp How could I do the loop, I can't get it to work with either for or while, and I only find information about doing it with .map or .iterate. // Creamos la función que nos calcula el indice del NDVI function NDVI(entrada){ var ndvi = entrada.addBands(entrada.normalizedDifference(['B8','B4']).rename('NDVI')) return (ndvi) } var cloud_masks = require('users/fitoprincipe/geetools:cloud_masks'); var sentinel2function = cloud_masks.sentinel2(); // Creamos la coleccion inicial, filtramos por fechas y lugar, añadimos la banda del NDVI var coleccion_NDVI = ee.ImageCollection('COPERNICUS/S2_SR') .filterBounds(Outline_Trigo) .filterDate('2018-03-01','2018-03-15'); Map.centerObject(Outline_Trigo,15); Map.addLayer(Outline_Trigo,{color: '006600', strokeWidth: 8},"Outline_Trigo"); print(coleccion_NDVI, 'Colección NDVI'); var lista=coleccion_NDVI.toList(coleccion_NDVI.size()) var i=0; var imagen; var longitud= lista.size().getInfo() //var fecha; for(var i = 0; i
gis.stackexchange.com
September 9, 2026 at 3:11 AM
What's the use of ImageCollection.errorMatrix() in Google Earth Engine?
In the docs there are two versions of the errorMatrix function: ee.FeatureCollection.errorMatrix and ee.ImageCollection.errorMatrix I've been sampling points from my classified images to create error matrices using the former, which is working just fine, but I'm curious about when/how the ImageCollection version is used. I assumed ImageCollection.errorMatrix would implicitly convert pixels to points, then check if my classification band matched a reference band. It's not clear if the Image Collection should be a collection of images with two bands or two images with one band each (reference and classification), or something else. Any combination I try just gives me a 1*1 EM with a value of 0. The two arrangements that I thought might work: var classifiedImage = ee.Image(someClassifiedImage) //Some classified image with two bands: "reference" and "classification" ///Create image collection. Using one image now, but could probably do multiple var classifiedImageCollection = ee.ImageCollection.fromImages([classifiedImage]); var imageEM = classifiedImageCollection.errorMatrix("reference", "classification") Or var referenceImage= ee.Image(someReferenceImage) var classifiedImage = ee.Image(someClassifiedImage) var classifiedImageCollection= ee.ImageCollection.fromImages([referenceImage, classifiedImage]); var imageEM = classifiedImageCollection.errorMatrix("tailings", "classification") Both of these produce an error matrix of [[0]] To make it a little more confusing, the args for ImageCollection.errorMatrix are identical to those of ee.FeatureCollection.errorMatrix, including: this:collection (FeatureCollection): The input collection Again, I can just sample the image and get an EM from that, but I'm curious if there's a way to make this work.
gis.stackexchange.com
September 7, 2026 at 9:04 PM
Exporting values from Images in ImageCollection to CSV
I am working with rainfall monthly totals for a 30-year period using CHIRPS pentad. //1.Reference Period var historical = ee.List.sequence(1991, 2020) var months = ee.List.sequence(1, 5) //print(historical) //2.Map over the years and create a monthly totals collection var monthlyImages = historical.map(function(year){ return months.map(function(month){ var filtered = chirps .filter(ee.Filter.calendarRange(year, year, 'year')) .filter(ee.Filter.calendarRange(month, month, 'month')) var monthly = filtered.sum(); return monthly.set({'month': month, 'year': year}) }) }).flatten() print(monthlyImages) //3. Create an Image Collection for each month of each year var monthlyCol = ee.ImageCollection.fromImages(monthlyImages) print(monthlyCol) //4. Convert to Feature Collection var montlyRainfall = ee.FeatureCollection(monthlyImages) // Export.table.toDrive({ // collection: monthlyRainfall, // fileNamePrefix: 'rainfallbymonth', // fileFormat: 'CSV'}) I have been able to get an Image Collection with 150 images for the months I require. I am looking to export each monthly totals(sum) to a table and obtain results from my geometry. Transforming my Image Collection to a Feature Collection and exporting to CSV has worked with the correct dates but it just doesn't contain the values from my 'precipitation' band which is the sum that I filtered in the first code of block. I understand I need to transform my image collection to a feature collection and tell it to assign the dictionary values to my table I just have not figured out how to do it. I am also not sure if I need to Reduce.sum again even though I have filtered my monthly images totals using .sum already.
gis.stackexchange.com
August 9, 2026 at 11:08 AM
Export an Landsat image from ImageCollection from GEE to drive
I'm trying to export an Landsat image from GEE to a Drive, but the Export function that I applied gets 14 images (13 contain NoData and 1 the image). This is my code: function applyScaleFactors(image) { var opticalBands = image.select('SR_B.').multiply(0.0000275).add(-0.2); return image.addBands(opticalBands, null, true); } function maskClouds(image) { var cloudFree = bitwiseExtract(image.select('QA_PIXEL'), 0, 5).eq(0) return image .updateMask(cloudFree) } function bitwiseExtract(value, fromBit, toBit) { if (toBit === undefined) toBit = fromBit var maskSize = ee.Number(1).add(toBit).subtract(fromBit) var mask = ee.Number(1).leftShift(maskSize).subtract(1) return value.rightShift(fromBit).bitwiseAnd(mask) } var Addband_NDVI=function (image){ var NDVI=image.normalizedDifference(['SR_B4','SR_B3']).rename('NDVI') return image.addBands(NDVI);} var collection = ee.ImageCollection("LANDSAT/LE07/C02/T1_L2") .filterDate('2000-01-01', '2001-01-01') // End date is exclusive .filter(ee.Filter.metadata('WRS_PATH', "greater_than", 171)) .filter(ee.Filter.metadata('WRS_PATH', "less_than", 206)) .filter(ee.Filter.metadata('WRS_ROW', "greater_than", 27)) .filter(ee.Filter.metadata('WRS_ROW', "less_than", 37)) .map(applyScaleFactors) .map(Addband_NDVI) .select('NDVI') var pathRowCollection = ee.ImageCollection(ee.Join.saveAll('images') .apply({ primary: collection .distinct(['WRS_PATH', 'WRS_ROW']), secondary: collection, condition: ee.Filter.and( ee.Filter.equals({leftField: 'WRS_PATH', rightField: 'WRS_PATH'}), ee.Filter.equals({leftField: 'WRS_ROW', rightField: 'WRS_ROW'}) ) }) .map(function (image) { return ee.ImageCollection(ee.List(image.get('images'))) .median() // Include row/path for the composite .copyProperties(image, ['WRS_PATH', 'WRS_PATH']) }) ) var ten= pathRowCollection.limit(1); print(ten) Map.addLayer(ten) Export.image.toDrive({ image: ten, scale:30, description: 'prova2M', region: geometry, maxPixels:3e12, crs: 'EPSG:4326' }); My goal is export a single Landsat Image (as displayed on the map layer). Is there an other function that allows get this?
gis.stackexchange.com
August 8, 2026 at 12:12 PM
Create array from EE image after reducing image collection in Google Earth Engine
I'm trying to create an array from an EE image, following the accepted answer in this post. However, instead of grabbing a specific image, I start with an EE imageCollection, then reduce it to an image (taking the median across cloud free pixels). When grabbing a specific image, I get the expected shape of the np array; however, I'm not able to get the expected shape when starting with an imageCollection. (This is a similar issue as described in this post, although I'm not sure of the solution in this context. In addition, this post gets close to what I'm looking for -- but returns a 1d array, not a 2d array). #### Set up import ee import numpy as np import geetools from geetools import ui, cloud_mask ee.Authenticate() ee.Initialize() #### Create AOI aoi = ee.Geometry.Polygon( [[[-110.8, 44.7], [-110.8, 44.6], [-110.6, 44.6], [-110.6, 44.7]]], None, False) #### Create np array, starting from image # This works! img = ee.Image('LANDSAT/LC08/C01/T1_SR/LC08_038029_20180810') band_arrs = img.sampleRectangle(region=aoi) band_arr_b1 = band_arrs.get('B1') np_arr_b1 = np.array(band_arr_b1.getInfo()) np_arr_b1.shape # Returns --> (373, 531) #### Create np array, starting from imageCollection # This doesn't seem to work mask_l8SR_all = cloud_mask.landsatSR() img = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')\ .filterDate('2017-01-01', '2020-12-31')\ .map(mask_l8SR_all)\ .median()\ .multiply(0.0001) band_arrs = img.sampleRectangle(region=aoi) band_arr_b1 = band_arrs.get('B1') np_arr_b1 = np.array(band_arr_b1.getInfo()) np_arr_b1.shape # Returns --> (1, 1) Google Colab link to the above code
gis.stackexchange.com
August 6, 2026 at 10:14 PM
Mask out non-bare soil pixels in Landsat8
I aim to create an Landsat8 image for bare-soil (no vegetation). To do this, I plan to derive the quantile of the bare soil index for each pixel and mask out pixels where the bare soil index has a value lower than the 95th quantile. I got until the point where I added the bare soil index to the imagecollection, and created an image of the 95th quantile of the bare soil index for each pixel. But how can I then use this as a mask? //Imports (country borders and landsat8 collection) var countries = ee.FeatureCollection("USDOS/LSIB_SIMPLE/2017"), L8 = ee.ImageCollection("LANDSAT/LC08/C02/T1_L2"); // Define a function to add BSI (bare soil index) var addBSI = function(image){ var bsi = image.expression( '((SWIR+RED)-(NIR+BLUE)) / ((SWIR+RED) + (NIR + BLUE))', { 'RED': image.select('SR_B4'), 'SWIR': image.select('SR_B7'), 'NIR': image.select('SR_B5'), 'BLUE': image.select('SR_B2') }).rename('BSI'); return image.addBands(bsi); }; // Create 'collection', filtering landsat collection and adding bare soil index var collection = ee.ImageCollection(L8 // filter images within range (2014-2022) .filterDate("2014-01-01", "2022-12-31") // incldue geographic filter on created shape .filterBounds(netherlands) //filter away images with many clouds .filterMetadata("CLOUD_COVER", "less_than", 10) //add bare soil index to collection .map(addBSI)); //Create image of 95th quantile of bare soil index var bsi95 = collection.select('BSI').reduce(ee.Reducer.percentile([95])) //Mask out pixels where BSI is lower than the pixel-specific 95th quantile of the BSI //?
gis.stackexchange.com
August 4, 2026 at 4:10 PM
Dictionary.get: Dictionary does not contain key: bucketMeans Error when trying to apply Otsu threshold
I am trying to apply Otsu's threshold to remove water from my NDVI image. But when running the code I get the error: ImageCollection (Error) Error in map(ID=1_2_LE07_020039_20220510): Dictionary.get: Dictionary does not contain key: bucketMeans. The image shows nothing when I try to display the image with Map.addLayer, so they probably have null. I am wondering if there's anyway to filter them out so that I don't get the error. Or any other idea would be helpful. var PEI = ee.Geometry.Polygon( [[[-88.64042172041307, 30.446701603950796], [-88.64042172041307, 30.32290398952697], [-88.49004635420214, 30.32290398952697], [-88.49004635420214, 30.446701603950796]]], null, false); Map.centerObject(PEI, 15) var otsu = function(histogram) { var counts = ee.Array(ee.Dictionary(histogram).get('histogram')); var means = ee.Array(ee.Dictionary(histogram).get('bucketMeans')); var size = means.length().get([0]); var total = counts.reduce(ee.Reducer.sum(), [0]).get([0]); var sum = means.multiply(counts).reduce(ee.Reducer.sum(), [0]).get([0]); var mean = sum.divide(total); var indices = ee.List.sequence(1, size); // Compute between sum of squares, where each mean partitions the data. var bss = indices.map(function(i) { var aCounts = counts.slice(0, 0, i); var aCount = aCounts.reduce(ee.Reducer.sum(), [0]).get([0]); var aMeans = means.slice(0, 0, i); var aMean = aMeans.multiply(aCounts) .reduce(ee.Reducer.sum(), [0]).get([0]) .divide(aCount); var bCount = total.subtract(aCount); var bMean = sum.subtract(aCount.multiply(aMean)).divide(bCount); return aCount.multiply(aMean.subtract(mean).pow(2)).add( bCount.multiply(bMean.subtract(mean).pow(2))); }); //print(ui.Chart.array.values(ee.Array(bss), 0, means)); // Return the mean value corresponding to the maximum BSS. return means.sort(bss).get([-1]); }; var threshold_func = function(image) { image = ee.Image(image).select('NDVI') var histogram = image.reduceRegion({ reducer: ee.Reducer.histogram() .combine('mean', null, true) .combine('variance', null, true), geometry: PEI, scale: 10, bestEffort: true }); var threshold = otsu(histogram.get('NDVI_histogram')); var water_removed = image.gt(threshold).selfMask(); return water_removed; }; var addNDVI = function(img) { var ndvi = img.normalizedDifference(['B5','B4']).rename('NDVI') return img.addBands(ndvi) } var addNDVIpre8 = function(img) { var ndvi = img.normalizedDifference(['B4','B3']).rename('NDVI') return img.addBands(ndvi) } var landsat5 = ee.ImageCollection("LANDSAT/LT05/C02/T1_TOA").filterBounds(PEI) .filterMetadata('CLOUD_COVER', 'less_than', 20) .select(['B5', 'B4', 'B3', 'QA_PIXEL']) .map(addNDVIpre8) print('l5', landsat5) var landsat7 = ee.ImageCollection("LANDSAT/LE07/C02/T1_TOA").filterBounds(PEI) .filterMetadata('CLOUD_COVER', 'less_than', 20) .select(['B5', 'B4', 'B3', 'QA_PIXEL']) .map(addNDVIpre8) print('l7', landsat7) var landsat8 = ee.ImageCollection("LANDSAT/LC08/C02/T1_TOA").filterBounds(PEI) .filterMetadata('CLOUD_COVER', 'less_than',20) .select(['B5', 'B4', 'B3', 'QA_PIXEL']) .map(addNDVI) print('l8', landsat8) var landsat = landsat5.merge(landsat7).merge(landsat8) print('total', landsat) //var landsatlist = landsat.toList(landsat.size()); var landsat_otsu = landsat.map(threshold_func) print(landsat_otsu) Link: https://code.earthengine.google.com/46a1c8ed3b8ae773fea005a65ac87576
gis.stackexchange.com
July 30, 2026 at 8:05 PM