Metadata-Version: 2.4
Name: facadescapy
Version: 0.1.0a3
Summary: Tools for street-level facade imagery, rectification, annotation data, and facade-analysis workflows.
Author: Anthony Suppa
License: BSD-3-Clause
Keywords: facades,street-level-imagery,mapillary,rectification,annotation,window-to-wall-ratio
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: BSD License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: GIS
Classifier: Topic :: Scientific/Engineering :: Image Processing
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.24
Requires-Dist: opencv-python>=4.8
Requires-Dist: pandas>=2.0
Requires-Dist: pyproj>=3.6
Requires-Dist: requests>=2.31
Requires-Dist: shapely>=2.0
Provides-Extra: geo
Requires-Dist: duckdb>=0.10; extra == "geo"
Requires-Dist: fiona>=1.9; extra == "geo"
Requires-Dist: fsspec>=2024.0; extra == "geo"
Requires-Dist: geopandas>=0.14; extra == "geo"
Requires-Dist: osmnx>=2.0; extra == "geo"
Requires-Dist: pyarrow>=14.0; extra == "geo"
Requires-Dist: s3fs>=2024.0; extra == "geo"
Provides-Extra: maps
Requires-Dist: contextily>=1.6; extra == "maps"
Requires-Dist: geopandas>=0.14; extra == "maps"
Requires-Dist: matplotlib>=3.8; extra == "maps"
Provides-Extra: annotation
Requires-Dist: fastapi>=0.110; extra == "annotation"
Requires-Dist: pydantic>=2.0; extra == "annotation"
Requires-Dist: python-multipart>=0.0.9; extra == "annotation"
Requires-Dist: uvicorn[standard]>=0.27; extra == "annotation"
Provides-Extra: training
Requires-Dist: ultralytics>=8.0; extra == "training"
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: ruff>=0.5; extra == "dev"
Requires-Dist: twine>=5.0; extra == "dev"
Dynamic: license-file

﻿# facadescapy

`facadescapy` is an early-stage Python package for street-level facade imagery workflows: selecting and downloading Mapillary images, rectifying facade views, preparing facade geometry, and generating manifests.

This first alpha release is intentionally focused on stable, model-independent functionality. Deep learning inference and training integrations are kept out of the core dependency set while the model and licensing path is finalized.

## Planned first-release scope

- Mapillary metadata and image download helpers
- Equirectangular-to-perspective rectification for facade imagery
- Facade-oriented geometry utilities, including splitline preparation and street-facing segment helpers
- OSM and EUBUCCO geometry helpers behind optional geospatial dependencies
- Manifest read/write helpers for batch image preparation
- Thin CLI entry points for common batch workflows

## Development facade workflow

The development notebook uses the following geometry sequence:

1. `make_building_splitlines(..., min_length_m=0)` records the source ring.
2. `simplify_building_footprint(...)` simplifies the complete WGS84 footprint
   in a local metric CRS. This is the footprint-level operation for noisy
   EUBUCCO rings; it is separate from the row-based simplifiers.
3. `make_building_splitlines(...)` creates the usable facade rows.
4. `identify_street_facing_segments_from_roads(...)` classifies road-facing
   rows.
5. `connect_jogged_facades(...)` extends flags across short jogs. Its existing
   jog-detection behavior is unchanged.

The splitline APIs use `segment_index` as the canonical field and retain
`segment_idx` as a compatibility alias. Simplified rows preserve source
metadata, including list-valued EUBUCCO fields, building IDs, and Shapely
geometry objects.

Small road queries use the standard OSM map-bbox API first. Overpass queries
use a 30-second request timeout, skip the additional rate-limit status
preflight for this low-volume interactive workflow, and fail over between two
public instances. Pass `overpass_urls=[...]` when a local or
organization-specific endpoint is preferred. Successful building/road feature
results are cached under `data/osm_feature_cache`.

## Automatic facade candidate ranking

`rank_mapillary_facade_candidates` searches around every eligible facade,
filters image/facade pairs geometrically, rectifies the surviving images, and
ranks them using geometry, resolution, rectification plausibility,
completeness, sharpness, exposure, and an occlusion proxy. It therefore does
not equate the nearest camera with the best facade capture.

```python
from facadescapy.facade_selection import (
    FacadeSearchConfig,
    prepare_building_facades,
    rank_mapillary_facade_candidates,
)

splitlines = prepare_building_facades(buildings_gdf, roads_gdf, building_row=0)
result = rank_mapillary_facade_candidates(
    splitlines,
    access_token,
    config=FacadeSearchConfig(top_n=5),
)
best = result.best
display(result.summary)
```

The default `annotation` padding profile deliberately keeps generous context
on every side so a reviewer can crop later. Use `padding_profile="compact"`
for the previous tighter behavior. Edge-content checks now cover top, bottom,
left, and right; leveling estimates how much its valid-pixel crop removes and
reruns rectification with a padding guard. Outputs with excessive residual
slant, inconsistent axes, camera-coordinate disagreement, or content touching
the final border are marked `needs_review` and ranked behind clean candidates.

For reproducible bulk comparisons, `run_facade_batch` accepts either a
contiguous positional slice or an explicit sequence of building rows and
writes source images, rectified images, per-image JSON metadata, and a
resumable CSV manifest. By default it also saves an OSM-backed diagnostic map
showing surrounding buildings and roads, the target building and facade chain,
camera position/view ray, camera heading, and facade normal. Install the map
dependencies with `pip install -e ".[maps]"`; if a tile request fails, the
vector overlay is still saved and `map_status` records the fallback.

Set `replay_manifest_path` to seed an earlier run. `replay_mode="end_to_end"`
keeps normal discovery while ensuring those image IDs are evaluated;
`replay_mode="locked"` disables discovery and locks the recorded image and
facade row for a controlled rectification comparison.

## Installation

From a local checkout:

```bash
pip install -e .
```

With optional geospatial functionality:

```bash
pip install -e ".[geo]"
```

The geospatial extra requires OSMnx 2.x with Shapely 2.x. If an existing
environment reports `cannot import name 'TopologicalError' from shapely.geos`,
upgrade OSMnx with `python -m pip install --upgrade "osmnx>=2.0"`.

With annotation-server dependencies:

```bash
pip install -e ".[annotation]"
```

The `training` extra currently includes Ultralytics and is license-sensitive because Ultralytics YOLO is AGPL-3.0 by default unless a separate license applies.

## CLI

```bash
facadescapy --help
facadescapy build-manifest --help
facadescapy rectify --help
```

## License

BSD 3-Clause. See `LICENSE`.

## Notices

This project is not affiliated with Mapillary, Meta, OpenStreetMap, EUBUCCO, Ultralytics, or any facade product manufacturer. Users are responsible for complying with external data, imagery, model, and software licenses.
