城市感知评估系统实战:基于CNN街景语义分割的应用

发布时间:2026/8/26 6:13:05
城市感知评估系统实战:基于CNN街景语义分割的应用 简介计算机视觉与深度学习的结合正在重塑城市空间研究的方式。语义分割作为图像理解的核心技术之一能够对街景图像进行逐像素的类别解析从而将绿化率、天空开阔度、人行道占比等物理指标转化为可量化的城市感知评分。本文从技术原理出发剖析卷积神经网络在语义分割任务中的模型选型、损失函数设计与训练调参思路进而讨论如何建立从像素掩膜到感知评分体系的工程化管线。该方案在城市体检、街道品质评估、智慧城市治理等场景中具有明确的应用价值。当需要衡量一座城市的空间体验时训练一个高精度分类网络并非关键真正重要的是构建一套可解释、可复现的评估机制。本文围绕街景图像数据集的构建、CNN分割模型的部署以及评分系统的整体架构系统复盘了一套城市感知评估系统的完整落地路径。 拿到“基于卷积神经网络的城市感知评估系统源码与数据集高分毕业设计项目”这个题目时很多同学第一反应是这不就是一个图像分类项目吗用CNN训练一个模型能区分街景是干净还是脏乱、是安全还是危险然后交差。但真正动手做下去才会发现这个题目的关键难点根本不在“训练一个CNN”而在于你怎么把“城市感知评估”这个偏社会科学的概念翻译成一套可计算、可复现、可演示的计算机视觉系统。这篇文章我想从数据、模型、评分体系到系统部署完整复盘一遍做这类项目的思路和踩坑记录给正在做或准备复现类似毕设的同学一个可以直接参考的路线。1. “城市感知评估”这个毕设题目本质上在考察什么1.1 毕设题目里的“评估”二字为什么比CNN本身更关键城市感知评估简单说就是用街景图像、卫星影像等数据去量化人对城市空间的主观感受。比如一条街道看起来是否整洁、绿化多不多、天空视野是否开阔、步行体验是否友好。这个方向在学术界并不新鲜MIT就做过Place Pulse项目让大量用户给不同城市的街景照片打分然后训练模型去预测这种“感知分数”。国内这几年城市更新、街道品质提升的项目很多用图像数据做大规模城市体检也成了一个热门方向。所以毕业设计选这个题目底层逻辑是成立的。但它真正考察的不是你会不会调一个分类网络而是三件事第一你能不能把“感知”这个抽象概念拆解成可计算的具体维度第二你能不能自建一套可用的街景数据集哪怕是中小规模第三你能不能把模型输出变成一套有逻辑的评价系统而不只是一个黑盒分数。1.2 城市感知评估的经典维度与可计算指标把这个题目落到具体指标上常见的维度大致可以分成六类绿化水平植被覆盖度、树冠连续度空间开阔度天空可见比例、街道宽高比整洁度垃圾、杂物、墙面破损等异常元素的出现频率步行友好度人行道连续性、行人空间占比界面丰富度沿街建筑立面、店铺密度等安全感视野通透性、夜间照明、行人活动密度等。每一项都不是让CNN直接回归一个0到100的分数而是先通过语义分割得到像素级类别分布再基于类别像素占比去计算物理层面的量化指标。这样做的好处是每个分数都可解释答辩的时候你能说清楚“绿化率67.3分”是怎么来的而不是含糊地说“模型认为这张图比较绿”。1.3 一个完整项目需要拆成哪几个模块做这种“系统”级毕设最忌讳一上来就写模型代码。我建议直接按四条流水线来规划数据层街景图像采集与清洗、公开数据集整合、标注规范制定模型层基于CNN的语义分割模型训练、调优、对比实验指标层从分割掩膜计算各类别占比映射到感知维度和评分展示层Web端上传图片、输出评分、可视化分割效果。这样拆完之后你会发现“卷积神经网络”只是中间一环前端的样本质量、后端的指标计算逻辑同样决定项目上限。2. 数据集是命根子公开数据集打底自建样本补差异2.1 公开语义分割数据集迁移学习的起点训练一个能用于城市感知评估的模型不能只靠几十张自己拍的街景照片。CV领域已经有不少公开的街景语义分割数据集最常见的两个Cityscapes欧洲城市街景精细标注5000张30类适合做预训练和迁移学习AeroScapes无人机视角的航拍分割数据集包含天空、建筑、道路、植被等类别有助于模型理解俯视场景下的城市结构。在项目初期我建议直接用公开数据集的预训练权重做初始化或者在公开数据集上先跑一个baseline确认自己的训练管线没有bug。这里有个容易被忽略的点公开数据集里的类别和你自己定义的类别不一定完全对齐。比如Cityscapes里有“sky”“vegetation”“building”“road”“person”“car”等这些可以直接映射到你的感知评估维度里。但如果你要加“垃圾堆积”“占道经营”这类特异类别公开数据集里没有就必须自建样本。2.2 自建街景样本集采集、标注与类别体系自建数据集首先要解决“从哪里拿街景图”的问题。最稳妥的方式是通过地图开放平台申请街景图片接口输入经纬度或道路坐标获取指定视角的静态图。这条路径比爬虫合规得多权限清晰代码也不复杂。采集时建议按网格或者道路均匀采样覆盖不同城区、不同时间段避免数据集中在一个商圈或者景区。类别体系设计要时刻想到后面的指标计算。我自己的项目里用了以下类别类别含义主要关联指标sky天空区域空间开阔度building建筑立面界面丰富度、街道尺度road机动车道交通属性、硬质面占比sidewalk人行道步行友好度vegetation树木、灌木、草地绿化率、绿视率person行人活力、安全感vehicle汽车、自行车拥堵程度、场景嘈杂度street object路灯、电箱、长椅等街道设施完善度other其他背景辅助类别标注工具我用过LabelMe和X-Anylabeling两者都支持多边形标注和导出JSON格式。如果是一个人标注一条规律要记牢宁可类别少不能标注乱。建议先把标注规范写清楚比如“人行道被树冠遮挡时归到vegetation还是sidewalk”这类边界情况不提前定好后面训练会反复返工。2.3 数据增强和数据集划分被多数人忽略的两个细节数据增强方面随机翻转、裁剪、色域抖动这些常规操作肯定要做。针对街景项目我特别建议大家把“亮度对比度扰动”和“随机遮挡”做强一点。因为不同城市、不同天气下街景亮度差异很大模型如果只在晴天样本上训练换到阴天就容易崩。数据划分有个更隐蔽的坑直接随机划分train/val/test会导致同一街道的相似图片同时出现在训练集和验证集里验证指标虚高。正确做法是按街道或按采样区域划分保证模型真正见过的是不同类型片区而不是记住了同一条街的纹理。我第一批模型mIoU看起来不错但换一条没见过的街道测试效果立刻掉下来后来改成按区域划分才暴露了真实水平。3. 让CNN看懂街景模型选型、损失函数与训练调参记录3.1 为什么不是图像分类也不是目标检测而是语义分割做城市感知评估核心任务是逐像素理解场景结构。图像分类只能告诉你“这张图是商业街还是居民区”没有办法回答“绿化像素占比是多少”目标检测能框出树、行人、车但树冠遮挡建筑时边界关系完全没法表达。只有语义分割能输出每个像素的类别标签让后续的像素级统计成为可能。很多人一开始会想用YOLO做目标检测然后数目标个数来代替感知评估。这个思路只适用于少数场景比如统计车流量。但绿化率、天空开阔度这种指标目标检测基本无能为力。所以模型主线一定选语义分割检测模型最多作为辅助。3.2 骨干网络与分割头的选型对比毕设项目的算力通常有限不太建议直接上Swin Transformer这类大模型。我用过的方案里三个组合值得参考骨干网络分割头显存占用实际效果适用场景ResNet34UNet Decoder约6GB512x512mIoU约0.65入门baseline训练快ResNet50UNet Decoder约8GB512x512mIoU约0.73最终方案主力EfficientNet-B4DeepLabV3 ASPP约10GB512x512mIoU约0.75追求精度需要更好显卡训练时用timm库加载预训练骨干权重效率很高。简单贴一下我用的模型骨架构建方式import torch.nn as nn import timm class SegModel(nn.Module): def __init__(self, encoder_nameresnet50, num_classes9, decoder_channels256): super().__init__() self.encoder timm.create_model( encoder_name, pretrainedTrue, features_onlyTrue, out_indices[1, 2, 3, 4] ) # 以ResNet50为例四个阶段输出通道分别为256, 512, 1024, 2048 self.decoder UNetDecoder( encoder_channels[256, 512, 1024, 2048], decoder_channelsdecoder_channels, num_classesnum_classes ) def forward(self, x): features self.encoder(x) return self.decoder(features)UNet Decoder的核心思想是把深层语义信息和浅层细节信息逐级融合对小目标比如行人、路灯比较友好。DeepLabV3则用ASPP模块在多个膨胀率下提取上下文对“大块区域”更好。如果你预算有限先老老实实跑通ResNet34UNet再换ResNet50性价比最高。3.3 训练配置、损失函数与评估指标训练配置我用的是输入尺寸512x512优化器AdamW初始学习率1e-4学习率策略warmup 5个epoch后余弦衰减损失函数CrossEntropy Loss Dice Loss权重比为0.7:0.3训练轮数80到100轮Batch Size8单卡12GB如果显存不够降到4并用梯度累积。加Dice Loss的原因很直接街景数据里“天空/建筑/道路”这类大类别占比很高“行人/路灯”等小类别占比很低交叉熵会被大类别带偏Dice Loss对小类别的梯度信号更友好。训练过程中mIoU从0.38起步最终稳定在0.73左右。这个数字不算惊艳但对一个中等规模自建数据集来说已经够用。评估时不要只看accuracy。街景图像里背景占比太高像素准确率很容易虚高到90%以上实际上小目标全没分出来。要同时看mIoU、各类别IoU、F1分数答辩时也更有说服力。4. 从分割掩膜到城市评分核心源码组织与指标计算管线4.1 项目源码目录先有结构再有功能“系统”和“脚本”的区别在于工程组织。我的项目目录结构大致是这样的city-sense/ ├── data/ │ ├── images/ │ ├── masks/ │ └── annotations/ ├── configs/ │ └── train_config.yaml ├── models/ │ ├── backbones.py │ └── decoder.py ├── train.py ├── infer.py ├── metrics/ │ ├── semantic_metrics.py │ └── perception_scores.py ├── web/ │ ├── app.py │ ├── templates/ │ └── static/ └── utils/ ├── dataset.py ├── transforms.py └── visualize.py这样拆的好处是训练、评估、指标计算、Web展示各模块之间松耦合。改模型结构不影响评分计算改评分逻辑也不用重新训练。4.2 从预测掩膜到评价指标的计算逻辑推理阶段把所有测试图片输入模型得到每张图的预测掩膜。掩膜本质上是一个二维数组每个位置的值是类别ID。接下来的计算逻辑就变得很简单统计每个类别像素数占总像素数的比例再映射到各个感知维度。比如我定义了几个核心子指标绿化率 vegetation像素数 / 总像素数天空开阔度 sky像素数 / 总像素数道路视野占比 road像素数 / 总像素数步行友好度 sidewalk像素数 / 总像素数建筑界面密度 building像素数 / 总像素数。然后把这些“原始比例”做了百分位归一化映射成0到100的分数。这一步很重要因为不同城市绿化基线不同直接拿原始占比去做对比不公平。实际计算代码很简单用numpy就能实现import numpy as np def compute_perception_scores(mask, class_ids): total mask.size ratios {} for name, cls_id in class_ids.items(): ratios[name] (mask cls_id).sum() / total scores {} # 以绿化率为例使用百分位归一化 scores[green_score] np.clip(ratios[vegetation] * 250, 0, 100) scores[openness_score] np.clip(ratios[sky] * 200, 0, 100) scores[walkability_score] np.clip(ratios[sidewalk] * 220, 0, 100) # 综合感知评分 scores[overall] ( 0.3 * scores[green_score] 0.3 * scores[openness_score] 0.2 * scores[walkability_score] 0.2 * scores[building_interface_score] ) return scores这里的系数250、200、220是基于我自己的统计分布调的目的是让常见街道的分数落在40到80之间避免所有结果都集中在60分附近。你可以根据自己数据集的分布重新标定。4.3 网页端与可视化让系统“看得见”毕业设计答辩时评委最吃“可交互”这一套。我用Flask写了一个非常轻量的Web应用逻辑只有两步前端上传图片后端调用训练好的模型推理返回评分和可视化掩膜图。from flask import Flask, request, jsonify, render_template import cv2 import numpy as np app Flask(__name__) app.route(/predict, methods[POST]) def predict(): file request.files[image] img np.frombuffer(file.read(), np.uint8) img cv2.imdecode(img, cv2.IMREAD_COLOR) img cv2.resize(img, (512, 512)) mask model.predict(img) scores compute_perception_scores(mask, class_ids) vis overlay_mask(img, mask) return jsonify({ scores: scores, visualization: encode_image(vis) })可视化里我最推荐的方式是原始街景图上叠加半透明彩色掩膜每一类用一种颜色右上角显示综合评分再用matplotlib输出一个雷达图。这样一张图就能同时呈现“模型看到了什么”和“评估结果怎么样”答辩时的信息密度比单独贴一张网络结构图高得多。4.4 参考评测结果用数据说明模型有效做完整套管线我建议表格里至少留三组数据公开数据集Cityscapes上的mIoU、自建数据集上的mIoU、最终感知评分与人工评分的相关性。人工评分相关性这个数字非常关键。你可以找5到10个人对20到30张街景图打1到5分的“整体感知分”然后和模型输出的overall分数做皮尔逊相关系数。相关性达到0.7以上基本就能说明模型不是自嗨。这部分如果做好了毕设的创新点和效益分析都有了直接证据。5. 实际训练与部署中最容易翻车的六个坑5.1 标注不一致最先崩溃的是数据集而不是模型做语义分割项目模型表现差有一半以上是标注质量问题。常见情况是标完第一遍之后发现同一种事物在不同图片里归到了不同类别或者多边形边界不齐。这个问题不会立刻暴露在训练损失里但会严重限制mIoU的上限。解决方式没有捷径制定标注规范 抽检交叉验证。我自己是第一遍标完全部图片后随机抽20%让另一个同学独立标注计算类别一致性把不一致的图片找出来重新对齐。这一步虽然枯燥但对模型精度的提升是决定性的。5.2 类别不平衡绿化占比大行人占比小街景数据里植被、天空、建筑、道路占了绝大多数像素行人、自行车、路灯可能只占不到1%。如果不做处理行人这类目标基本学不出来。我在项目里试了三种方案在损失函数里按类别像素频率倒数加权加入Dice Loss对包含小目标的图片做过采样让同一张小目标图片多训练几个epoch。组合起来之后行人IoU从0.11提升到了0.35左右。虽然还是不高但已经能用于感知指标计算了。5.3 换个街道就失灵泛化能力的真实差距我在3.2节提到按区域划分train/val这个设计直接决定了模型的泛化表现。如果训练数据里全是大学城附近的街景换到老城区光线条件、建筑风格、植被类型完全不一样分割结果会迅速劣化。缓解方案主要有两个一是采集数据时按城市功能区分层采样商业区、住宅区、工业区、公园周边都要覆盖二是训练时用较强的颜色抖动和模糊增强强迫模型学习形状和上下文而不是死记颜色。5.4 显存不足与训练太慢的工程解法学生显卡最常见的是8GB到12GB。512x512输入、ResNet50编码器Batch Size开到8已经是上限再大就会爆显存。如果还想刷精度有几个工程手段混合精度训练PyTorch AMP显存占用降低约30%速度提升20%左右梯度累积模拟更大的Batch Size推理时用patch-wise滑动窗口对大图切成512x512小块再拼接。实测下来16GB显卡跑80轮约需要6到8小时12GB显卡要10小时以上。训练时可以固定随机种子保证可复现这也是毕设报告里会被追问的点。5.5 边缘粗糙与指标失真容易被答辩老师抓住的破绽语义分割的边缘通常带锯齿一旦掩膜边缘不平滑会导致绿化率和建筑界面密度发生系统性偏移。答辩时如果评委放大看可视化图边缘粗糙是特别明显的减分项。处理方式有两层第一层推理后对掩膜做一轮中值滤波去掉零散噪点第二层如果还想更精细可以在特定类别上做条件随机场CRF后处理但CRF速度慢毕设里没有太大必要。我用了中值滤波后mIoU基本不变但视觉观感好了很多。5.6 模型部署与演示环节的临场问题Web演示崩溃的常见原因有三个推理耗时太长、内存占用过高、模型文件太大无法提交。我最后的模型文件是ResNet50UNetPyTorch权重约200MB放在GitHub上有点吃力。后来导出成ONNX格式体积压到120MB左右CPU推理单张512x512大约0.8秒演示起来完全够用。如果想让系统更完整还可以在Web端加一个“按片区汇总”的页面对每条街道的多张图片评分取平均输出街道级感知热力图。这个功能不需要改模型只是把评分结果做一次聚合但演示效果会提升一个档次。6. 做完这个项目后我想对准备复现的人说6.1 训练时间占比其实没有数据整理高整个项目做下来我最直观的感受是模型训练只占不到三分之一的时间剩下的时间全在采集、标注、清洗、调试指标计算逻辑。如果你准备复现最好一开始就把数据集建设当作一个正式模块来规划而不是临时凑几百张图。数据整理的规范性决定了后面所有工作的上限。6.2 给想复现这个项目的同学三条实操建议第一不要一开始就追新模型。先拿ResNet34UNet跑通端到端管线从数据到评分再到Web展示然后再考虑换ResNet50、加ASPP、提升精度。先把完整链路跑通比单独提高2个点mIoU重要得多。第二自建数据集的采集策略要从“按城区分布”出发不要图省事只采校园周边。泛化能力在答辩中会被反复质疑而这是数据层面决定的事。第三把“感知评分”和“人工评分”的相关性实验提前到中期。如果能拿到0.75以上的相关性系数你的毕设就有了一个很强的闭环证据链数据支撑模型、模型支撑指标、指标符合主观感知。如果后续想把项目做得更大可以尝试接入多时相数据比较不同季节的绿化感知差异或者把街景评分结果按地理坐标聚合到地图上输出城市感知热力图。这些方向都不需要推翻现有架构属于“锦上添花”式的延伸。做完这个项目我对城市计算和视觉感知交叉方向的兴趣更浓了这种“用图像量化空间体验”的思路后续无论是找工作还是继续读研都会是一个很有辨识度的切入点。本文还有配套的精品资源点击获取

相关新闻