Tiled Segmentation for Large GeoTIFF Images with SAM 3¶
This notebook demonstrates how to use the sliding window (tiled) approach to segment large GeoTIFF images that would otherwise exceed GPU memory limits.
Overview¶
When working with large satellite or aerial imagery, loading the entire image into GPU memory for SAM 3 inference is often not feasible. The generate_masks_tiled() method solves this by:
- Dividing the large image into smaller, overlapping tiles
- Processing each tile independently with SAM 3
- Merging the results back into a seamless output mask
- Preserving georeferencing information from the original GeoTIFF
Key Parameters¶
- tile_size: Size of each processing tile (default: 1024 pixels)
- overlap: Overlap between adjacent tiles (default: 128 pixels) - helps prevent edge artifacts
- prompt: Text description of objects to segment
- min_size/max_size: Filter objects by pixel area
Installation¶
Uncomment and run the following cell to install the required packages:
# %pip install "segment-geospatial[samgeo3]"
Import Libraries¶
import os
import leafmap
from samgeo import SamGeo3, common
Download Sample Data¶
We'll use a sample satellite image for this demonstration. You can replace this with your own large GeoTIFF.
# Download a sample satellite image
url = "https://huggingface.co/datasets/giswqs/geospatial/resolve/main/naip/naip_water_train.tif"
image_path = "naip_water_train.tif"
if not os.path.exists(image_path):
common.download_file(url, image_path)
Check Raster Info¶
Let's check the dimensions of our image to understand why tiling might be necessary.
common.print_raster_info(image_path)
Initialize SamGeo3¶
sam = SamGeo3(backend="meta")
Run Tiled Segmentation¶
Now we'll use the generate_masks_tiled() method to process the image. This method:
- Reads the image tile by tile
- Processes each tile with SAM3
- Merges overlapping regions intelligently
- Saves the result as a georeferenced GeoTIFF
# Output path for the mask
output_path = "segmentation_mask.tif"
# Run tiled segmentation
sam.generate_masks_tiled(
source=image_path,
prompt="water", # Change prompt based on what you want to segment
output=output_path,
tile_size=1024, # Size of each tile (adjust based on GPU memory)
overlap=128, # Overlap between tiles
min_size=100, # Minimum object size in pixels
unique=False, # Create binary mask (0 or 1)
dtype="int32", # Data type for output
verbose=True, # Show progress
)
Visualize Results¶
m = leafmap.Map()
m.add_raster(image_path, layer_name="Original Image")
m.add_raster(
output_path, nodata=0, opacity=0.8, cmap="Blues", layer_name="Segmentation Mask"
)
m
Convert Mask to Vector¶
You can convert the raster mask to vector format (GeoPackage, Shapefile, etc.) for further analysis in GIS software.
# Convert mask to vector
vector_path = "segmentation_mask.gpkg"
common.raster_to_vector(output_path, vector_path)
Smooth Vector¶
smooth_vector_path = "segmentation_mask_smooth.gpkg"
gdf = common.smooth_vector(vector_path, smooth_vector_path)
m.add_gdf(gdf, layer_name="Smoothed Vector", info_mode=None)
m
Tips for Processing Large Images¶
Tile Size: Larger tiles capture more context but require more GPU memory. Start with 512 or 1024 and increase if you have sufficient GPU memory.
Overlap: Higher overlap (e.g., 128-256) helps prevent artifacts at tile boundaries but increases processing time. Lower overlap (e.g., 64) is faster but may have more edge effects.
Memory Management: The method automatically clears GPU memory after each tile. If you still encounter memory issues, try reducing the tile_size.
Data Type: Use
int32for images with many objects,int16for up to 65535 objects, orint8for up to 255 objects.Filtering: Use
min_sizeandmax_sizeto filter out noise (small objects) or irrelevant large regions.