1

I am trying to export an image without having to specify the scale and the CRS in the Export.image.toDrive function. In order to do this I found online a solution which I tried to apply it on my dataset but it shows an error saying

Line 46: brdf.projection is not a function.

How can I apply the solution showing in the link to my code?

Map.centerObject(table);

// Here I'm trying to set the Bits according to table 'Bitmask for QF_Cloud_Mask'
var mask_vnpa2_img = function(image) {
  var qa = image.select('QF_Cloud_Mask');
  //var landWaterBackground = bitwiseExtract(qa, 1, 3)
  var cloudMaskQuality = bitwiseExtract(qa, 4, 5)
  var cloudDetectionResultsConfidenceIndicator = bitwiseExtract(qa, 6, 7)
  var shadowDetected = bitwiseExtract(qa, 8)
  var cirrusDetection = bitwiseExtract(qa, 9)
  var snowIceSurface = bitwiseExtract(qa, 10)

  var mask = ee.Image(1)
    //.and(landWaterBackground.eq(1)) // Land no Desert
    .and(cloudMaskQuality.eq(3)) // High
    .and(cloudDetectionResultsConfidenceIndicator.eq(0)) // Confident Clear
    .and(shadowDetected.eq(0)) // No
    .and(cirrusDetection.eq(0)) // No cloud
    .and(snowIceSurface.eq(0)) // No Snow/Ice
    
  return image.updateMask(mask);
};

var dataset = ee.ImageCollection('NOAA/VIIRS/001/VNP46A2')
  .filterDate('2018-07-30', '2018-07-31')
  .map(mask_vnpa2_img)

print(dataset)

// Bidirectional Reflectance Distribution Function (BRDF)
var brdf = dataset.select('DNB_BRDF_Corrected_NTL');
var brdfVis = {
  min: 0,
  max: 100,
  palette: ['black', 'purple', 'cyan', 'green', 'yellow', 'red', 'white'],
};

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 myScale = brdf.projection().nominalScale();

Export.image.toDrive({
image: brdf,
description: 'ntl_beijing_30_07',
maxPixels: 1000000000000,
region: table,
scale: myScale.getInfo()
});

Also, I tried:

var myScale = ee.Image(brdf).projection().nominalScale();

Export.image.toDrive({
image: brdf,
description: 'ntl_beijing_30_07',
maxPixels: 1000000000000,
region: table,
scale: myScale
});

But it shows an error saying

Error: Image.clipToBoundsAndScale, argument 'input': Invalid type. Expected type: Image. Actual type: ImageCollection. (Error code: 3)

which means (from what I understand) that I am passing an ImageCollection although I specified to my code a band (brdf).

Another try I made, where I select the first of the ImageCollection:

var dataset = ee.ImageCollection('NOAA/VIIRS/001/VNP46A2')
.filterDate('2018-07-30', '2018-07-31') .map(mask_vnpa2_img)
.first()

returns the following error

Error: Exported bands must have compatible data types; found inconsistent types: Float64 and Byte. (Error code: 3)

3rd Edit A new approach I tried was:

Map.centerObject(table);

var mask_vnpa2_img = function(image) {
  var qa = image.select('QF_Cloud_Mask');
  var cloudMaskQuality = bitwiseExtract(qa, 4, 5);
  var cloudDetectionResultsConfidenceIndicator = bitwiseExtract(qa, 6, 7);
  var shadowDetected = bitwiseExtract(qa, 8);
  var cirrusDetection = bitwiseExtract(qa, 9);
  var snowIceSurface = bitwiseExtract(qa, 10);

  var mask = ee.Image(1)
    .and(cloudMaskQuality.eq(3)) // High
    .and(cloudDetectionResultsConfidenceIndicator.eq(0)) // Confident Clear
    .and(shadowDetected.eq(0)) // No
    .and(cirrusDetection.eq(0)) // No cloud
    .and(snowIceSurface.eq(0)); // No Snow/Ice
    
  return image.updateMask(mask);
};

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 dataset = ee.ImageCollection('NOAA/VIIRS/001/VNP46A2')
  .filterDate('2018-07-30', '2018-07-31')
  .map(mask_vnpa2_img);

//var brdf = dataset.select('DNB_BRDF_Corrected_NTL');

// Get the first image in the collection
var firstImage = ee.Image(dataset.first());

// Get the scale from the first image
var scale = firstImage.projection().nominalScale();

// Export the image to Drive using the native scale
Export.image.toDrive({
  image: firstImage,
  description: 'ntl_beijing_30_07',
  maxPixels: 1000000000000,
  region: table,
  scale: scale.getInfo(),
});

But I am still receiving the same error with the inconsistent data types.

And a link to my (first attempt) code.

2 Answers 2

1

In your code, dataset is ee.ImageCollection. Then, you select one band for each image in dataset:

var brdf = dataset.select('DNB_BRDF_Corrected_NTL');

so brdf is still ee.ImageCollection. The error brdf.projection is not a function. is because .projection is a method for a single ee.Image, not ee.ImageCollection. That also applies to the Export.image.toDrive -- you need to either select a single image per each Export task, or reduce the collection to a single image to export.. that depends on what you want to do.

I also recommend taking a look at this related answer for how to use the .projection() information to export an image:

https://gis.stackexchange.com/a/443194/67301

1
  • Please see my edit of another try I made where I select the first image of the question and the error I am getting.
    – Nikos
    Commented Nov 12, 2023 at 11:21
0

I managed to solve it by specifying which image from the ImageCollection I wanted, like so:

Map.centerObject(table);

// Here I'm trying to set the Bits according to table 'Bitmask for QF_Cloud_Mask'
var mask_vnpa2_img = function(image) {
  var qa = image.select('QF_Cloud_Mask');
  var landWaterBackground = bitwiseExtract(qa, 1, 3)
  var cloudMaskQuality = bitwiseExtract(qa, 4, 5)
  var cloudDetectionResultsConfidenceIndicator = bitwiseExtract(qa, 6, 7)
  var shadowDetected = bitwiseExtract(qa, 8)
  var cirrusDetection = bitwiseExtract(qa, 9)
  var snowIceSurface = bitwiseExtract(qa, 10)

  var mask = ee.Image(1)
    .and(landWaterBackground.eq(1)) // Land no Desert
    .and(cloudMaskQuality.eq(3)) // High
    .and(cloudDetectionResultsConfidenceIndicator.eq(0)) // Confident Clear
    .and(shadowDetected.eq(0)) // No
    .and(cirrusDetection.eq(0)) // No cloud
    .and(snowIceSurface.eq(0)) // No Snow/Ice
    
  return image.updateMask(mask);
};

var dataset = ee.ImageCollection('NOAA/VIIRS/001/VNP46A2')
  .filterDate('2018-06-01', '2018-06-30')
  .map(mask_vnpa2_img)
  .select('DNB_BRDF_Corrected_NTL')
  .filterBounds(table)
  .first()

print(dataset)

// Bidirectional Reflectance Distribution Function (BRDF)
var brdf = dataset.select('DNB_BRDF_Corrected_NTL');
var brdfVis = {
  min: 0,
  max: 100,
  palette: ['black', 'purple', 'cyan', 'green', 'yellow', 'red', 'white'],
};

// Day/Night Band (DNB)
// NightTime Light (NTL)
Map.addLayer(brdf, brdfVis, 'DNB_BRDF_Corrected_NTL');


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)
}

// Get the scale from the first image
var scale = dataset.projection().nominalScale();

// Export the image to Drive using the native scale
Export.image.toDrive({
  image: dataset,
  description: 'ntl_beijing_30_07',
  maxPixels: 1000000000000,
  region: table,
  scale: scale.getInfo(),
});

in the above code, when I called the var dataset, I added the .first() argument in the end. In this way, I used one image and not an ImageCollection of one image, and the mask (QF_Cloud_Mask) has been applied properly without giving me any errors for incopatible data type when exporting the image. Next, I managed to get the scale info properly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.