Get Sentinel-1 image with decibels values

Hello,

I’m using sentinelhub-py and i’m trying to understand how to get the images as arrays with decibels values. I think I have asked it before but maybe mmy question was not clear enough so I will try to make it clearer.

under “confiduration utility” I have created configuration with serveral layers, among them some sentinel1 layers, as:

  1. TRUE-COLOR-S1-IW - which uses the function
 return [VV,VH, 2 * VH, VV / VH / 100.0]
  1. VV -which uses the function:
return [Math.max(0, Math.log(VH) * 0.21714724095 + 1), dataMask];
  1. VH- which uses the function:
return [Math.max(0, Math.log(VH) * 0.21714724095 + 1), dataMask];

Now, i’m trying to use evalscript in order to get image with 3 dimensions.bands : vv, vh and the datamask.

As I undersand, according to my configuration layers (the return), I suppose to get back my values as db, e.g 0 to -20, but anytime I use the get data, and print the result array, I see that the result is in UINT8 (0-255 and not -20-0 ).

This is how I tried to call teh VV,VH and datamask:

 bbox_coords_wgs84=[-56.41393258886229, -12.932876469776858,-56.33590746533693, -12.817048229804314]



evalscript = """
    //VERSION=3
    

    return [VV,VH, dataMask]
"""

time_interval = time_interval

request = SentinelHubRequest(
    data_folder='results',
    evalscript=evalscript,
    input_data=[
        SentinelHubRequest.input_data(
            data_collection=DataCollection.SENTINEL1_IW,
            time_interval=time_interval,
            
        )
    
    ],
    responses=[
        SentinelHubRequest.output_response('default', MimeType.TIFF)
    ],
    bbox=bbox,
    config=config
)

image = request.get_data(save_data=True)

then when I plot the image, I get nice image, and i’m able to plot each band:

plt.figure(figsize=(20,10))
plt.imshow(image[0][:,:,0],cmap='gray')

image

but when I print the array to see the values I get it as UINT8:

image[0][:,:,0]

array([[ 44,  29,  29, ...,  74,  54,  18],
       [ 55,  21,  45, ...,  65,  32,  32],
       [ 35,  25,  29, ..., 104,  88,  32],
       ...,
       [ 25,  26,  21, ...,  37,  40,  30],
       [ 27,  27,  28, ...,  31,  50,  50],
       [ 23,  24,  32, ...,  30,  52,  28]], dtype=uint8)

I have also tried to put directly the function to get decibels inside the avalscript but it didn’t change the result.

evalscript = """
    //VERSION=3
    

    return [Math.max(0, Math.log(VV) * 0.21714724095 + 1),Math.max(0, Math.log(VH) * 0.21714724095 + 1), dataMask]
"""

So what I’m asking is, how can I get the result array in decibels values, I care less regard the visulaization, what is important to me here are the values. You can imagine it as if I wanted to retrieve NDVI image,and I would like to get the pixels values between -1 to 1, and not in UINT8.

I have read the documentation here and also the sentinelhub-py one but hasn’t found any solution to this issue.

Thanks in advanced,

Reut

Dear Reut,

as you can see in our Evalscript V3 documentation and this FAQ on values in Sentinel Hub, all the evalscripts are by default in sampleType.AUTO, which expects your values to be between 0-1 and then maps them to 0-255, or UINT8 range.
If you want your values to be in a different format, such as UINT16 or FLOAT32 (this one includes decimals), you would need to use a V3 evalscript and return a different sampleType, e.g. sampleType:"FLOAT32".
Additionally, it doesn’t make sense to return 2 channels + dataMask. DataMask goes either into the second or the fourth channel (second if you’re returning grayscale channel, and fourth, if you’re returning RGB). So if you are interested in e.g. VV in decibels, and want to also have no-data values transparent, it would make more sense to return it like this:

//VERSION=3 
return [Math.max(0, Math.log(VV) * 0.21714724095 + 1), dataMask]

With returning 3 channels, like you did, you’re getting unusual purple colors, and transparency is not working. You’re also not taking full advantage of the RGB capabilities. To understand how RGB composites work and how to construct custom scripts, I would recommend you to check our webinar on custom scripts.

Example V3 script, that returns decibels in full FLOAT32 values:

//VERSION=3
function setup() {
  return {
    input: [{
      bands: ["VV", "VH", "dataMask"]
    }],
    output: {
      bands: 2, 
      sampleType: "FLOAT32" 
    }
  }
}
function evaluatePixel(samples){
   let decibels = Math.max(0, Math.log(samples.VV) * 0.21714724095 + 1)
   return [decibels, samples.dataMask]
}

If you want to use custom evalscripts (and not only the premade data products), it’s essential for you to understand how our evalscripts work. To get started, go here, where you will find all the documentation links and tutorials.

1 Like

Hi Monja,

First I want to thank you for your answer,

I have gone over the tutorial you shared but I’m still a bit confused reagrd the values.

I have tried your example and it’s true that now I get values that are FLOAT32, but is still not the values I am trying to get- db between -20 to 0, e.g negative values.

I feel confused as it seems in the script in the configuration utility is seems like the result should be in db (-20 - 0 ):

so I feel confused regard the values I get in the array back.
After reading the documentation part about sampletype (and evalscripts in general) I’m not sure if is possible to get the data in those negative values.

As I mentioned before, In this case I care more about the raster values and not about the visualization.I want to do computation on the values and this specific computation I need it to be db negative values and not between 0-1.:slight_smile:

So if you have any hint regard how I can get the values as I need, it will be wonderfull.

Dear Reut,

the FLOAT32 does not only include values between 0 and 1, but all values between -2^32 to +2^32, including all the decimals in between. That’s why this format takes the most space.

The reason your values are not negative is that the visualization returned by the data product (return [Math.max(0, Math.log(linear) * 0.21714724095 + 1)]) maps decibel values to a range of 0-1, which is most suitable for visualization using simple scripts or scripts with sampleType:AUTO, such as for example in EO Browser.

To get decibel values from -20 to 0, you would have to return decibel values, and not a script optimized for visualization, with the following formula: return [10 * Math.log(linear) / Math.LN10] (with linear being e.g. VV).

The script to use to convert VV linear values to decibels would be:

//VERSION=3
function setup() {
  return {
    input: [{
      bands: ["VV"]
    }],
    output: {
      bands: 1, 
      sampleType: "FLOAT32" 
    }
  }
}
function evaluatePixel(samples){
   return [10 * Math.log(samples.VV) / Math.LN10]

The values of linear polarizations, such as VV and VH (if you were simply returning return [VV]), would typically be between 0 and 0.5.
If we map these values using the equation for decibel conversion (10 * Math.log(samples.VV) / Math.LN10), we get:

0.1 -> -9.999999999999998
0.2 -> -6.9897000433601875
0.3 -> -5.228787452803376
0.5 -> -3.0102999566398116

In radar, some pixels can have extreme reflectance values - either very high, or very low. So just as pixel values can be higher than 1 for VV, so can decibel values be higher than 0, or lower than -20. Let’s see what the following extreme values would return:

0.00001 -> -50
2 -> 3.0102999566398116
445 -> 26.483600109809313

However, typically, your decibel values will be in a general range -20 to 0, as that’s typical for most pixels.

On another note, the data product title does say “decibel visualization from -20 to 0”, which might be a bit confusing, but what is meant is that the equation converting values to decibels in a typical range from -20 and 0 is modified for the visualization - mapped to values from 0-1.

I hope this helps.

Best,
Monja

2 Likes

I found this after a good amount of searching and appreciate the answer. I think the Request Builder should include an option to get the data in actual dB units that aren’t meant for nice visualization but instead are meant for computation with software that expects dB values.