Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

77 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Streetscope: Measuring Gender Representation in Public Spaces

Analyzing classified person-sightings in GoPro wearable-camera imagery collected along routes in four Indian cities.

Key Findings

The tables below are regenerated by scripts/10_analysis.py (via make figures/make tables).

Summary

City Images Pedestrians Female share [95% CI] Sex Ratio (F/1000 M)
Mumbai 2,809 12,331 19.1% [17.4%, 20.8%] 236
Navi Mumbai 2,189 5,186 18.1% [16.0%, 20.2%] 221
Bangalore 2,015 2,311 27.4% [25.7%, 29.1%] 377
Delhi 2,417 3,020 19.8% [17.3%, 22.2%] 246

By Mode

Mode Mumbai Navi Mumbai Bangalore Delhi
Pedestrians 19.1% 18.1% 27.4% 19.8%
Two-wheelers 8.2% 5.3% 8.8% 5.9%

By Road Type

City Primary Secondary Tertiary Residential
Mumbai 20.3% 16.9% 18.6% 20.3%
Navi Mumbai 16.7% 15.9% 18.1% 23.3%
Bangalore 28.8% 22.8% 25.1% 29.4%
Delhi 16.5% 16.8% 19.6% 23.4%

Women-coded pedestrian sightings are below parity in the collected imagery in every city, and the female share is lower among two-wheeler riders than among pedestrians. Census sex ratios are population quantities and are not directly comparable to this route-image sample.

Pipeline

The project is a linear pipeline from sampling design to published results:

geo-sampling → itineraries (allocator) → GoPro collection → EXIF/GPS/frame extraction
  → face-frame extraction → human annotation (Label Studio)
  → parse annotations → assign GPS → enrich with road type → analysis_data
  → figures + tables + maps

Frozen vs. fair-game

The collection half is frozen: it has been run once in the field and on the raw footage, and its outputs (extracted frames, EXIF, GPS index, annotations) are treated as immutable inputs. The analysis half is fair game: it transforms those frozen inputs into the published dataset and outputs and can be re-run freely.

Stage Script(s) Status
Geo-sampling / itineraries (allocator) scripts/gen_data/<city>/run_*_sampler.py frozen
Video processing: EXIF, GPS, frame extraction 00_process_videos.py frozen
Face-detection frame extraction 01_extract_face_frames.py frozen
Coverage QA / frame compression 02_plot_video_coverage.py, 03_compress_frames.py frozen
GPS lookup index / EXIF recovery 04_build_gps_index.py, rebuild_csvs_from_exif.py frozen
Human annotation (Label Studio) external frozen
Parse annotations 05_parse_annotations.py fair game
Assign GPS to frames (ts/lat/lon) 06_assign_frame_gps.py fair game
Enrich with road type (itinerary + OSM) 07_enrich_with_geo.py fair game
Build analysis dataset 08_build_analysis_data.py fair game
EDA / publication figures+tables / maps 09_eda.py, 10_analysis.py, 11_make_maps.py fair game
Descriptive clustered inference inference.py fair game
LLM annotation comparison (optional diagnostic) 12_validate_annotations.py fair game
Inter-rater reliability 13_interrater_reliability.py fair game
Descriptive pattern mining 14_descriptive_patterns.py fair game

Run the analysis half

The analysis half starts from the frozen GPS index and annotations and never re-touches videos or frames:

# One city, end to end (analysis_data + its figures/tables/maps), using cached GPS index:
make analyze CITY=mumbai

# Regenerate figures/tables/maps across cities from existing analysis_data:
make figures CITIES=mumbai,navi_mumbai

# Tables only:
make tables CITIES=mumbai,navi_mumbai

Equivalent direct invocation:

.venv/bin/python scripts/run_pipeline.py --city mumbai --skip-rebuild-gps

Re-running collection (frozen — only if raw footage changes)

# Re-process videos and re-extract frames (requires video_dir in cities.yaml):
.venv/bin/python scripts/run_pipeline.py --city mumbai --process-videos

Inference

The primary estimand is the share of classified pedestrian sightings coded as women: sum(women pedestrians) / sum(all pedestrians). This definition is also used in the Google Street View analysis. Combined pedestrian/two-wheeler estimates and image-level means are secondary.

The extracted images are face-triggered frames along collected routes, not a probability sample of streets or residents. Results therefore describe visible classified sightings in the collected imagery. Confidence intervals use a collection-day cluster sandwich with a t distribution on G−1 degrees of freedom; they quantify variability across the observed fieldwork days and do not imply population representativeness.

Counts recorded as 10+ are interval-censored. The primary tables use 11, the known minimum, and report sensitivity to replacement values 15, 20, and 30.

The optional OpenAI comparison is a diagnostic, not a gold-standard validation. Install it with uv sync --all-extras; the script defaults to the pinned image-capable model snapshot gpt-4o-2024-11-20 and performs no request unless --submit or --check is supplied.

Setup

# System tools (macOS)
brew install ffmpeg exiftool

# Python environment (uv-managed .venv):
make install

make install installs the pinned analysis and development dependencies from uv.lock.

Optional: OSM ground-truth road type

07_enrich_with_geo.py can attach an OSM "ground truth" road type alongside the itinerary road type. It is skipped automatically unless the city's PBF is present. Download the region from Geofabrik into data/osm/ using the filename in cities.yaml, e.g.:

data/osm/maharashtra-latest.osm.pbf   # mumbai, navi_mumbai
data/osm/karnataka-latest.osm.pbf     # bangalore

When present, tableS1_road_type.tex gains an OSM ground-truth section.

Directory Structure

scripts/
  gen_data/{city}/           Sampling-design scripts (frozen)
  00_process_videos.py ...   Pipeline scripts (see table above)
  inference.py               descriptive collection-day clustered inference
  run_pipeline.py            Analysis-half orchestrator
data/
  {city}/
    exif/                    Raw EXIF text files (frozen)
    gps_index/               GPS lookup parquet files (frozen)
    labelstudio/             Label Studio JSON exports (frozen)
    face_frame_metadata.csv  Face-detection frame log
    analysis_data.parquet    Final analysis dataset (primary annotator)
    analysis_data_long.parquet  Long format (all annotators)
  annotation_task/           Extracted frames for annotation
  osm/                       Optional OSM PBFs for ground-truth road type
sampling/
  {city}/itineraries/        Itinerary road-type classifications
figs/                        Generated figures and maps
tabs/                        Generated LaTeX tables
cities.yaml                  Per-city config (video_dir, osm_file, timezone)
Makefile                     Analysis-half workflow targets

Outputs

Data

  • data/{city}/analysis_data.parquet - Primary analysis dataset
  • data/{city}/analysis_data_long.parquet - Long format (all annotators)

Figures (figs/)

  • fig2_distribution.pdf - Proportion female distribution
  • fig3_multipanel.pdf - Multi-panel summary (mode, road type, POI, time)
  • fig4_weekday_weekend.pdf - Weekday vs weekend comparison
  • fig5_pedestrian_crowdsize.pdf - Female share by pedestrian crowd size
  • map_locations_{city}.pdf / .html - Data collection locations
  • map_sexratio_{city}.pdf / .html - Female share by ~500m cell
  • map_overview_india.pdf - All cities on one India basemap
  • eda_*.pdf - Exploratory analysis plots

Tables (tabs/)

  • table1_city_summary.tex - City-level summary
  • tableS1_road_type.tex - By road type (itinerary + optional OSM ground truth)
  • tableS2_temporal.tex - Temporal patterns
  • tableS3_poi_infrastructure.tex - POI and infrastructure
  • tableS4_irr.tex - Inter-rater reliability (via make irr)
  • descriptive_patterns.md - Accompaniment, place rankings, joint regression

Data Coverage

Metric Mumbai Navi Mumbai
GPS coverage 97.4% 99.4%
Itinerary match 66.3% 72.1%
Hour range (IST) 7-19 9-18

Bangalore and Delhi are annotated and included in the analysis outputs. Hyderabad has sampling itineraries and partially processed footage (face frames extracted); annotation/analysis for it is in progress.

Per-frame counts are top-coded at 10 ("10+" recorded as 11), and collection spans roughly 06:00-22:00 IST only.

License

MIT

About

Missing Women On the Streets: Evidence from Mumbai, Navi Mumbai, Delhi, and Bangalore.

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages