[postgis-users] Incorrect Results for ST_ValueCount with large polygons

Michael Treglia mtreglia at gmail.com
Wed Jul 11 13:59:42 PDT 2018


Hi everyone,

Sorry for multiple emails on this, but wanted to ping this list again to
see if there is anything obvious I'm missing or should check regarding this
issue. I've reiterated context/the problem/sample sql code below, and if
there's other info that would be helpful, please let me know.

Thanks! Sincerely,
Mike

# To reiterate:
## The goal/issue:
I'm trying to calculate # of pixels from a categorical raster, by value,
within distinct polygons of a vector layer. I have code, below, that seems
to work accurately for small polygons, though I'm getting inaccuracies in
large polygons - the addition of some pixels, including some from a value
that aren't actually contained within a focal polygon. (I'm comparing to
available calculations for the same overlay, along with results from QGIS
Zonal Histogram tool). I'd like to get this working for this specific
overlay, but then be able to apply the SQL code to comparable situations.

##Data:
The polygons are parcels, ranging quite widely in size;
The raster dataset is a 6" land cover dataset loaded as an in-db raster via
raster2pgsql;
raster2pgsql -s 2263 -d -C -t 128x128 -M -I -l 4,16
"landcover_2010_nyc_05ft.img" base_rasters.landcover6in | psql -h localhost
-U postgres -d dbname -v ON_ERROR_STOP=1

## System Info:
I'm running  PostGIS 2.4.4 with PostgreSQL v 10.3 on Windows 7 x64

## Two sets of sample code that give the same result:
1)
SELECT  bbl, (pvc).VALUE, SUM((pvc).COUNT) AS tot_pix
 FROM base_rasters.landcover6in
  INNER join  results_scratch.polys_test
  ON ST_Intersects(landcover6in.rast, polys_test.geom_2263),
    ST_ValueCount(ST_Clip(landcover6in.rast,polys_test.geom_2263),1, TRUE,
ARRAY[1, 2, 3, 4, 5, 6, 7]) AS pvc
  GROUP BY (pvc).VALUE, bbl
 ORDER BY bbl, (pvc).VALUE;

2)
 SELECT
   bbl, (value_count).value, SUM((value_count).count) AS count
  FROM
    (
    select
    bbl,
      rid,
      ST_ValueCount(
        ST_Union(ST_Clip(rast, geom_2263, TRUE)), 1, TRUE, ARRAY[1, 2, 3,
4, 5, 6, 7]
      ) value_count
    FROM
      (SELECT bbl, geom_2263 FROM results_scratch.polys_test) v,
      (SELECT rid, rast FROM base_rasters.landcover6in) r
    WHERE ST_Intersects(rast, geom_2263)
    GROUP BY bbl, rid, geom_2263
    ) i
  GROUP BY bbl, value
  ORDER BY bbl, value



On Fri, Jun 22, 2018 at 5:12 PM, Michael Treglia <mtreglia at gmail.com> wrote:

> Hi again all,
>
> Sorry for the multiple messages on this - realizing the query I posted was
> somewhat off from what I intended - below are examples that are getting at
> what I'm going for but exhibiting the issue I described (sometimes
> including pixels in counts aren't actually be within polygons [i.e., the
> categorical value isn't actually within the polygon based on visual
> inspection & this same analysis with other tools]).
>
> Simpler/quicker:
>
>   SELECT  bbl, (pvc).VALUE, SUM((pvc).COUNT) AS tot_pix
>  FROM base_rasters.landcover6in
>   INNER join  results_scratch.polys_test
>   ON ST_Intersects(landcover6in.rast, polys_test.geom_2263),
>     ST_ValueCount(ST_Clip(landcover6in.rast,polys_test.geom_2263),1,
> TRUE, ARRAY[1, 2, 3, 4, 5, 6, 7]) AS pvc
>   GROUP BY (pvc).VALUE, bbl
>  ORDER BY bbl, (pvc).VALUE;
>
>
>
> A longer, less efficient version that gives the same results (but unions
> the clipped raster tiles):
>
>
>  SELECT
>    bbl, (value_count).value, SUM((value_count).count) AS count
>   FROM
>     (
>     select
>     bbl,
>       rid,
>       ST_ValueCount(
>         ST_Union(ST_Clip(rast, geom_2263, TRUE)), 1, TRUE, ARRAY[1, 2, 3,
> 4, 5, 6, 7]
>       ) value_count
>     FROM
>       (SELECT bbl, geom_2263 FROM results_scratch.polys_test) v,
>       (SELECT rid, rast FROM base_rasters.landcover6in) r
>     WHERE ST_Intersects(rast, geom_2263)
>     GROUP BY bbl, rid, geom_2263
>     ) i
>   GROUP BY bbl, value
>   ORDER BY bbl, value
>
> On Thu, Jun 21, 2018 at 4:23 PM, Michael Treglia <mtreglia at gmail.com>
> wrote:
>
>> Hi all,
>>
>> I'm basically trying to compute # of pixels of land cover type by
>> polygon, for lots of polygons.
>>
>> I'm working with a query a query like this:
>> SELECT  bbl, (pvc).VALUE, SUM((pvc).COUNT) AS tot_pix
>>  FROM base_rasters.landcover6in
>>   INNER join  results_scratch.polys_test
>>   ON ST_Intersects(landcover6in.rast, polys_test.geom_2263),
>>     ST_ValueCount(ST_Clip(landcover6in.rast,polys_test.geom_2263),1) AS
>> pvc
>>   GROUP BY (pvc).VALUE, bbl
>>  ORDER BY (pvc).VALUE;
>>
>> For smaller polygons, spot-checking, it looks like I'm generally getting
>> the right results. However, for larger polygons, not always. For example,
>> though a polygon might not have roads, I'm getting non-0 counts for road
>> pixels within a polygon (polygons have unique identifiers as 'bbl').  The
>> total area of pixels counted ends up being larger than the polygon (larger
>> than would be attributable to differences between polygons edges & pixels)
>>
>> I'm thinking it's an issue when there are multiple raster tiles
>> included... but not entirely sure. Any suggestions on whether there's
>> something off in this query that might be causing an issue like I describe?
>>
>> Thanks in advance for any suggestions!
>> Mike
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/postgis-users/attachments/20180711/d9101970/attachment.html>


More information about the postgis-users mailing list