Dessiner une forme sur une image avec matplotlib

Sep 24 2020

À partir d'une forme de polygone, je crée un tampon carré pour créer une image satellite de mon emplacement. La forme est définie comme un fichier .shp que j'ai lu avec geopandas.

Je voudrais afficher l'image ET la forme sur le même graphique en utilisant matplotlib, le résultat final devrait ressembler à ça:

J'arrive à afficher et étirer l'image sur une figure matplotlib

with rio.open(file) as f:
    data = f.read([1, 2, 3], masked=True)
                
    bands = [] 
    for i in range(3):
        band = data[i]
        h_, bin_ = np.histogram(band[np.isfinite(band)].flatten(), 3000, density=True) #remove the NaN from the analysis
    
        cdf = h_.cumsum() # cumulative distribution function
                    cdf = 3000 * cdf / cdf[-1] # normalize
    
        # use linear interpolation of cdf to find new pixel values
        band_equalized = np.interp(band.flatten(), bin_[:-1], cdf)
        band_equalized = band_equalized.reshape(band.shape)
        
        bands.append(band_equalized)
    
    data = np.stack( bands, axis=0 )

    data = data/3000
    data = data.clip(0, 1)
    data = np.transpose(data,[1,2,0])
            
    i = year - start_year
    ax = axes[getPositionPdf(i)[0], getPositionPdf(i)[1]]
    ax.imshow(data, interpolation='nearest')
    #[...] unrelevant display customization

Mais je ne sais pas comment afficher la forme par-dessus. Quelqu'un sait-il comment exécuter cette astuce?

Réponses

5 gene Sep 24 2020 at 17:09

Regardez quelle est la signification de l'échelle sur les axes x et y de l'image en utilisant matplotlib

Un fichier de formes vectoriel ponctuel (projection cartésienne) :

 import geopandas as gpd
 df = gpd.read_file("points.shp")
 df['x'] = df.geometry.x
 df['y'] = df.geometry.y
 df.head(2)
    id         geometry                    x               y
 0  1   POINT (203734.167 89573.589)    203734.166875   89573.588721
 1  2   POINT (203981.632 89261.402)    203981.631683   89261.402347

fig, ax = plt.subplots()
ax.scatter(df.x,df.y,c='r')

Un raster:

a) avec GDAL (projection cartésienne)

  from osgeo import gdal 
  ds = gdal.Open(dem)
  data = ds.ReadAsArray()
  # plot the raster
  fig, ax = plt.subplots()
  img = ax.imshow(data)
  plt.show()

Nous pouvons voir que nous ne pouvons pas tracer les points sur l'image, mais si nous calculons l'extension réelle du raster (en utilisant le résultat de gdal geotransform) pour l'étendue matplotlib:

 gt = ds.GetGeoTransform()     
 extent = (gt[0], gt[0] + ds.RasterXSize * gt[1],gt[3] + ds.RasterYSize * gt[5], gt[3])
 fig, ax = plt.subplots()
 img = ax.imshow(data, extent=extent, origin='upper')
 ax.scatter(df.x,df.y,c='r')
 plt.show()

b) avec rasterio (en utilisant directement la transformation rasterio )

import rasterio
from rasterio.plot import show
ds = rasterio.open(dem)
fig, ax = plt.subplots()
show(ds2.read(), transform=ds2.transform, ax=ax)
ax.scatter(df.x,df.y,c='r')
plt.show()