02Urban Portrait

City as a Face — generative cartographic portrait studio • v0.2.3

1. Overview

02Urban Portrait transforms urban vector infrastructure (roads, buildings, points) into optical portraits. The user loads a portrait image, maps it to a geographic frame, and the plugin styles vector features by luminance values sampled from the image pixels. This is a generative, non-destructive cartographic technique—no source geometry or attributes are ever modified. The plugin applies a rule-based renderer with five luminance tone bands, each mapped to per-preset colours, line widths, and transparencies.

The plugin is a three-tab dock: Set up (data acquisition and frame definition), Portrait (art-direction controls and rendering), and Export (format export and style restoration). A bonus panel in the Set up tab provides a built-in OSM downloader for one-click city data acquisition.

2. Feature Documentation

2.1 Luminance-Based Styling Engine

Image-to-Vector Sampling Pipeline

  1. Image loading: Supports PNG, JPG, JPEG, TIFF, TIF, WebP, BMP. Auto-scales images larger than 1800×1800 px. Preserves EXIF orientation via QImageReader.setAutoTransform(True).
  2. Geographic frame: The image aspect ratio is fitted to a geographic rectangle (canvas extent or user-drawn frame) with letterbox/pillarbox centring and no stretching. Can be screen-locked (frame follows pan/zoom) or fixed to geographic coordinates.
  3. Sampling: For each visible feature within the frame, the plugin computes sampling points by geometry type and sampling mode, maps world coordinates to normalised image coordinates (flipping Y), samples luminance from the downscaled image, and applies auto-contrast stretch, gamma correction, optional inversion, and optional edge emphasis.
  4. Rendering: A QgsRuleBasedRenderer with 5 tone rules applies per-preset colours, line widths (deepest tones widest, lightest tones thinnest), and transparencies. A custom QGIS expression function zero2portrait_luma(layer_id, feature_id) reads from an in-process cache to drive the rule filters.

2.2 Three Sampling Modes

ModeLine Sample PointsPolygon Sample Points
Fast1 (midpoint)1 (point on surface)
Balanced3 (20%, 50%, 80%)2 (point on surface + centroid)
High Quality5 (10%, 30%, 50%, 70%, 90%)2 (point on surface + centroid)

2.3 Five Tone Rules

Five equal luminance intervals defined by TONE_BREAKS = (0, 52, 104, 156, 208, 256). Each gets per-preset colour, line width (descending from ~1.55 mm for darkest to ~0.10 mm for lightest), and opacity. When hide_highlights is active, the top band ("Paper") has opacity 0.0, letting the background show through—this is how the Ink Portrait and Sepia Blocks presets create white-space faces.

2.4 Rendering Enhancements

Visual Quality Details

Line underlay: A darker, wider base line (+0.35 mm, darkened by 250) is placed 2 layers behind the main line to make it pop from the background.

Polygon fills: Semi-transparent fills (deepest tones alpha 225, medium alpha 150) with thin outlines.

Point symbols: Small circles with outlines.

Line caps and joins: All lines use round cap and round join styles for organic, hand-drawn quality.

2.5 Built-In OSM Downloader

One-Click City Data Acquisition

Adds an XYZ tile OpenStreetMap basemap (with duplicate detection). Downloads the current canvas view via a single Overpass API query (with custom User-Agent header). Validates that viewport is within 6 km × 6 km and 25 km2. Parses the OSM XML response through QGIS/GDAL OGR driver, splitting into three specialised memory layers: OSM Roads (MultiLineString, filtered by highway tag), OSM Buildings (MultiPolygon, filtered by building tag), and OSM Land Use (MultiPolygon, filtered by landuse tag). Each layer carries osm_id, name, and class fields. Tags are extracted from the other_tags HSTORE string via regex.

3. Art Presets

PresetBackgroundColour PaletteCharacter
Ink Portrait#f5f1e8 (warm paper)Dark ink tones; widest lines for shadows, highlights hiddenClassic pen-and-ink portrait
Neon Night#050816 (deep space)Pink / purple / cyan / mint; all bands visibleCyberpunk / synthwave aesthetic
Blueprint#082f49 (deep navy)Cyan / teal gradient (reversed); all bands visibleArchitectural blueprint
Sepia Blocks#f1e3c6 (warm cream)Brown / sepia tones; highlights hiddenAntique map / vintage engraving
Negative City#07071a (deep navy)Indigo / violet gradient (reversed); all bands visibleFilm negative / X-ray aesthetic

4. Image Processing Pipeline

Luminance Enhancement Parameters

5. Controls Summary

TabControlDescription
Set upAdd OSM basemapInserts a live XYZ tile layer
Set upDownload this viewFetches OSM roads, buildings, and land use for the viewport
Set upUpload pictureLoads a portrait image (PNG, JPG, TIFF, WebP, BMP)
Set upVector canvasMulti-select QListWidget of all project vector layers
Set upUse canvas extent / Draw frameDefines the geographic portrait frame
Set upScreen-locked maskWhen on, frame moves with pan/zoom; off = fixed geographic
PortraitPresetDropdown: Ink Portrait, Neon Night, Blueprint, Sepia Blocks, Negative City
PortraitSamplingDropdown: Fast, Balanced, High Quality
PortraitGammaQDoubleSpinBox: 0.2–3.0, step 0.1
PortraitEdge emphasisQDoubleSpinBox: 0.0–1.0, step 0.1
PortraitLayer opacityQDoubleSpinBox: 0.05–1.0, step 0.05
PortraitFeature limitQSpinBox: 500–100,000, step 500, default 10,000
PortraitAuto contrast / InvertCheckboxes for percentile stretch and luminance inversion
PortraitLive updateCheckbox: re-samples on pan/zoom with 240 ms debounce
ExportFormat / DPI / ExportPNG (72–1200 dpi), PDF, or SVG; saves via file dialog
ExportRestore styles / Export QMLReturns layers to original renderers; saves one layer's style as .qml

6. Workflow Guide

  1. Click the 02Urban Portrait toolbar icon. The dock opens on the right.
  2. On the Set up tab, add city data. Use the built-in OSM downloader (Add basemap → pan to a neighbourhood → Download this view) or select existing project vector layers.
  3. Upload a portrait image via the Upload button. A preview thumbnail appears with filename, dimensions, and aspect ratio.
  4. Define the portrait position: either "Use canvas extent" or "Draw frame" (drag a rectangle on the map). Optionally enable "Screen-locked mask" for frame-following.
  5. Select vector layers to stylise from the list.
  6. Switch to the Portrait tab. Choose an art preset, adjust gamma, edge emphasis, and feature limit.
  7. Click Create portrait. The layers are restyled in place with the rule-based renderer. Pan and zoom with live update enabled to see the portrait react.
  8. Switch to the Export tab to export as PNG, PDF, or SVG. Use "Restore original styles" to undo all changes. Use "Export QML" to save a layer's portrait style.

7. Technical Notes

8. Literature

  1. Wood, D. (2010). Rethinking the Power of Maps. Guilford Press.
  2. Harley, J. B. (1989). Deconstructing the map. Cartographica, 26(2), 1–20. DOI: 10.3138/E635-7827-1757-9T53
  3. Schumann, H. & Mueller, W. (2000). Visualisierung: Grundlagen und allgemeine Methoden. Springer.
  4. Brewer, C. A. (2005). Designing Better Maps: A Guide for GIS Users. ESRI Press.
  5. Tufte, E. R. (1983). The Visual Display of Quantitative Information. Graphics Press.