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:
MS_FootprintScraper using Microsoft Footprint Database
OSM_FootprintScraper using Open Street Maps (OSM)
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# Modified: bacetiner 12/24
3# License: BSD-2
4
5"""
6brails_footprint.py
7===================
8
9This is a simple BRAILS example to demonstrate different methods to obtain
10building inventories for an area.
11
12"""
13import argparse
14from brails.utils.importer import Importer
15
16
17def download_footprints(location):
18 """
19 Download and analyze building footprint data for a specified location.
20
21 Args:
22 location (str):
23 The name of the geographic region for which building footprints
24 are to be downloaded. This is used to specify the boundary region.
25
26 Functionality:
27 1. Initializes a boundary region for the given location.
28 2. Retrieves building footprints from:
29 - OpenStreetMap using the `OSM_FootprintScraper`.
30 - Microsoft Building Footprints data using the
31 `MS_FootprintScraper`.
32 - FEMA USA Structures database using the `USA_FootprintScraper`.
33 3. Prints a summary of the number of buildings retrieved from each
34 source.
35 4. Extracts and prints details for a small random subset of the
36 retrieved footprints from each data source for verification and
37 sampling.
38
39 Prints:
40 - The number of buildings found in each dataset.
41 - Information about small random subsets of the inventories for OSM,
42 Microsoft, and FEMA USA Structures data sources.
43
44 Note:
45 The function uses an `Importer` class to dynamically load the required
46 scraper classes.
47 The random sampling is performed to give a quick overview of the data
48 quality and coverage without loading the full dataset.
49 """
50 # Create an Importer to get the classes:
51 importer = Importer()
52
53 # Specify the BoundaryRegion:
54 region_boundary_class = importer.get_class("RegionBoundary")
55 region_boundary_object = region_boundary_class(
56 {"type": "locationName", "data": location})
57
58 # Get footprints using OpenStreetMap:
59 print("Using OSM_FootprintsScraper...")
60
61 osm_class = importer.get_class("OSM_FootprintScraper")
62 osm_scraper = osm_class({"length": "ft"})
63 osm_inventory = osm_scraper.get_footprints(region_boundary_object)
64
65 # Get footprints using Microsoft Building Footprints data:
66 print("\nUsing Microsoft Footprint Database...")
67
68 ms_class = importer.get_class("MS_FootprintScraper")
69 ms_scraper = ms_class({"length": "ft"})
70 ms_inventory = ms_scraper.get_footprints(region_boundary_object)
71
72 # Get footprints from FEMA USA Structures database:
73 print("\nUsing USA_FootprintsScraper...")
74
75 usa_class = importer.get_class("USA_FootprintScraper")
76 usa_scraper = usa_class({"length": "ft"})
77 usa_inventory = usa_scraper.get_footprints(region_boundary_object)
78
79 # Print number of buildings found:
80 seperator = '-' * 27
81 print('\n\n')
82 print(seperator)
83 print(f"{'Scraper':<15} {'# building':<10}")
84 print(seperator)
85 print(f"{'OSM':<15} {len(osm_inventory.inventory):<10}")
86 print(f"{'Microsoft':<15} {len(ms_inventory.inventory):<10}")
87 print(f"{'USA':<15} {len(usa_inventory.inventory):<10}")
88 print(seperator)
89
90 # Test obtaining a smaller random subset of each, method needed as we will
91 # not always want to get all the images. Print to see what we are getting
92 # from each:
93 print('\n\nSmall Subset of USA Inventory: ')
94 small_inventory = usa_inventory.get_random_sample(2, 200)
95 small_inventory.print_info()
96
97 print('\n\nSmall Subset of OSM Inventory: ')
98 small_inventory = osm_inventory.get_random_sample(2, 200)
99 small_inventory.print_info()
100
101 print('\n\nSmall Subset of MS Inventory: ')
102 small_inventory = ms_inventory.get_random_sample(2, 200)
103 small_inventory.print_info()
104
105
106if __name__ == '__main__':
107 # Set up command-line arguments:
108 parser = argparse.ArgumentParser(description='Download footprints for a '
109 'specified location using BRAILS++ '
110 'footprint scrapers.')
111 parser.add_argument('location', type=str, nargs='?', default='Tiburon, CA',
112 help="Name of the location to analyze.")
113
114 # Parse the command-line arguments:
115 args = parser.parse_args()
116
117 # Get the building footprints for the specified location:
118 download_footprints(args.location)
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
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.
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.
OSM offers global coverage, Microsoft’s data is expanding internationally, and USA Structures is limited to the United States.
OSM is updated in real time by contributors, Microsoft’s data is updated periodically, and USA Structures updates are infrequent.