Saving Band 2,3 and 4 (BGR) as PNG or BMP

Using a Sentinel 2A product I am doing the following steps:

  1. Spatial subset - creating a spatial subset using a predefined GeoJSON file to reduce area
  2. Reprojection - to EPSG:4326 - WGS 84 for future use in QGIS (default CRS)
  3. Band subset - creating subset from bands 2,3 and 4 (BGR colors, 10m resolution) as well as a single-band subset for band 5, 6 and 7 (vegetation red edge, 20m resolution)
  4. Export to GeoTIFF - export each subset to a GeoTIFF file

I am working on a CNN that will enhance bands 5, 6 and 7 using the image data provided by bands 2, 3 and 4. The goal is to get the resolution of the former (20m) up to the resolution of the latter (10m), which will result in double the resolution for the former. In order to do this enhancement I am trying to figure out a way to export just the pixel values (RGB) in separate PNG files (one file per subset; if required I can split the BGR subset into three for each channel). Those files will be then (depending on their size) split into grids and a dataset will be generated and use with a pre-trained model to produce (hopefully) the desired results.

I am very new to SNAP, Sentinel and remote sensing in general. The function for my GeoTIFF file is

def export_to_geotiff(product_src, strip_tie_points=False, path=None):
    logger.info('Exporting product "' + product_src.getName() + '" to GeoTIFF file')

    if strip_tie_points:
        for tie_point_grid in product_src.getTiePointGrids():
            logger.info('Removing tie-point grid "' + tie_point_grid.getName() + '" from product due to difference in resolution, which prevents exporting to (Big)GeoTiff')
            product_src.removeTiePointGrid(tie_point_grid)

    snappy.ProductIO.writeProduct(product_src, path, 'GeoTIFF-BigTIFF')

I tried GPF, GPT as well as the Graph Builder (inside SNAP). All produce empty PNG files. I am looking into a Python solution but a GPT command is also a good solution. The only reason why I am thinking all of this should be possible is the fact that the Write node inside the Graph Builder offers PNG/BMP.

Ok, here is my solution:

def export_to_png(product_src, bands=['B4', 'B3', 'B2'], path=None):
    print('Exportin product to PNG: "' + path  + '"')
    JAI = snappy.jpy.get_type('javax.media.jai.JAI')
    ImageManager = snappy.jpy.get_type('org.esa.snap.core.image.ImageManager')
    format = 'PNG'
    RGB = []
    for band in bands:
        RGB.append(product_src.getBand(band))
    if len(RGB) == 1:
        RGB.extend([RGB[0], RGB[0]])
    elif len(RGB) != 3:
        exit()

    img_info = snappy.ProductUtils.createImageInfo(RGB, True, snappy.ProgressMonitor.NULL)
    img_rgb = ImageManager.getInstance().createColoredBandImage(RGB, img_info, 0)
    
    JAI.create("filestore", img_rgb, path + '.png', format)

export_to_png(
    product_src=subset_b2b3b4_from_region,
    bands=['B4', 'B3', 'B2'],
    path=subset_b7_from_region_png_path)

export_to_png(
    product_src=subset_b5_from_region,
    bands=['B5'],
    path=subset_b5_from_region_png_path)

Example call:

export_to_png(
    product_src=subset_b2b3b4_from_region,
    bands=['B4', 'B3', 'B2'],
    path=subset_b7_from_region_png_path)

export_to_png(
    product_src=subset_b5_from_region,
    bands=['B5'],
    path=subset_b5_from_region_png_path)

All images contain 3 channels. Two configurations are possible - 3 bands (e.g. band 2, 3 and 4 for an RGB image) and 1 band (e.g. band 5 only). In case of single band the specified band is used for all three channels.

1 Like

This is saving the image as RGB, because cmap=‘gray’ is ignored when supplying RGB data to imsave.

This is the closest I could get with my lack of knowledge regarding the toolbox. Later on I removed the cloning of the single band (if only one band is passed):

    # Remove following lines
    if len(RGB) == 1:
        RGB.extend([RGB[0], RGB[0]])
    elif len(RGB) != 3:
        exit()

It works. That said even if you have 3 channels with each channel having the same values as the rest and the color value range is ok, it is very easy to reduce the number of those channels to a single one when loading the RGB image for further processing. I didn’t find any problems with my solution but I am definitely opened to other suggestions. It’s quite confusing as a newcomer when you have to deal with the NetBeans-based GUI, the command line tool, the Java API, the Java-to-Python bridge and the snappy Python module.