0

I have a TIFF file and a shapefile with polygons. What i would like to achieve is a binary TIFF file with the mask of the polygons indicated as 1's and the surrounding extend of the TIFF file as 0's. The polygons should still just have the same vertices as the original one (just the coordinates of the polygons vertices). In the end I need to polygonize the raster again and get the coordinates of the polygon (after tiling the rasterized polygons). I have tried several approaches:

  1. Rasterizing the vector layer
    • Here is the problem the specification of the resolution -> the tif file has a strange resolution of 0.1000020249960453383,-0.09999548095543589477. Creating a raster with this resolution results in much more vertices than the original.
    • Furthermore I get outside of the polygons 'no data' instead of 0's.
  2. Clip Raster by Mask layer
    • I can clip the raster with the shapefile to the area of interest but get stuck here as well.

This is what I get at the moment (inverted version of what I need):

enter image description here

I feel like i just misconfigure the rasterizing part, but can not figure out where.

5
  • 4
    This goal is impossible "The polygons should still just have the same vertices as the original one". Rasters are like a chessboard with of cells of fixed size. You can set the horizontal and vertical resolutions in QGIS. Process of rasterizing and polygonizing back is not reversible but it is possible to get quite close by using a small pixel size and by simplifying the new polygonized vectors. The outside of the polygon in your result has probably value 0 already but it is also marked as nodata into the image metadata. Change setting to "Not set" in QGIS for disabling the metadata part.
    – user30184
    Aug 19, 2022 at 9:04
  • Ok, thanks for your clarification. I knwo this would be another question. But do you then know how i could merge my polygons to the original tiff? I mean that the polygons ar actually in the tiff file?
    – Milap
    Aug 19, 2022 at 9:15
  • 1
    QGIS has also a tool "Rasterize (overwrite with fixed value) that burns values to an existing raster. You can also use gdal.org/programs/gdal_polygonize.html directly from the command line.
    – user30184
    Aug 19, 2022 at 9:30
  • Would Clip raster by mask layer solve your problem? See docs.qgis.org/3.22/en/docs/user_manual/processing_algs/gdal/…
    – Babel
    Aug 19, 2022 at 10:28
  • Thanks user30184 and Babel, i have tried (again) both of your suggestions, but none lead to my desired output. I will post my solution.
    – Milap
    Aug 20, 2022 at 9:29

1 Answer 1

1

I did not find any solution to my problem in QGIS. Therefore I switched to rasterio since I will proceed with the pictures afterwards anyway in python (segmentation problem). So I found my solution in here: [https://lpsmlgeo.github.io/2019-09-22-binary_mask/]

# function of generating binary mask
def generate_mask(raster_path, shape_path, output_path, file_name):
    
    """Function that generates a binary mask from a vector file (shp or geojson)
    
    raster_path = path to the .tif;

    shape_path = path to the shapefile or GeoJson.

    output_path = Path to save the binary mask.

    file_name = Name of the file.
    
    """
    
    #load raster
    
    with rasterio.open(raster_path, "r") as src:
        raster_img = src.read()
        raster_meta = src.meta
    
    #load o shapefile ou GeoJson
    train_df = gpd.read_file(shape_path)
    
    #Verify crs
    if train_df.crs != src.crs:
        print(" Raster crs : {}, Vector crs : {}.\n Convert vector and raster to the same CRS.".format(src.crs,train_df.crs))
        
        
    #Function that generates the mask
    def poly_from_utm(polygon, transform):
        poly_pts = []

        poly = cascaded_union(polygon)
        for i in np.array(poly.exterior.coords):

            poly_pts.append(~transform * tuple(i))

        new_poly = Polygon(poly_pts)
        return new_poly
    
    
    poly_shp = []
    im_size = (src.meta['height'], src.meta['width'])
    for num, row in train_df.iterrows():
        if row['geometry'].geom_type == 'Polygon':
            poly = poly_from_utm(row['geometry'], src.meta['transform'])
            poly_shp.append(poly)
        else:
            for p in row['geometry']:
                poly = poly_from_utm(p, src.meta['transform'])
                poly_shp.append(poly)

    mask = rasterize(shapes=poly_shp,
                     out_shape=im_size)
    
    #Save
    mask = mask.astype("uint16")
    
    bin_mask_meta = src.meta.copy()
    bin_mask_meta.update({'count': 1})
    os.chdir(output_path)
    with rasterio.open(file_name, 'w', **bin_mask_meta) as dst:
        dst.write(mask * 255, 1)

This does exactly what I needed.

2
  • Your Question specifies an answer in QGIS, so while we're happy you solved your task, it doesn't seem as if your Answer answers the Question.
    – Vince
    Aug 20, 2022 at 9:48
  • Hello Vince, this is true. I first also wanted to do it in QGIS since i prprocess the images there. But i really could not figure out how to get to my desired output. That is why i opened up on other tools as well. But i see absolutely your point!
    – Milap
    Aug 20, 2022 at 9:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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