前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >手把手教你5行代码实现街景图片语义分割并计算绿视率与天空率

手把手教你5行代码实现街景图片语义分割并计算绿视率与天空率

作者头像
DataCharm
发布2021-02-22 15:18:12
7.5K7
发布2021-02-22 15:18:12
举报

今天特意带来压箱底的教程,教大家5行代码实现街景图片的语义分割,并计算绿视率与天空率!

相信大家对针对街景图片计算绿视率和天空率一定并不陌生,这类研究应该是在2018年兴起,国际上做的比较知名的应该是张帆老师(感兴趣的可以关注他们的城室科技官网,非常不错),跟交通方面结合的比较紧密的是城大的陆毅老师,国内的话就是清华的龙瀛老师和同济的叶宇老师,还有很多大牛,不过我看过的文章大多是以上几位的,比如:

Fan, Z. , Bolei, Z. , Liu, L. , Yu, L. , Fung, H. H. , & Hui, L. , et al. (2018). Measuring human perceptions of a large-scale urban region using machine learning. Landscape and Urban Planning, 180, 148-160.

Wang, R. , Lu, Y. , Wu, X. , Liu, Y. , & Yao, Y. . (2020). Relationship between eye-level greenness and cycling frequency around metro stations in shenzhen, china: a big data approach. Sustainable Cities and Society, 102201.

叶宇,张灵珠,颜文涛,曾伟.街道绿化品质的人本视角测度框架——基于百度街景数据和机器学习的大规模分析[J].风景园林,2018,25(08):24-29.

还有很多这里就不一一列举了。感兴趣的同学可以自行搜索一下。


下面说说语义分割。

简单来说,语义分割就是利用深度学习技术把图片中的物体分类,为每一个像素赋予一个类别。因此我们计算绿视率与天空率的思路就是,首先利用模型对图片进行语义分割,为每个像素赋予类别,然后用所有代表绿植/天空的像素数除以图片中所有的像素数,就可以得到对应的绿视率/天空率。

实际上语义分割是非常成熟的技术,github上项目一搜一大把。但我在学习这玩意的过程中,发现github上各类项目实际上很难用。首先就是配置环境的问题,从caffe到keras,什么框架的都有,安装的时候坑贼多

。再有就是模型训练的问题,训练数据集和标签的准备,以及训练时文件夹的设置也十分令人抓狂,此外很少有项目是基于cpu的,这给mac党带来了很大的不便。就算以上的东西你都搞定了,用自己的电脑,训练起来也贼慢(涉及到迁移学习可能好一点,但这也增加了学习成本)。然而我们只是想利用现有的SOTA(state-of-the-art)的技术完成语义分割,为什么要搞得这么麻烦呢,咱又不是专门搞cv的,主业还是规划吹牛逼。

于是我就开始寻找,有没有什么工具,能让我们轻松的调用各种预训练的模型,并且能一键配置环境呢。经过搜索,果然让我找到了。那就是gluoncv这个包,由李沐大神开发,基于亚马逊maxnet框架,基本所有cv的领域它全都包含(比如图像识别、目标检测、语义分割、实例分割和姿态检测等等等等),并且有强大的预训练模型库(他们叫model zoo,十分贴切了)。也就是说,我们用gluoncv调用的模型,是亚马逊在他们的服务器上帮我们训练好的,在测试集上的精度非常高,完成绿视率和天空率的识别绰绰有余。话不多说,让我们这就开始本期的教学。

首先,大家需要到gluoncv的官网 https://gluon-cv.mxnet.io/install.html 上找到这个安装页面:

然后按提示找到合适的安装命令,比如我是mac用户,我想安装稳定版本的最正常的gluoncv,就可以输入

代码语言:javascript
复制
pip install --upgrade mxnet gluoncv

这行命令,即可安装,windows同理。(实际上,gluoncv的tutorial写的非常好,本篇文章实际上也只是重复了一下tutorial而已。

安装好之后,我们就可以打开jupyter notebook啦。首先调包:

代码语言:javascript
复制
import mxnet as mx
from mxnet import image
import gluoncv
import matplotlib.pyplot as plt
from gluoncv.data.transforms.presets.segmentation import test_transform
from gluoncv.utils.viz import get_color_pallete,plot_image
import matplotlib.image as mpimg
import numpy as np
# using cpu
ctx = mx.cpu()

这里我们要测试的图片是下面这张,我在百度上随便找的成都的街景:

首先读取文件:

代码语言:javascript
复制
img = image.imread('cd2.jpg')

然后将文件转化一下:

代码语言:javascript
复制
img = test_transform(img,ctx)

再然后调用模型,这里我调用了backbone为resnet101的DeeplabV3模型,训练集为cityscapes,实际上有基于不同训练集(比如cityscapes和ade20k)训练的很多模型可以选择,大家可以根据需要来选 https://gluon-cv.mxnet.io/model_zoo/segmentation.html :

代码语言:javascript
复制
model1 = gluoncv.model_zoo.get_model('deeplab_resnet101_citys', pretrained=True)

然后开始预测:

代码语言:javascript
复制
output = model1.predict(img)
predict = mx.nd.squeeze(mx.nd.argmax(output, 1)).asnumpy()

这时上语义分割已经完成了,我们可以看到predict是一个二维矩阵:

其中每一个元素就代表一个像素点,元素的值代表像素的分类,有了这个信息就可以计算绿视率与天空率了。在cityscapes训练集中,vegetation 的label是8,sky的label是10。因此,我们通过以下代码便可计算出绿视率与天空率。

代码语言:javascript
复制
green = (predict==8)
print('绿视率为:',str(len(predict[green])/(predict.shape[0]*predict.shape[1])))
代码语言:javascript
复制
sky = (predict==10)
print('天空率为:',str(len(predict[sky])/(predict.shape[0]*predict.shape[1])))

这就计算出来了,不过眼见为实,下面让我们来可视化一下:

代码语言:javascript
复制
mask = get_color_pallete(predict, 'citys')
base = mpimg.imread('cd2.jpg')
plt.figure(figsize=(10,5))
plt.imshow(base)
plt.imshow(mask,alpha=0.5)
plt.axis('off')
#plt.savefig('cd2_deeplab_citys.jpg',dpi=150,bbox_inches='tight')

可以看到,结果还不错,不过左下角的公交车有一部分被识别成了建筑

运用同样的方法,我们可以测试一下在ade20k训练集上训练的同样的模型,在这张图片上的表现:

代码语言:javascript
复制
model2 = gluoncv.model_zoo.get_model('deeplab_resnet101_ade', pretrained=True)
output = model2.predict(img)
predict = mx.nd.squeeze(mx.nd.argmax(output, 1)).asnumpy()
mask = get_color_pallete(predict, 'ade20k')
green = (predict==4)
print('绿视率为:',str(len(predict[green])/(predict.shape[0]*predict.shape[1])))
sky = (predict==2)
print('天空率为:',str(len(predict[sky])/(predict.shape[0]*predict.shape[1])))

天空率跟第一个模型几乎一样,但绿视率稍小一些。

我们可视化一下,找找原因:

代码语言:javascript
复制
base = mpimg.imread('cd2.jpg')
plt.figure(figsize=(10,5))
plt.imshow(base)
plt.imshow(mask,alpha=0.5)
plt.axis('off')
plt.savefig('cd2_deeplab_ade.jpg',dpi=150,bbox_inches='tight')

可以看到,ade20k和cityscapes训练出来的模型还是有细微的差别,比如ade20k准确的识别出了左下角的公交车,而cityscapes翻车了,但cityscapes成功识别了右边建筑房顶的树木,而ade20k没有。大家可以根据自己项目/论文的需求自行选择合适的训练集训练的模型。

然后我在百度街景上随便截了一张图:

用同样的方法看一下效果

cityscapes:

ade20k:

效果整体上都还可以,有细微的差别,可以说是各有千秋吧。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-09-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DataCharm 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档