BE 498 / BE 598Computer Vision Applications in Architecture and Urban Environments
Computer Vision Applications in Architecture and Urban EnvironmentsUNIVERSITY OF WASHINGTONCollege of Built EnvironmentsComputer VisionApplications in Architectureand Urban EnvironmentsBE 498 / BE 59801 Visual data foundationsEmerging technologies, images and spatial dataBE 498 / BE 59801Suzzallo Library. A.Schneider83, CC BY-SA 4.0.
LIVE 01

Run the complete Python workflow. The first run loads the computing environment.

[1] Python

Code explanations

Results

Ctrl / ⌘ + Enter: run all

Display helper functions

These functions display computed images, maps and tables. The editable cells perform image processing, geometry calculations, acquisition and file operations.

import json, io, base64
import numpy as np
from PIL import Image, ImageDraw
RESULTS = []
def show_image(image, title=''):
    if isinstance(image, np.ndarray): image = Image.fromarray(image)
    buffer = io.BytesIO(); image.save(buffer,format='PNG')
    RESULTS.append({'kind':'image','title':title,'src':'data:image/png;base64,'+base64.b64encode(buffer.getvalue()).decode()})
def show_table(rows, title=''):
    RESULTS.append({'kind':'table','title':title,'rows':rows})
def show_summary(title, facts, explanation=''):
    RESULTS.append({'kind':'summary','title':title,'facts':facts,'explanation':explanation})
def keep_file(path):
    RESULTS.append({'kind':'file','name':path.rsplit('/',1)[-1],'data':base64.b64encode(open(path,'rb').read()).decode()})
def show_map(routes,samples,building,title='',camera=None,linked_id=None):
    area=building.buffer(buffer_m)
    if camera is not None: area=area.union(camera.buffer(15))
    bounds=area.bounds
    x0,y0,x1,y1=bounds; scale=610/max(x1-x0,y1-y0)
    def xy(x,y):return (45+(x-x0)*scale,655-(y-y0)*scale)
    im=Image.new('RGB',(720,720),'#faf9fc');d=ImageDraw.Draw(im)
    for route in routes:d.line([xy(x,y) for x,y in route['geometry'].coords],fill='#aaa4b1',width=2)
    d.polygon([xy(x,y) for x,y in building.exterior.coords],fill='#e5d7b0',outline='#8c7749')
    for p in samples:
        x,y=xy(p['geometry'].x,p['geometry'].y);d.ellipse((x-2,y-2,x+2,y+2),fill='#4b2e83')
    if camera is not None:
        cx,cy=xy(camera.x,camera.y)
        matched=next((p for p in samples if p['sample_id']==linked_id),None)
        if matched:
            mx,my=xy(matched['geometry'].x,matched['geometry'].y)
            d.line([(cx,cy),(mx,my)],fill='#197148',width=3)
            d.ellipse((mx-7,my-7,mx+7,my+7),outline='#197148',width=3)
        d.ellipse((cx-7,cy-7,cx+7,cy+7),fill='#d65c12',outline='#fff',width=2)
        d.text((cx+11,cy-10),'Camera (source)',fill='#9b400b')
    d.text((30,15),f'Suzzallo | {len(samples)} planned points | spacing={spacing_m:g} m',fill='#312744')
    d.text((660,30),'N ^',fill='black');d.line([(45,680),(45+50*scale,680)],fill='black',width=3)
    d.text((45,688),'50 m',fill='black')
    d.text((350,688),'OSM contributors | ODbL 1.0',fill='#5b5364')
    show_image(im,title)
Case photograph: Suzzallo Library, A.Schneider83, CC BY-SA 4.0, captured November 29, 2014. Map data: © OpenStreetMap contributors, ODbL 1.0, snapshot October 17, 2026. The building geometry represents an OSM building part. Source camera coordinates are retrieved in Live 5 and have no independent survey validation here.
Live 5 retrieves Wikimedia metadata and the original JPEG. Google Street View is a separate parameter example with no configured request. Code, responses and results save in this browser without cross-device synchronization.
Street View parameters · Metadata · Usage requirements · GeoPackage · Python runtime
1 / 55