3

I am trying to access individual pixel values in a raster layer I'm working with. I can use QgsRasterBandStats to get some information about the raster layer with the following code:

layer = iface.activeLayer()
print("Active Layer: ", layer.name())
provider = layer.dataProvider()
extent = layer.extent()
stats = provider.bandStatistics(1, QgsRasterBandStats.All) 
print("min value =", stats.minimumValue)
print("max value =", stats.maximumValue)

I'm using the minimumValue and maximumValue attributes of QgsRasterBandStats. All the attributes are listed in the documentation.

In this raster layer I'm working with, there are really only 7 raster values. If I go into the symbology and manually classify these values, you can see them below.

enter image description here

What I'd really like to do is capture these values in a list, for example. Is there a way to access the individual pixel values in a raster object using QgsRasterBandStats?

Or could I choose a raster value (155 for example) and print the number of pixels with that value? Using something like the following pseudocode?

desired_value = 155
print(count of pixels with desired_value)
4

You can do that by using 'block' method from QgsRasterDataProvider for accessing the individual pixel values in a raster object. Below code adds necessary lines to your code for producing each desired counts.

layer = iface.activeLayer()
print("Active Layer: ", layer.name())
provider = layer.dataProvider()
extent = layer.extent()
stats = provider.bandStatistics(1, QgsRasterBandStats.All) 
print("min value =", stats.minimumValue)
print("max value =", stats.maximumValue)

provider = layer.dataProvider()

extent = provider.extent()

rows = layer.height()
cols = layer.width()

block = provider.block(1, extent, cols, rows)

values = [ [] for i in range(rows) ]

for i in range(rows):
    for j in range(cols):
        values[i].append(block.value(i,j))

flattened_list = [ element for list in values for element in list ]

unique = [ flattened_list[i] for i in range(len(flattened_list)) if flattened_list[i] not in flattened_list[:i] ]

for item in unique:
    count = 0

    for element in flattened_list:
        if element == item:
            count += 1

    print ("value: ", item, "count: ", count)

I tried above code out with a random raster with only ten values (between 1 and 10) and result, printed at Python Console, it was as follow:

Active Layer:  random_raster
min value = 1.0
max value = 10.0
value:  8.0 count:  38
value:  2.0 count:  51
value:  3.0 count:  34
value:  6.0 count:  43
value:  9.0 count:  33
value:  1.0 count:  43
value:  5.0 count:  38
value:  7.0 count:  39
value:  4.0 count:  41
value:  10.0 count:  40
3

You can use QgsRasterInterface.histogram to calculate lists of unique values and their respective counts. That's how the paletted/unique values renderer obtains its list of unique values, but using the API gives you the pixel count for each also.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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