urban-imageable 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. urban_imageable-0.1.0/.gitignore +54 -0
  2. urban_imageable-0.1.0/LICENSE +24 -0
  3. urban_imageable-0.1.0/PKG-INFO +319 -0
  4. urban_imageable-0.1.0/README.md +275 -0
  5. urban_imageable-0.1.0/pyproject.toml +286 -0
  6. urban_imageable-0.1.0/src/imageable/__init__.py +70 -0
  7. urban_imageable-0.1.0/src/imageable/_correction_ensembles/__init__.py +0 -0
  8. urban_imageable-0.1.0/src/imageable/_correction_ensembles/cluster_weighted_ensemble.py +456 -0
  9. urban_imageable-0.1.0/src/imageable/_correction_ensembles/model_factories.py +15 -0
  10. urban_imageable-0.1.0/src/imageable/_dataset_builder/__init__.py +0 -0
  11. urban_imageable-0.1.0/src/imageable/_dataset_builder/dataset_from_gdf.py +164 -0
  12. urban_imageable-0.1.0/src/imageable/_extraction/__init__.py +0 -0
  13. urban_imageable-0.1.0/src/imageable/_extraction/building.py +445 -0
  14. urban_imageable-0.1.0/src/imageable/_extraction/extract.py +323 -0
  15. urban_imageable-0.1.0/src/imageable/_extraction/footprint.py +863 -0
  16. urban_imageable-0.1.0/src/imageable/_extraction/image.py +325 -0
  17. urban_imageable-0.1.0/src/imageable/_features/__init__.py +0 -0
  18. urban_imageable-0.1.0/src/imageable/_features/height/__init__.py +0 -0
  19. urban_imageable-0.1.0/src/imageable/_features/height/building_height.py +714 -0
  20. urban_imageable-0.1.0/src/imageable/_features/height/image.jpg +0 -0
  21. urban_imageable-0.1.0/src/imageable/_features/height/metadata.json +21 -0
  22. urban_imageable-0.1.0/src/imageable/_features/materials/__init__.py +0 -0
  23. urban_imageable-0.1.0/src/imageable/_features/materials/building_materials.py +399 -0
  24. urban_imageable-0.1.0/src/imageable/_images/__init__.py +0 -0
  25. urban_imageable-0.1.0/src/imageable/_images/acquisition.py +298 -0
  26. urban_imageable-0.1.0/src/imageable/_images/camera/__init__.py +0 -0
  27. urban_imageable-0.1.0/src/imageable/_images/camera/building_observation.py +191 -0
  28. urban_imageable-0.1.0/src/imageable/_images/camera/camera_adjustment.py +219 -0
  29. urban_imageable-0.1.0/src/imageable/_images/camera/camera_parameters.py +71 -0
  30. urban_imageable-0.1.0/src/imageable/_images/download.py +255 -0
  31. urban_imageable-0.1.0/src/imageable/_images/image.py +58 -0
  32. urban_imageable-0.1.0/src/imageable/_models/__init__.py +0 -0
  33. urban_imageable-0.1.0/src/imageable/_models/base.py +90 -0
  34. urban_imageable-0.1.0/src/imageable/_models/distance_to_streets_wrapper.py +272 -0
  35. urban_imageable-0.1.0/src/imageable/_models/height_correction_model.py +166 -0
  36. urban_imageable-0.1.0/src/imageable/_models/height_estimation/__init__.py +5 -0
  37. urban_imageable-0.1.0/src/imageable/_models/height_estimation/height_calculator.py +632 -0
  38. urban_imageable-0.1.0/src/imageable/_models/height_estimation/processors/__init__.py +0 -0
  39. urban_imageable-0.1.0/src/imageable/_models/height_estimation/processors/line_classifier.py +148 -0
  40. urban_imageable-0.1.0/src/imageable/_models/height_estimation/processors/line_refiner.py +129 -0
  41. urban_imageable-0.1.0/src/imageable/_models/height_estimation/single_view_metrology.py +92 -0
  42. urban_imageable-0.1.0/src/imageable/_models/height_estimation/vanishing_point.py +89 -0
  43. urban_imageable-0.1.0/src/imageable/_models/huggingface/__init__.py +0 -0
  44. urban_imageable-0.1.0/src/imageable/_models/huggingface/base.py +92 -0
  45. urban_imageable-0.1.0/src/imageable/_models/huggingface/floor_sky_ratio_calculator.py +189 -0
  46. urban_imageable-0.1.0/src/imageable/_models/huggingface/segformer_segmentation.py +282 -0
  47. urban_imageable-0.1.0/src/imageable/_models/lcnn/__init__.py +8 -0
  48. urban_imageable-0.1.0/src/imageable/_models/lcnn/core/__init__.py +9 -0
  49. urban_imageable-0.1.0/src/imageable/_models/lcnn/core/box.py +1092 -0
  50. urban_imageable-0.1.0/src/imageable/_models/lcnn/core/config.py +7 -0
  51. urban_imageable-0.1.0/src/imageable/_models/lcnn/core/datasets.py +89 -0
  52. urban_imageable-0.1.0/src/imageable/_models/lcnn/core/metric.py +190 -0
  53. urban_imageable-0.1.0/src/imageable/_models/lcnn/core/postprocess.py +77 -0
  54. urban_imageable-0.1.0/src/imageable/_models/lcnn/core/trainer.py +314 -0
  55. urban_imageable-0.1.0/src/imageable/_models/lcnn/core/utils.py +95 -0
  56. urban_imageable-0.1.0/src/imageable/_models/lcnn/lcnn_wrapper.py +401 -0
  57. urban_imageable-0.1.0/src/imageable/_models/lcnn/models/__init__.py +5 -0
  58. urban_imageable-0.1.0/src/imageable/_models/lcnn/models/hourglass_pose.py +201 -0
  59. urban_imageable-0.1.0/src/imageable/_models/lcnn/models/line_vectorizer.py +260 -0
  60. urban_imageable-0.1.0/src/imageable/_models/lcnn/models/multitask_learner.py +104 -0
  61. urban_imageable-0.1.0/src/imageable/_models/line_param_selection_model.py +80 -0
  62. urban_imageable-0.1.0/src/imageable/_models/materials/backbones/segformer_mit_encoder.py +583 -0
  63. urban_imageable-0.1.0/src/imageable/_models/materials/decoders/samixer_head.py +588 -0
  64. urban_imageable-0.1.0/src/imageable/_models/materials/dpt_gate.py +391 -0
  65. urban_imageable-0.1.0/src/imageable/_models/materials/label_palette.py +82 -0
  66. urban_imageable-0.1.0/src/imageable/_models/materials/material_seg_model.py +1609 -0
  67. urban_imageable-0.1.0/src/imageable/_models/materials/norms/sync_batchnorm.py +392 -0
  68. urban_imageable-0.1.0/src/imageable/_models/materials/postprocess.py +139 -0
  69. urban_imageable-0.1.0/src/imageable/_models/materials/preprocess.py +197 -0
  70. urban_imageable-0.1.0/src/imageable/_models/materials/result_types.py +58 -0
  71. urban_imageable-0.1.0/src/imageable/_models/materials/rmsnet.py +78 -0
  72. urban_imageable-0.1.0/src/imageable/_models/materials/rmsnet_wrapper.py +139 -0
  73. urban_imageable-0.1.0/src/imageable/_models/vpts/vpts_wrapper.py +112 -0
  74. urban_imageable-0.1.0/src/imageable/_utils/__init__.py +0 -0
  75. urban_imageable-0.1.0/src/imageable/_utils/geometry/__init__.py +0 -0
  76. urban_imageable-0.1.0/src/imageable/_utils/geometry/line_geometry.py +178 -0
  77. urban_imageable-0.1.0/src/imageable/_utils/geometry/point_geometry.py +63 -0
  78. urban_imageable-0.1.0/src/imageable/_utils/geometry/polygons.py +267 -0
  79. urban_imageable-0.1.0/src/imageable/_utils/geometry/ray_geometry.py +195 -0
  80. urban_imageable-0.1.0/src/imageable/_utils/geometry/surface_geometry.py +10 -0
  81. urban_imageable-0.1.0/src/imageable/_utils/geometry/vector_geometry.py +1 -0
  82. urban_imageable-0.1.0/src/imageable/_utils/masks/__init__.py +0 -0
  83. urban_imageable-0.1.0/src/imageable/_utils/masks/mask_operations.py +121 -0
  84. urban_imageable-0.1.0/src/imageable/_utils/masks/mask_visualizer.py +104 -0
  85. urban_imageable-0.1.0/src/imageable/_version.py +3 -0
  86. urban_imageable-0.1.0/src/imageable/assets/ade20k_palette.json +455 -0
  87. urban_imageable-0.1.0/src/imageable/assets/wireframe.yaml +71 -0
  88. urban_imageable-0.1.0/src/imageable/core/__init__.py +36 -0
  89. urban_imageable-0.1.0/src/imageable/core/building_data.py +625 -0
  90. urban_imageable-0.1.0/src/imageable/core/dataset.py +59 -0
  91. urban_imageable-0.1.0/src/imageable/core/image.py +213 -0
  92. urban_imageable-0.1.0/src/imageable/visualization/__init__.py +0 -0
  93. urban_imageable-0.1.0/src/imageable/visualization/footprints.py +322 -0
  94. urban_imageable-0.1.0/src/imageable/visualization/wheel_visualization.py +353 -0
@@ -0,0 +1,54 @@
1
+ # Python
2
+ cache
3
+ __pycache__/
4
+ *.py[cod]
5
+ *$py.class
6
+ *.so
7
+ .Python
8
+ build/
9
+ develop-eggs/
10
+ dist/
11
+ downloads/
12
+ eggs/
13
+ .eggs/
14
+ lib/
15
+ lib64/
16
+ parts/
17
+ sdist/
18
+ var/
19
+ wheels/
20
+ *.egg-info/
21
+ .installed.cfg
22
+ *.egg
23
+ MANIFEST
24
+
25
+ # Testing
26
+ .pytest_cache/
27
+ .coverage
28
+ htmlcov/
29
+ .tox/
30
+ .nox/
31
+ coverage.xml
32
+
33
+ # Type checking
34
+ .mypy_cache/
35
+ .dmypy.json
36
+ dmypy.json
37
+
38
+ # Environments
39
+ .env
40
+ .venv
41
+ env/
42
+ venv/
43
+ ENV/
44
+
45
+ # IDEs
46
+ .vscode/
47
+ .idea/
48
+ *.swp
49
+ *.swo
50
+
51
+ # OS
52
+ .DS_Store
53
+ Thumbs.db
54
+ .coverage.*
@@ -0,0 +1,24 @@
1
+ BSD 2-Clause License
2
+
3
+ Copyright (c) 2025, Scalable Design Participation Lab
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,319 @@
1
+ Metadata-Version: 2.4
2
+ Name: urban-imageable
3
+ Version: 0.1.0
4
+ Summary: Computer vision library for extracting 43+ building properties from street view images and footprints
5
+ Project-URL: Homepage, https://github.com/scalable-design-participation-lab/imageable
6
+ Project-URL: Bug Tracker, https://github.com/scalable-design-participation-lab/imageable/issues
7
+ Project-URL: Documentation, https://github.com/scalable-design-participation-lab/imageable#readme
8
+ Author-email: Khoi Ngo <ngo.kho@northeastern.edu>, Uriel Legaria <fill@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: building-analysis,computer-vision,geospatial,gis,height-estimation,segmentation,street-view,urban-planning
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Classifier: Topic :: Scientific/Engineering :: GIS
21
+ Classifier: Topic :: Scientific/Engineering :: Image Processing
22
+ Requires-Python: >=3.13
23
+ Requires-Dist: cmcrameri>=1.9
24
+ Requires-Dist: geopandas>=1.1.1
25
+ Requires-Dist: libpysal>=4.13.0
26
+ Requires-Dist: lu-vp-detect>=1.0.4
27
+ Requires-Dist: matplotlib>=3.5.0
28
+ Requires-Dist: numpy>=2.2.6
29
+ Requires-Dist: osmnx>=2.0.6
30
+ Requires-Dist: pandas>=2.2.3
31
+ Requires-Dist: pillow>=11.2.1
32
+ Requires-Dist: pydeck>=0.9.1
33
+ Requires-Dist: scikit-image>=0.19.0
34
+ Requires-Dist: scikit-learn>=1.7.2
35
+ Requires-Dist: seaborn>=0.13.2
36
+ Requires-Dist: shapely>=2.1.1
37
+ Requires-Dist: spopt>=0.7.0
38
+ Requires-Dist: tensorboardx>=2.6.4
39
+ Requires-Dist: timm>=1.0.21
40
+ Requires-Dist: torch>=2.7.1
41
+ Requires-Dist: transformers>=4.52.4
42
+ Requires-Dist: ultralytics>=8.4.0
43
+ Description-Content-Type: text/markdown
44
+
45
+ # imageable
46
+
47
+ [![Tests](https://github.com/scalable-design-participation-lab/imageable/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/scalable-design-participation-lab/imageable/actions/workflows/ci.yml)
48
+ [![PyPI version](https://badge.fury.io/py/imageable.svg)](https://badge.fury.io/py/imageable)
49
+ [![Python 3.13+](https://img.shields.io/badge/python-3.13+-blue.svg)](https://www.python.org/downloads/)
50
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
51
+
52
+ An open-source Python library for extracting **43+ building properties** from street view images and building footprints. Designed for urban planners, architects, climate resilience researchers, and GIS professionals.
53
+
54
+ ![Imageable](./imageable.png)
55
+
56
+ ## Features
57
+
58
+ - **Height Estimation**: Estimate building heights from single street-level images using vanishing point detection and semantic segmentation
59
+ - **Material Analysis**: Segment and quantify façade materials (brick, glass, concrete, etc.)
60
+ - **Footprint Properties**: Extract 21 geometric, engineered, and contextual features from building polygons
61
+ - **Image Features**: Analyze color, shape, and façade characteristics from street view images
62
+ - **Batch Processing**: Process entire neighborhoods via GeoDataFrames or GeoJSON files
63
+
64
+ ## Installation
65
+
66
+ ```bash
67
+ pip install urban-imageable
68
+ ```
69
+
70
+ ### For Development
71
+
72
+ ```bash
73
+ # Clone the repository
74
+ git clone https://github.com/scalable-design-participation-lab/imageable.git
75
+ cd imageable
76
+
77
+ # Install with uv (recommended)
78
+ uv sync --group dev
79
+ ```
80
+
81
+ ## Quick Start
82
+
83
+ ### Single Building Analysis
84
+
85
+ ```python
86
+ import imageable
87
+ from shapely.geometry import Polygon
88
+
89
+ # Define building footprint (WGS84 coordinates)
90
+ footprint = Polygon([
91
+ (-71.0589, 42.3601),
92
+ (-71.0585, 42.3601),
93
+ (-71.0585, 42.3605),
94
+ (-71.0589, 42.3605),
95
+ ])
96
+
97
+ # Get street view image
98
+ image, metadata = imageable.get_image(api_key, footprint)
99
+
100
+ # Extract all 43+ properties
101
+ props = imageable.get_dataset(api_key, footprint)
102
+ print(f"Estimated height: {props.building_height}m")
103
+ print(f"Projected area: {props.projected_area}m²")
104
+ print(f"Shape complexity: {props.complexity}")
105
+ ```
106
+
107
+ ### Batch Processing from GeoDataFrame
108
+
109
+ ```python
110
+ import geopandas as gpd
111
+ import imageable
112
+
113
+ # Load building footprints
114
+ gdf = gpd.read_file("buildings.geojson")
115
+
116
+ # Extract properties for all buildings
117
+ result = imageable.get_building_data_from_gdf(
118
+ gdf,
119
+ api_key,
120
+ id_column="building_id",
121
+ neighbor_radius=100.0, # meters
122
+ verbose=True,
123
+ )
124
+
125
+ # Result is a GeoDataFrame with 43+ new columns
126
+ print(result.columns)
127
+ ```
128
+
129
+ ### From GeoJSON File
130
+
131
+ ```python
132
+ import imageable
133
+
134
+ # Process directly from GeoJSON
135
+ result = imageable.get_building_data_from_geojson(
136
+ "buildings.geojson",
137
+ api_key,
138
+ output_format="gdf", # or "geojson", "dict"
139
+ )
140
+ ```
141
+
142
+ ### With Pre-downloaded Images
143
+
144
+ ```python
145
+ import imageable
146
+
147
+ # Process from local footprints and images
148
+ result = imageable.get_building_data_from_file(
149
+ "footprints.geojson",
150
+ "images/", # Directory containing images named by building ID
151
+ id_column="building_id",
152
+ )
153
+ ```
154
+
155
+ ## Extracted Properties
156
+
157
+ ### Footprint Properties (21 features)
158
+
159
+ **Geometric (6):**
160
+ - `unprojected_area`, `projected_area`: Area in original and projected CRS
161
+ - `longitude_difference`, `latitude_difference`: Bounding box dimensions
162
+ - `n_vertices`: Number of polygon vertices
163
+ - `shape_length`: Perimeter length
164
+
165
+ **Engineered (5):**
166
+ - `complexity`: Perimeter/area ratio
167
+ - `inverse_average_segment_length`: Edge length metric
168
+ - `vertices_per_area`: Vertex density
169
+ - `average_complexity_per_segment`: Segment-level complexity
170
+ - `isoperimetric_quotient`: Circularity measure (4πA/P²)
171
+
172
+ **Contextual (10):**
173
+ - `neighbor_count`: Number of buildings within radius
174
+ - `mean_distance_to_neighbors`: Average centroid distance
175
+ - `nearest_neighbor_distance`: Distance to closest building
176
+ - `n_size_mean/std/min/max/cv`: Neighbor area statistics
177
+ - `expected_nearest_neighbor_distance`: Random distribution expectation
178
+ - `nni`: Nearest neighbor index
179
+
180
+ ### Height Estimation
181
+
182
+ - `building_height`: Estimated height in meters using CV pipeline (vanishing points + segmentation)
183
+
184
+ ### Image Features (16 features)
185
+
186
+ **Color (5):**
187
+ - `average_red/green/blue_channel_value`: RGB means
188
+ - `average_brightness`: HSV brightness percentage
189
+ - `average_vividness`: HSV saturation percentage
190
+
191
+ **Shape (5):**
192
+ - `mask_area`: Segmented building pixels
193
+ - `mask_length`: Boundary perimeter
194
+ - `mask_complexity`: Length/area ratio
195
+ - `number_of_edges`, `number_of_vertices`: Polygon complexity
196
+
197
+ **Façade (6):**
198
+ - `average_window_x/y`: Window centroid location
199
+ - `average_door_x/y`: Door centroid location
200
+ - `number_of_windows`, `number_of_doors`: Element counts
201
+
202
+ ### Material Percentages
203
+
204
+ - `material_percentages`: Dictionary of façade material coverage (brick, glass, concrete, metal, etc.)
205
+
206
+ ## API Reference
207
+
208
+ ### Main Functions
209
+
210
+ ```python
211
+ # Batch processing
212
+ imageable.get_building_data_from_gdf(gdf, api_key, ...)
213
+ imageable.get_building_data_from_geojson(source, api_key, ...)
214
+ imageable.get_building_data_from_file(footprints, images_dir, ...)
215
+
216
+ # Single building
217
+ imageable.get_dataset(api_key, footprint, ...)
218
+ imageable.get_image(api_key, footprint, ...)
219
+
220
+ # Data class
221
+ imageable.BuildingProperties
222
+ ```
223
+
224
+ ### BuildingProperties
225
+
226
+ ```python
227
+ from imageable import BuildingProperties
228
+
229
+ # Create and populate
230
+ props = BuildingProperties(building_id="b001")
231
+ props.update_footprint_features(footprint_dict)
232
+ props.update_height(25.5)
233
+ props.update_material_percentages({"brick": 60.0, "glass": 40.0})
234
+
235
+ # Export
236
+ props.to_dict() # Dictionary
237
+ props.to_json("output.json") # JSON file
238
+ props.get_feature_vector() # NumPy array for ML
239
+
240
+ # Import
241
+ props = BuildingProperties.from_dict(data)
242
+ props = BuildingProperties.from_json("input.json")
243
+ ```
244
+
245
+ ## Requirements
246
+
247
+ - Python 3.13+
248
+ - Google Street View API key (for image acquisition and height estimation)
249
+ - See `pyproject.toml` for full dependency list
250
+
251
+ ## Development
252
+
253
+ ```bash
254
+ # Run tests
255
+ uv run pytest
256
+
257
+ # Run tests with coverage
258
+ uv run pytest --cov-report=html
259
+ open htmlcov/index.html
260
+
261
+ # Lint and format
262
+ uv run pre-commit run --all-files
263
+
264
+ # Build package
265
+ uv build
266
+ ```
267
+
268
+ ## Project Structure
269
+
270
+ ```
271
+ imageable/
272
+ ├── src/imageable/
273
+ │ ├── core/ # Public API
274
+ │ │ ├── building_data.py # Batch processing
275
+ │ │ ├── dataset.py # Single building extraction
276
+ │ │ └── image.py # Image acquisition
277
+ │ ├── _extraction/ # Property extraction
278
+ │ │ ├── building.py # BuildingProperties dataclass
279
+ │ │ ├── extract.py # Main orchestrator
280
+ │ │ ├── footprint.py # Footprint features
281
+ │ │ └── image.py # Image features
282
+ │ ├── _features/ # Feature pipelines
283
+ │ │ ├── height/ # Height estimation
284
+ │ │ └── materials/ # Material segmentation
285
+ │ ├── _images/ # Image acquisition
286
+ │ │ ├── camera/ # Camera parameters
287
+ │ │ └── download.py # Street View API
288
+ │ └── _models/ # ML models
289
+ │ ├── huggingface/ # SegFormer segmentation
290
+ │ ├── lcnn/ # Line detection
291
+ │ └── vpts/ # Vanishing points
292
+ └── tests/ # Test suite
293
+ ```
294
+
295
+ ## Citation
296
+
297
+ If you use imageable in your research, please cite:
298
+
299
+ ```bibtex
300
+ @software{imageable2025,
301
+ author = {Ngo, Khoi and Legaria, Uriel and Sandoval Olascoaga, Carlos},
302
+ title = {imageable: Computer Vision Library for Urban Building Analysis},
303
+ year = {2025},
304
+ url = {https://github.com/scalable-design-participation-lab/imageable}
305
+ }
306
+ ```
307
+
308
+ ## License
309
+
310
+ MIT License - see [LICENSE](LICENSE) for details.
311
+
312
+ ## Authors
313
+
314
+ - Khoi Ngo ([Khoi Ngo](https://github.com/billnqk)) - ngo.kho@northeastern.edu
315
+ - Uriel Legaria
316
+ - Carlos Sandoval Olascoaga
317
+
318
+
319
+ Developed at the [Scalable Design Participation Lab](https://github.com/scalable-design-participation-lab), Northeastern University.
@@ -0,0 +1,275 @@
1
+ # imageable
2
+
3
+ [![Tests](https://github.com/scalable-design-participation-lab/imageable/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/scalable-design-participation-lab/imageable/actions/workflows/ci.yml)
4
+ [![PyPI version](https://badge.fury.io/py/imageable.svg)](https://badge.fury.io/py/imageable)
5
+ [![Python 3.13+](https://img.shields.io/badge/python-3.13+-blue.svg)](https://www.python.org/downloads/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ An open-source Python library for extracting **43+ building properties** from street view images and building footprints. Designed for urban planners, architects, climate resilience researchers, and GIS professionals.
9
+
10
+ ![Imageable](./imageable.png)
11
+
12
+ ## Features
13
+
14
+ - **Height Estimation**: Estimate building heights from single street-level images using vanishing point detection and semantic segmentation
15
+ - **Material Analysis**: Segment and quantify façade materials (brick, glass, concrete, etc.)
16
+ - **Footprint Properties**: Extract 21 geometric, engineered, and contextual features from building polygons
17
+ - **Image Features**: Analyze color, shape, and façade characteristics from street view images
18
+ - **Batch Processing**: Process entire neighborhoods via GeoDataFrames or GeoJSON files
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ pip install urban-imageable
24
+ ```
25
+
26
+ ### For Development
27
+
28
+ ```bash
29
+ # Clone the repository
30
+ git clone https://github.com/scalable-design-participation-lab/imageable.git
31
+ cd imageable
32
+
33
+ # Install with uv (recommended)
34
+ uv sync --group dev
35
+ ```
36
+
37
+ ## Quick Start
38
+
39
+ ### Single Building Analysis
40
+
41
+ ```python
42
+ import imageable
43
+ from shapely.geometry import Polygon
44
+
45
+ # Define building footprint (WGS84 coordinates)
46
+ footprint = Polygon([
47
+ (-71.0589, 42.3601),
48
+ (-71.0585, 42.3601),
49
+ (-71.0585, 42.3605),
50
+ (-71.0589, 42.3605),
51
+ ])
52
+
53
+ # Get street view image
54
+ image, metadata = imageable.get_image(api_key, footprint)
55
+
56
+ # Extract all 43+ properties
57
+ props = imageable.get_dataset(api_key, footprint)
58
+ print(f"Estimated height: {props.building_height}m")
59
+ print(f"Projected area: {props.projected_area}m²")
60
+ print(f"Shape complexity: {props.complexity}")
61
+ ```
62
+
63
+ ### Batch Processing from GeoDataFrame
64
+
65
+ ```python
66
+ import geopandas as gpd
67
+ import imageable
68
+
69
+ # Load building footprints
70
+ gdf = gpd.read_file("buildings.geojson")
71
+
72
+ # Extract properties for all buildings
73
+ result = imageable.get_building_data_from_gdf(
74
+ gdf,
75
+ api_key,
76
+ id_column="building_id",
77
+ neighbor_radius=100.0, # meters
78
+ verbose=True,
79
+ )
80
+
81
+ # Result is a GeoDataFrame with 43+ new columns
82
+ print(result.columns)
83
+ ```
84
+
85
+ ### From GeoJSON File
86
+
87
+ ```python
88
+ import imageable
89
+
90
+ # Process directly from GeoJSON
91
+ result = imageable.get_building_data_from_geojson(
92
+ "buildings.geojson",
93
+ api_key,
94
+ output_format="gdf", # or "geojson", "dict"
95
+ )
96
+ ```
97
+
98
+ ### With Pre-downloaded Images
99
+
100
+ ```python
101
+ import imageable
102
+
103
+ # Process from local footprints and images
104
+ result = imageable.get_building_data_from_file(
105
+ "footprints.geojson",
106
+ "images/", # Directory containing images named by building ID
107
+ id_column="building_id",
108
+ )
109
+ ```
110
+
111
+ ## Extracted Properties
112
+
113
+ ### Footprint Properties (21 features)
114
+
115
+ **Geometric (6):**
116
+ - `unprojected_area`, `projected_area`: Area in original and projected CRS
117
+ - `longitude_difference`, `latitude_difference`: Bounding box dimensions
118
+ - `n_vertices`: Number of polygon vertices
119
+ - `shape_length`: Perimeter length
120
+
121
+ **Engineered (5):**
122
+ - `complexity`: Perimeter/area ratio
123
+ - `inverse_average_segment_length`: Edge length metric
124
+ - `vertices_per_area`: Vertex density
125
+ - `average_complexity_per_segment`: Segment-level complexity
126
+ - `isoperimetric_quotient`: Circularity measure (4πA/P²)
127
+
128
+ **Contextual (10):**
129
+ - `neighbor_count`: Number of buildings within radius
130
+ - `mean_distance_to_neighbors`: Average centroid distance
131
+ - `nearest_neighbor_distance`: Distance to closest building
132
+ - `n_size_mean/std/min/max/cv`: Neighbor area statistics
133
+ - `expected_nearest_neighbor_distance`: Random distribution expectation
134
+ - `nni`: Nearest neighbor index
135
+
136
+ ### Height Estimation
137
+
138
+ - `building_height`: Estimated height in meters using CV pipeline (vanishing points + segmentation)
139
+
140
+ ### Image Features (16 features)
141
+
142
+ **Color (5):**
143
+ - `average_red/green/blue_channel_value`: RGB means
144
+ - `average_brightness`: HSV brightness percentage
145
+ - `average_vividness`: HSV saturation percentage
146
+
147
+ **Shape (5):**
148
+ - `mask_area`: Segmented building pixels
149
+ - `mask_length`: Boundary perimeter
150
+ - `mask_complexity`: Length/area ratio
151
+ - `number_of_edges`, `number_of_vertices`: Polygon complexity
152
+
153
+ **Façade (6):**
154
+ - `average_window_x/y`: Window centroid location
155
+ - `average_door_x/y`: Door centroid location
156
+ - `number_of_windows`, `number_of_doors`: Element counts
157
+
158
+ ### Material Percentages
159
+
160
+ - `material_percentages`: Dictionary of façade material coverage (brick, glass, concrete, metal, etc.)
161
+
162
+ ## API Reference
163
+
164
+ ### Main Functions
165
+
166
+ ```python
167
+ # Batch processing
168
+ imageable.get_building_data_from_gdf(gdf, api_key, ...)
169
+ imageable.get_building_data_from_geojson(source, api_key, ...)
170
+ imageable.get_building_data_from_file(footprints, images_dir, ...)
171
+
172
+ # Single building
173
+ imageable.get_dataset(api_key, footprint, ...)
174
+ imageable.get_image(api_key, footprint, ...)
175
+
176
+ # Data class
177
+ imageable.BuildingProperties
178
+ ```
179
+
180
+ ### BuildingProperties
181
+
182
+ ```python
183
+ from imageable import BuildingProperties
184
+
185
+ # Create and populate
186
+ props = BuildingProperties(building_id="b001")
187
+ props.update_footprint_features(footprint_dict)
188
+ props.update_height(25.5)
189
+ props.update_material_percentages({"brick": 60.0, "glass": 40.0})
190
+
191
+ # Export
192
+ props.to_dict() # Dictionary
193
+ props.to_json("output.json") # JSON file
194
+ props.get_feature_vector() # NumPy array for ML
195
+
196
+ # Import
197
+ props = BuildingProperties.from_dict(data)
198
+ props = BuildingProperties.from_json("input.json")
199
+ ```
200
+
201
+ ## Requirements
202
+
203
+ - Python 3.13+
204
+ - Google Street View API key (for image acquisition and height estimation)
205
+ - See `pyproject.toml` for full dependency list
206
+
207
+ ## Development
208
+
209
+ ```bash
210
+ # Run tests
211
+ uv run pytest
212
+
213
+ # Run tests with coverage
214
+ uv run pytest --cov-report=html
215
+ open htmlcov/index.html
216
+
217
+ # Lint and format
218
+ uv run pre-commit run --all-files
219
+
220
+ # Build package
221
+ uv build
222
+ ```
223
+
224
+ ## Project Structure
225
+
226
+ ```
227
+ imageable/
228
+ ├── src/imageable/
229
+ │ ├── core/ # Public API
230
+ │ │ ├── building_data.py # Batch processing
231
+ │ │ ├── dataset.py # Single building extraction
232
+ │ │ └── image.py # Image acquisition
233
+ │ ├── _extraction/ # Property extraction
234
+ │ │ ├── building.py # BuildingProperties dataclass
235
+ │ │ ├── extract.py # Main orchestrator
236
+ │ │ ├── footprint.py # Footprint features
237
+ │ │ └── image.py # Image features
238
+ │ ├── _features/ # Feature pipelines
239
+ │ │ ├── height/ # Height estimation
240
+ │ │ └── materials/ # Material segmentation
241
+ │ ├── _images/ # Image acquisition
242
+ │ │ ├── camera/ # Camera parameters
243
+ │ │ └── download.py # Street View API
244
+ │ └── _models/ # ML models
245
+ │ ├── huggingface/ # SegFormer segmentation
246
+ │ ├── lcnn/ # Line detection
247
+ │ └── vpts/ # Vanishing points
248
+ └── tests/ # Test suite
249
+ ```
250
+
251
+ ## Citation
252
+
253
+ If you use imageable in your research, please cite:
254
+
255
+ ```bibtex
256
+ @software{imageable2025,
257
+ author = {Ngo, Khoi and Legaria, Uriel and Sandoval Olascoaga, Carlos},
258
+ title = {imageable: Computer Vision Library for Urban Building Analysis},
259
+ year = {2025},
260
+ url = {https://github.com/scalable-design-participation-lab/imageable}
261
+ }
262
+ ```
263
+
264
+ ## License
265
+
266
+ MIT License - see [LICENSE](LICENSE) for details.
267
+
268
+ ## Authors
269
+
270
+ - Khoi Ngo ([Khoi Ngo](https://github.com/billnqk)) - ngo.kho@northeastern.edu
271
+ - Uriel Legaria
272
+ - Carlos Sandoval Olascoaga
273
+
274
+
275
+ Developed at the [Scalable Design Participation Lab](https://github.com/scalable-design-participation-lab), Northeastern University.