1

I am trying to replicate using Python, what QGIS does to visualize the rasters in the map.

QGIS automatically chooses as contrast enhancement the method Stretch to MinMax. Looking at the Min/Max Settings, the Cumulative count cut is selected with the range being between 2% - 98%.

enter image description here

I saw in this answer that the cumulative count cut method is basically the same than numpy.nanpercentile. So I implemented this function in python:

def cumulative_count_cut(band, min_percentile=2, max_percentile=98):
    min_val = np.nanpercentile(band, min_percentile)
    max_val = np.nanpercentile(band, max_percentile)
    print(min_val,max_val)

I was expecting to the Min and Max values equal or even near the ones in QGIS but this is what I got instead:

  • Band 04: Min: 0.0 | Max: 1221.0
  • Band 03: Min: 0.0 | Max: 1430.0
  • Band 02: Min: 0.0 | Max: 1663.0

Am I missing something? Shouldn't the values be the same?

3
  • 3
    To compare apples to apples, you might want to use an exact Accuracy in QGIS band rendering settings, not an estimate Commented May 9, 2024 at 18:12
  • @Kasper what do you mean? how do I do that in QGIS? I just want to try and understand how come the min value is different from QGIS. I am not expecting to get exactly the same value but somewhere near. Commented May 15, 2024 at 8:17
  • 1
    In your screenshot: change the setting where Estimate is currently written. With Estimate, a quick sampling is used to derive the Min /Max which can introduce some inaccuracies. Not saying you'll get near values, but at least you'll get the exact values that QGIS has as Min/Max according to its methodology Commented May 15, 2024 at 16:34

1 Answer 1

0

I have found the answer and it was quite easy.Considering that the min value was always 0, I tried to see if by ignoring the 0 values, the min_val would change. And it did! They are not exactly the same, but they are close enough.

Python:

  • Band 04: Min: 161 | Max: 1958
  • Band 03: Min: 179 | Max: 1714
  • Band 02: Min: 122 | Max: 1476

QGIS:

QGIS

Code:

def cumulative_count_cut(band, min_percentile=2, max_percentile=98):
    """Apply contrast enhancement stretch similar to QGIS"""
    new_band = band[band != 0]
    min_val = np.nanpercentile(new_band, min_percentile)
    max_val = np.nanpercentile(new_band, max_percentile)
    print(min_val,max_val)
    return (band - min_val) / (max_val - min_val + offset) * 255
2
  • Before you built something very broken, please do try setting the Accuracy in QGIS. Surely you do not want to always ignore the value 0 when calculating statistics. Commented May 16, 2024 at 11:15
  • @bugmenot123 as you can see in the code, i do not ignore the value 0 when converting the image to Byte. I only ignore the value 0 when getting the percentile for the cumulative count cut. The objective of this question was to try and figure it out how QGIS does this and replicate in python. That is what was done. Commented May 16, 2024 at 14:06

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.