Unable to get Mask from Sentinel 2 image with snappy

Hello everyone:

I am trying to get the ‘scl_water’ mask for every image I process. First I resample and reproject the image and then I run the following code:

mask_group = product.getMaskGroup()
mymask = mask_group.get(‘scl_water’)
my_real_mask = jpy.cast(mymask, Mask)
h = product.getSceneRasterHeight()
w = product.getSceneRasterWidth()
data = np.zeros(w * h, np.int32)
data.shape = h,w
my_real_mask.readPixels(0,0,w,h, data)

However, every element in data remains 0. I made the same operations with SNAP Desktop and there wasn’t any problem.

Does anyone know what is the problem?

Thanks

Hi @Borkadd,

Did you make any progress with this?

Reading masks was working fine for me based on previous advice from @marpet (same as you have it) but now it seems to be broken… not sure if this was caused by some kind of update.

Cheers,

Sam

For me this has not been resolved yet? Is there any update? Thanks

Sorry for not answering before @shunt16 .

No, this was not solved, but i found a way to bypass it by reading each pixel of the mask inside a double loop for (I know, quite inefficient), as shown below

mask_group = product.getMaskGroup().get(‘scl_cloud_medium_proba’)
mymask = jpy.cast(mask_group, Mask)
h = product.getSceneRasterHeight()
w = product.getSceneRasterWidth()
data = np.zeros(w * h, np.int32)
data.shape = h,w
final_mask_medium = mymask.getSourceImage().getData()
//Double loop after this

However, I have problems again. The last line before the loop gives a NullPointerException, so I can´t acces it, although there is no problem accesing mymask.getSoruceImage() . The problem is in getData()

Thanks and sorry again for not answering before

Another issue I found that I think is related to this one is that when I try to extract some bands from the image, it gives the same NullPointerException in the function ReadPixels() as shown below:

red = product.getBand(‘B4’)
w1 = red.getSpectralWavelength()
width = product.getSceneRasterWidth()
height = product.getSceneRasterHeight()
targetProduct = Product(‘Test_Product’, ‘FLH_Type’, width, height)
targetBand1 = targetProduct.addBand(‘Red’, ProductData.TYPE_FLOAT32)
ProductUtils.copyGeoCoding(product, targetProduct)
targetProduct.setProductWriter(ProductIO.getProductWriter(‘GeoTIFF’)) targetProduct.writeHeader(String(os.path.join(path,‘Pre-Processed_’+image_name+’.tif’)))
r1 = np.zeros(width, dtype=np.float32)

for y in range(height):
r = red.readPixels(0, y, width, 1, r1)
targetBand1.writePixels(0, y, width, 1, r)

targetProduct.closeIO()

pd: the only reason I think these problems are related is because they appeared at the same time, after being working until now.

Thanks @Borkadd. Yeah, looping through all the pixels is not really feasible as a solution for me because it would be too slow for the processing I need to do. For now I managed to find an old installation of snap where my old code still works… so will continue to use that until the issue resolved.

Hi @shunt16 , Finally I did It with GPT, calling It from a Python script. It takes far less time than doing It directly with Python, with or without loop.

Hello, i’m new here and i’ve been having challenges trying to get SNAP to produce for me images that have been Atmospherically corrected. How do i extract the corrected images from SNAP?

We need more information to help you. What input product do you use? Have you already performed any operations on your data?

Hi Borkadd,
The the second line, what is Mask?

mask_group = product.getMaskGroup().get(‘scl_cloud_medium_proba’)
mymask = jpy.cast(mask_group, Mask)
h = product.getSceneRasterHeight()
w = product.getSceneRasterWidth()
data = np.zeros(w * h, np.int32)
data.shape = h,w
final_mask_medium = mymask.getSourceImage().getData()
//Double loop after this

Mask is a Java class.

In the __init.py__ of snappy it is already defined, like this:

Mask = jpy.get_type('org.esa.snap.core.datamodel.Mask')

In some cases, it is necessary to cast objects, otherwise the collaboration between Python and Java does not work.

1 Like

Hi @Borkadd, how did you do it exactly? I’m trying using snappy but I am stuck at the same point as the previous comments to obtain the information of the mask.

Hi,
For the new version snappy, cast to Java Mask may return zeros array, so you can cast Java ProductNode to Java Band, rather than Java Mask.
My version is SNAP9.0-snappy, and data is sentinel2

for example:

from snappy import Band
mask_java = jpy.cast(source_product.getMaskGroup().get(“opaque_clouds”), Band)

sentinel2 cloud mask

I don’t know if other posts have already solved this problem, hope this method can help you :slightly_smiling_face: