3

I'm trying to implement a custom contrast enhancement function that will allow me to enhance an active raster layer in QGIS without having to create a new raster file.

I'm not trying to do a MinMaxEnhancement or use any of the other existing enhancement methods, I'd like to use a custom function that uses mean statistics as well as min, max.

This is my code so far (I'm doing this within a plugin btw):

layer = self.iface.activeLayer()

provider = layer.dataProvider()
renderer = layer.renderer()

for band_no in range(1, 4):

    stats = provider.bandStatistics(band_no, stats=QgsRasterBandStats.All, sampleSize=0)
    band_type = renderer.dataType(band_no)
    enhancement = QgsContrastEnhancement(band_type)
    enhancement.setContrastEnhancementAlgorithm(QgsContrastEnhancement.UserDefinedEnhancement)
            
    function = CustomFunction(band_type, stats.minimumValue, stats.maximumValue, stats.mean)
    enhancement.setContrastEnhancementFunction(function)

    value = enhancement.enhanceContrast(20)
    self.iface.messageBar().pushMessage("Success", f'band: {band_no} value: {value}', level=Qgis.Success, duration=3)

    if band_no == 1:
        renderer.setRedContrastEnhancement(enhancement)
    elif band_no == 2:
        renderer.setGreenContrastEnhancement(enhancement)
    else:
        renderer.setBlueContrastEnhancement(enhancement)

layer.triggerRepaint()

And my CustomFunction (I'm returning a fixed value 50 for testing purposes, in future I plan to replace this with a function that uses min, max and mean stats from each raster band):

class CustomFunction(QgsContrastEnhancementFunction):

    def __init__(self, data_type, min_value: float, max_value: float, mean: float):
        super().__init__(data_type, min_value, max_value)

        self.mean = mean
        self.setMinimumValue(min_value)
        self.setMaximumValue(max_value)

    def enhance(self, value: float) -> int:

        return 50

The value returned by enhanceContrast(20) is 50 as expected. However, the layer vanishes as if it had been turned off, I'd have expected the layer to have a flat colour with a value of 50 for each pixel.

To be honest I can't find any examples or much documentation on the setContrastEnhancementFunction method, so I could be using it incorrectly.

bgordon
  • 149
  • 2
  • 15

0 Answers0