This is my recipe and it works quite well.
import skimage
import gdal
import matplotlib.pyplot as plt
import numpy as np
import rasterio
import shapely
import fiona
#Open raster with gdal
image=gdal.Open('A.tif')
im=image.ReadAsArray()
#out variable stores the contours
out=skimage.measure.find_contours(im,0.5)
# Here,0.5 is taken assuming it is a binary raster
# but the default value is taken as (np.max(im)+np.min(im))/2
fig, ax = plt.subplots()
ax.imshow(im, cmap=plt.cm.gray)
#cs list will contain all the 2D Line objects
cs=[]
for contour in out:
cs.append(ax.plot(contour[:, 1], contour[:, 0], linewidth=2))
ax.axis('image')
#Show image with contours
plt.show()
#Read band 1 of raster or as per the usage it can be tweaked
with rasterio.open('A.tif') as raster:
image = raster.read()[0,:,:]
#Create list poly containing all the linestrings of contours
from shapely.geometry import mapping,MultiLineString,LineString
poly=[]
for i in cs:
x=i[0].get_xdata()
y=i[0].get_ydata()
aa=rasterio.transform.xy(raster.transform,y,x)
poly.append(LineString([(i[0], i[1]) for i in zip(aa[0],aa[1])]))
#Create a list of wkt strings
list_lstrings = [shapely.wkt.loads(p.wkt) for p in poly]
# Create a MultiLineString object from the list
mult=shapely.geometry.MultiLineString(list_lstrings)
#Inputting projection info
from fiona.crs import from_epsg
crs = from_epsg(4326)
#Create schema
schema = {
'geometry': 'MultiLineString',
'properties': {'id': 'int'},
}
# Write a new Shapefile
with fiona.open('U:\\new_shape.shp', 'w', 'ESRI Shapefile', schema,crs=crs) as c:
c.write({
'geometry': mapping(mult),
'properties': {'id': 1},
})
mask
a boolean array? If so, there might be a slightly more straightforward way of getting to the result you're looking for. – Sesamemask
is a boolean array (as a result of thresholding). – Deforest