Segmentation based on constrained connectivity¶

Constrained connectivity segmentation relies on two constraints:
(1) the local range threshold (called alpha);
(2) the global range threshold (called omega).
The default parameter values are set to alpha=omega=255. The constrained connectivity segmentation produces the coarsest partition of the viewed map such that any two points of each segment of the partition (called connected component) can be linked by a path included in the connected component while the absolute difference of any two successive pixels along the path never exceeds the alpha. In addition, the difference between the largest and smallest value within the connected component does not exceed omega. By increasing/decreasing the values of alpha and/or omega coarser/finer partitions can be obtained. In the example below, the segmentation is obtained on band 4 of a S2 image with alpha set to 256 and omega to 512. These values are appropriate since the theoretical range of the reflectance values of a S2 image is set between 1 and 10,000. The segmentation returns a labelled image with each segment (i.e., connected component) set to a unique label value. Since the number of segments of the partition can be as large as the number of pixels of the viewed area, for display purposes, the modulo(256) function is called to force the label values to belong to the integer range [0,255]. Random colours are given to each resulting 256 values by applying the color scheme "random".

Not all operators available inside interactive library are pixel-based. In such cases, displaying the ImageProcess objects using tiles would not provide good results. When a non pixel-based operator is present inside an ImageProcess object, the processing chain becomes a window-based chain and is automatically displayed by querying, at every zoom or pan, all the visible viewport of the Map. One example of such operators is "labelcc" which creates a segmentation based on the concept of constrained connectivity .

In [ ]:
map = Map()
map.zoomToExtent(inter.search("Toulouse"))
map
In [ ]:
coll = inter.ImageCollection("S2")
coll = coll.filterOnGeoName("Toulouse")
coll = coll.filterOnDate(2017,7,1, 2017,12,31)
coll = coll.filterOn("cloudcover", "<=", 0)
coll = coll.filterOn("jrc_filepath", "<>", "")
coll.limit(100)
coll.sort("cloudcover",True)

p = coll.process().band("B04").labelcc(256,1024).modulo(256).opacity(255)
p.colorScheme("random")

map.addLayer(p.toLayer())

A window-based ImageProcess can be exported. In this case a single query to the server is done to generate the full output image

In [ ]:
(latmin,lonmin),(latmax,lonmax) = map.getExtent()
zoom = map.zoom + 3
print p.exportPixelsX(lonmin,latmin,lonmax,latmax,zoom)
print p.exportPixelsY(lonmin,latmin,lonmax,latmax,zoom)
p.exportImage(lonmin,latmin,lonmax,latmax,zoom,"segmentation.tif")

The exported segmentation image can then be loaded from the local storage

In [ ]:
map = Map()
map
In [ ]:
p = inter.loadLocalRaster("segmentation.tif").opacity(150)
map.clear()
map.zoomToImageExtent(p)
map.addLayer(p.toLayer())

The interactive library automatically discovers if an ImageProcess can be displayed in tile-mode or needs the window-mode. A tile-based ImageProcess can be forced to be displayed in window-mode using forceWindowBased=True parameter in the map.addLayer call:

In [ ]:
map = Map()
map
In [ ]:
p = inter.ImageCollection("DEM").process()
p.parameter("mode","hillshade")
p.scale(0,1500)
p.colorScheme("dem")
map.clear()
map.addLayer(p.toLayer(),forceWindowBased=True)
In [ ]: