Building Footprints

Building footprints are required as the starting points for generating any building inventory using brails. The user can provide their own footprint data or they can use BrailsPlusPlus to create an inventory. There are 3 scraper classes in BrailsPlusPlus that can be used to obtain this from the web:

  1. MS_FootprintScraper using Microsoft Footprint Database

  2. OSM_FootprintScraper using Open Street Maps (OSM)

  3. USA_FootprintScraper using USA Structures

Each of these classes has a method get_footprints which will return the footprints for the RegionBoundary provided. In the example shown below, the 3 different classes are all used to generate an inventory for a location provided when the script is run.

  1# Written: fmk 4/24
  2# License: BSD-2
  3
  4"""
  5brails_footprint.py
  6===================
  7
  8This is a simple NRAILS example to demonstrate different methods to obtain
  9building inventories for an area.
 10
 11"""
 12
 13import argparse
 14import sys
 15
 16sys.path.insert(1, "../../")
 17
 18from brails.utils.importer import Importer
 19
 20def main():
 21    
 22    # Create the argument parser
 23    parser = argparse.ArgumentParser(description="Demonstrate Importer.")
 24    parser.add_argument('location', type=str, help="Location")    
 25
 26    # Parse the arguments
 27    args = parser.parse_args()
 28    
 29    # create an Import to get the classes
 30    
 31    importer = Importer()
 32
 33    #
 34    # specify the BoundaryRegion
 35    #
 36    
 37    region_boundary_class = importer.get_class("RegionBoundary")
 38    region_boundary_object = region_boundary_class({"type": "locationName", "data":args.location})
 39    
 40    #
 41    # Get Footprints using OSM
 42    #
 43    
 44    print("Using OSM_FootprintsScraper ...")
 45    
 46    osm_class = importer.get_class("OSM_FootprintScraper")
 47    osm_scraper = osm_class({"length": "ft"})
 48    osm_inventory = osm_scraper.get_footprints(region_boundary_object)
 49    
 50    #
 51    # Get Footprints using Microsofts Database
 52    #
 53    
 54    print("Using Microsoft Footprint Database ...")
 55    ms_class = importer.get_class("MS_FootprintScraper")
 56    ms_scraper = ms_class({"length": "ft"})
 57    ms_inventory = ms_scraper.get_footprints(region_boundary_object)
 58
 59    #
 60    # Get Footprints using USA Structures
 61    #
 62    
 63    print("Using USA_FootprintsScraper ...")
 64    usa_class = importer.get_class("USA_FootprintScraper")
 65    usa_scraper = usa_class({"length": "ft"})
 66    usa_inventory = usa_scraper.get_footprints(region_boundary_object)
 67
 68    #
 69    # Print num buildings found
 70    #
 71
 72    print("\n\n")
 73    print("-" * 27)
 74    print(f"{'Scraper':<15}  {'# building':<10}")
 75    print("-" * 27)    
 76    print(f"{'OSM':<15}  {len(osm_inventory.inventory):<10}")    
 77    print(f"{'Microsoft':<15}  {len(ms_inventory.inventory):<10}")
 78    print(f"{'USA':<15}  {len(usa_inventory.inventory):<10}")
 79    print("-" * 27)    
 80
 81    #
 82    # Test obtaining a smaller random subset of each,
 83    #    method needed as we will not always want to get all the images
 84    #    print to see what we are getting from each
 85
 86    print("\n\nSmall Subset of USA Inventory: ")
 87    small_inventory = usa_inventory.get_random_sample(2, 200)
 88    small_inventory.print_info()
 89
 90    print("\n\nSmall Subset of OSM Inventory: ")
 91    small_inventory = osm_inventory.get_random_sample(2, 200)
 92    small_inventory.print_info()
 93
 94    print("\n\nSmall Subset of MS Inventory: ")
 95    small_inventory = ms_inventory.get_random_sample(2, 200)
 96    small_inventory.print_info()
 97    
 98
 99if __name__ == "__main__":
100    main()

To run the example provided contained in a file example.py for for a “Berkeley, CA” location:

python3 brails_footprint.py "Berkeley, CA"

The example will print out the number of buildings obtained for each scraper.

---------------------------
Scraper          # building
---------------------------
OSM              35547
Microsoft        29469
USA              28404
---------------------------

The example when run will also prints out a two inventory subset of the data obtained for each footprint scraper. As shown below, the features obtained for each of the assets is different between scrapers.

 1Small Subset of USA Inventory: 
 2AssetInventory
 3Inventory stored in:  dict
 4Key:  1494 Asset:
 5	 Coordinates:  [[-122.251349037992, 37.8918864620566], [-122.251516845084, 37.8918428029327], [-122.251549765644, 37.8919222669851], [-122.251381955857, 37.891965925353], [-122.251349037992, 37.8918864620566]]
 6	 Features:  {'type': 'Building', 'buildingheight': 17.4, 'fpAreas': 1554}
 7Key:  6666 Asset:
 8	 Coordinates:  [[-122.249638045616, 37.8518085710136], [-122.249704555083, 37.8517353439222], [-122.249817801199, 37.8518000117672], [-122.249751291732, 37.8518732380851], [-122.249638045616, 37.8518085710136]]
 9	 Features:  {'type': 'Building', 'buildingheight': 21.6, 'fpAreas': 1326}
10
11
12Small Subset of OSM Inventory: 
13AssetInventory
14Inventory stored in:  dict
15Key:  2989 Asset:
16	 Coordinates:  [[-122.2539358, 37.8823889], [-122.2538841, 37.8822577], [-122.2538636, 37.882258], [-122.2538454, 37.8821659], [-122.2540379, 37.8821623], [-122.2540337, 37.8822459], [-122.2539784, 37.882245], [-122.2540264, 37.8823667], [-122.2539358, 37.8823889]]
17	 Features:  {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 'NA', 'numstories': 1, 'roofshape': 'NA', 'fpAreas': 2973}
18Key:  13333 Asset:
19	 Coordinates:  [[-122.2743673, 37.8721826], [-122.2743469, 37.8720391], [-122.2743897, 37.8720353], [-122.2743867, 37.8720143], [-122.2744387, 37.8720097], [-122.2744416, 37.8720305], [-122.2744612, 37.8720287], [-122.2744816, 37.8721725], [-122.2743673, 37.8721826]]
20	 Features:  {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 'NA', 'numstories': 'NA', 'roofshape': 'NA', 'fpAreas': 1866}
21
22
23Small Subset of MS Inventory: 
24AssetInventory
25Inventory stored in:  dict
26Key:  1494 Asset:
27	 Coordinates:  [[-122.2832593562512, 37.8673577272146], [-122.2831763030742, 37.86735994820125], [-122.2831818391027, 37.86748896307548], [-122.2832648922797, 37.86748674209271], [-122.2832593562512, 37.8673577272146]]
28	 Features:  {'type': 'Building', 'buildingheight': 13.4, 'fpAreas': 1129}
29Key:  6666 Asset:
30	 Coordinates:  [[-122.28236720333845, 37.86313236995723], [-122.2823711059354, 37.86320635580323], [-122.28259869901714, 37.86319887333546], [-122.28259568844234, 37.86314179854076], [-122.28253945956331, 37.86314364715192], [-122.28253856754118, 37.863126736093584], [-122.28236720333845, 37.86313236995723]]
31	 Features:  {'type': 'Building', 'buildingheight': 19.1, 'fpAreas': 1675}

Footprint Notebook

Here is a link to a Jupyter Notebook that runs the basic code, accompanied by graphics to better illustrate the output.

Note

  1. The number of buildings differs across datasets due to variations in data sources, processing techniques, geographic coverage, and update frequency. Since no dataset is perfect, users are encouraged to compare building inventories from different datasets for their area of interest by overlaying them with satellite imagery for accuracy.

  2. OSM is a community-driven platform where volunteers manually contribute building footprints using ground surveys, GPS data, and licensed aerial imagery. This results in variable data quality depending on the region and contributor activity, with a particularly active community in non-urban areas. The results may contain NA values for buildings for which community has yet to provide data.

  3. OSM offers global coverage, Microsoft’s data is expanding internationally, and USA Structures is limited to the United States.

  4. OSM is updated in real time by contributors, Microsoft’s data is updated periodically, and USA Structures updates are infrequent.