Reading Image and Calculating Zonal Statistics per Polygon

ZonalStatistics.gh (10.4 KB)

Hi all,

I’m writing a script to read an image and then calculate statistics per polygon overlaid on top of the image. The script I’ve attached works, but being that I’m relatively new to C#, I know it could be much faster. Right now the script I’ve posted spits out the average red value for all the pixels in reach polygon. Feel free to use the attached image with the script.

Here’s the process:

  1. Create a grid of rectangles overlaid on top of the image based on the dimensions of the image
  2. Create a list of doubles for each rectangle (as one nested list). Each list will store the red values for the pixels inside the intersecting rectangle.
  3. Read each pixel and in its place create a point where the x and y values correspond to the pixel location and the z-value corresponds to the red value of that pixel.
  4. Create a boolean for each point (set to false) to determine whether that point has already been “found” or accounted for inside a rectangle. No point is inside two rectangles, since they form a perfect grid with no overlap.
  5. Run a nested for-loop determining which points are inside which rectangles. Right now I’m creating a bounding box for each rectangle, and checking whether the x and y values of each point fall inside the bounding box Min and Max values for x and y. I found this method faster than using Point Containment. If the point is found inside that rectangle, the boolean for that point is set to “true” so the point will not be considered for future rectangles.
  6. For each list of red values, calculate the average (or other statistics, as need be).

Thanks, everyone! I sense that creating a point and testing point containment is probably not the fastest way to run statistics on pixel values, but am not sure how to proceed. I’m eager to learn more advanced methods and optimize this script.

Mark

So… you are “downsampling” the picture?
I’d suggest you to avoid any geometry at all.
Work only with simple data: doubles, integers, booleans, etc…

You need to “group” pixel values to analyze them?

Hi Riccardo,

Exactly - I’m trying to group pixel values into a grid that I define.

The ultimate utility is that I’m reading images exported from ArcGIS/QGIS where the color corresponds to a particular land cover classification. I’ve written a much longer script where I drape individual surfaces based on a topo mesh with the extents of each rectangle seen in this script, and those surfaces are baked to layers that match the aggregated pixel value. It all works, but I’d really like to optimize the section I’ve posted here where I calculate the aggregated pixel values.

If you want to have more “control”, you’ll need to iterate through all pixels 1 by 1 …

But if you just need a simple resize you should probably use common NET libraries and have the fastest result. Would that be a valid option?

I cant possibly put me on this right now…

That worked! Thanks, Riccardo. I was able to resample the bmp to the exact width and height dimensions so I had one pixel for every draped surface, thus removing the need to do any averaging or mode calculation.